2015-07-01 10 views
6

Unsere REST-API ermöglicht es Benutzern, benutzerdefinierten schemaligen JSON zu einigen unserer REST-Ressourcen hinzuzufügen, und wir müssen sie in Elasticsearch durchsuchen können. Diese benutzerdefinierten Daten und ihre Struktur können in Ressourcen desselben Typs völlig unterschiedlich sein.Schematische Unterstützung für elastische Suchabfragen

Betrachten Sie dieses Beispiel Dokument:

{ 
    "givenName": "Joe", 
    "username": "joe", 
    "email": "[email protected]", 
    "customData": { 
    "favoriteColor": "red", 
    "someObject": { 
     "someKey": "someValue" 
    } 
    } 
} 

Alle Felder außer customData ein Schema einzuhalten. customData ist immer ein JSON-Objekt, aber alle Felder und Werte in diesem Objekt können von Ressource zu Ressource stark variieren. Es gibt keine Garantie dafür, dass ein bestimmter Feldname oder -wert (oder sogar ein Werttyp) innerhalb von customData für zwei Ressourcen identisch ist, da Benutzer diese Felder beliebig bearbeiten können.

Was ist der beste Weg, um die Suche nach diesem zu unterstützen?

Wir dachten, eine Lösung wäre, nur kein Mapping für customData zu erstellen, wenn der Index erstellt wird, aber dann wird es unqueryable (was im Gegensatz zu dem ES docs say ist). Dies wäre die ideale Lösung, wenn Abfragen für nicht zugeordnete Eigenschaften ausgeführt werden und bei diesem Ansatz keine Leistungsprobleme auftreten. Nachdem wir mehrere Tests durchgeführt hatten, konnten wir dies jedoch nicht zum Laufen bringen.

Ist das etwas, das spezielle Konfiguration benötigt? Oder sind die Dokumente falsch? Etwas Klärung, warum es nicht funktioniert, würde sehr geschätzt werden.

Da dies derzeit nicht für uns arbeiten, haben wir von ein paar alternativen Lösungen gedacht:

  1. Reindizieren: dies kostspielig sein würde, wie wir jeden Index indizieren müssten, die dieses Dokument enthält und tun also jedes Mal, wenn ein Benutzer eine Eigenschaft mit einem anderen Werttyp aktualisiert. Wirklich schlecht für die Leistung, also ist dies wahrscheinlich keine echte Option.

  2. Verwenden Sie multi-match query: Wir würden dies tun, indem Sie dem customData-Feldnamen jedes Mal eine zufällige Zeichenfolge anhängen, wenn eine Änderung im customData-Objekt erfolgt. Zum Beispiel ist es das, was das Dokument aussehen würde indiziert:

    { 
        "givenName": "Joe", 
        "username": "joe", 
        "email": "[email protected]", 
        "customData_03ae8b95-2496-4c8d-9330-6d2058b1bbb9": { 
        "favoriteColor": "red", 
        "someObject": { 
         "someKey": "someValue" 
        } 
        } 
    } 
    

    a „mit der Verwendung beginnt eine neue Zuordnung für jedes‚zufällig‘Feld, und wir würden ES würde erstellen Dies bedeutet, verwenden Satz Multi-match-Abfrage "Platzhalter für die Feldnamen beim Ausführen der Abfragen. Zum Beispiel:

    curl -XPOST 'eshost:9200/test/_search?pretty' -d ' 
    { 
        "query": { 
        "multi_match": { 
         "query" : "red", 
         "type" : "phrase", 
         "fields" : ["customData_*.favoriteColor"] 
        } 
        } 
    }' 
    

    Dies könnte eine praktikable Lösung sein, aber wir sind besorgt, dass wie diese zu viele Abbildungen, die Leistung beeinträchtigen könnte. Gibt es Leistungseinbußen für zu viele Zuordnungen zu einem Index? Vielleicht könnte die periodische Neuindizierung zu viele Zuordnungen verringern?

    Dies fühlt sich auch einfach wie ein Hack und etwas, das von ES nativ behandelt werden sollte. Fehle ich etwas?

Irgendwelche Vorschläge über irgendwelche davon würden sehr geschätzt.

Danke!

Antwort

0

Felder mit gleicher Zuordnung werden als dasselbe Lucene-Feld im Lucene-Index (Elasticsearch shard) gespeichert.Verschiedene Lucene-Felder haben einen separaten invertierten Index (Term-Dict und Index-Eintrag) und separate Doc-Werte. Lucene ist stark optimiert, um Dokumente desselben Feldes komprimiert zu speichern. Die Verwendung eines Mappings mit einem anderen Feld für ein anderes Dokument verhindert, dass Lucene seine Optimierung durchführt.

Sie sollten Elasticsearch Nested Document zur effizienten Suche verwenden. Die zugrunde liegende Technologie ist Lucene BlockJoin, die Eltern-/Kinddokumente als Dokumentenblock indiziert.

+0

Sie sagen, dass verschachteltes Dokument die beschriebene nicht-deterministische Natur des 'customData' Objekts behandeln kann? –

2

Sie haben Recht, dass Elasticsearch nicht wirklich schemaless ist. Wenn keine Zuordnung angegeben ist, leitet Elasticsearch Feldtyp-Primitive basierend auf dem ersten Wert, den es für dieses Feld sieht, ein. Daher kann Ihr nicht-deterministisches customData-Objekt Sie in Schwierigkeiten bringen, wenn Sie zuerst "favoriteColor": 10 gefolgt von "favoriteColor": "red" sehen.

Für Ihre Anforderungen, können Sie einen Blick auf SIREn Solutions Elasticsearch plugin nehmen sollen, die eine schemaless Lösung bietet mit einer erweiterten Abfragesprache gekoppelt (mit Zweig) und ein Format benutzerdefinierten Lucene-Index nicht-deterministisch Daten zu beschleunigen Indizierung und Suchoperationen für .

+0

Danke für den Kommentar Peter - wir werden es ausprobieren und die Antwort geben, wenn es wie erwartet funktioniert. –