2017-08-31 3 views
0

ES Die Daten werden wie folgt indiziert:Elastic Suchabfrage für Mehrwertige Daten

{ 
    "addresses" : [ 
       { 
       "id" : 69, 
       "location": "New Delhi" 
       }, 
       { 
       "id" : 69, 
       "location": "Mumbai" 
       } 
      ], 
    "goods" : [ 
      { 
      "id" : 396, 
      "name" : "abc", 
      "price" : 12500 
      }, 
      { 
      "id" : 167, 
      "name" : "XYz", 
      "price" : 12000 
      }, 
      { 
      "id" : 168, 
      "name" : "XYz1", 
      "price" : 11000 
      }, 
      { 
      "id" : 169, 
      "name" : "XYz2", 
      "price" : 13000 
      } 
     ] 
     } 

In meiner Anfrage ich Aufzeichnungen holen wollen, die an-mindestens eine der Adresse abgestimmt und Warenpreisspanne zwischen 11.000 haben sollte und 13000 und Name xyz.

+0

Ich würde vorschlagen, dass Sie die [Bool Abfrage] (https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html), [Bereich Abfrage] (https://www.elastic.co/guide/en/elasticsearch/reference/5.5/query-dsl-range-query.html) und [match] (https://www.elastic.co/guide/en/ elasticsearch/reference/5.5/query-dsl-match-query.html) oder [term query] (https://www.elastic.co/guide/en/elasticsearch/reference/5.5/query-dsl-term-query. html) – dshockley

+0

was hast du bisher probiert? – Mysterion

Antwort

0

Wenn Ihre Daten Arrays komplexer Objekte wie eine Liste von Adressen oder eine Liste von Waren enthalten, möchten Sie wahrscheinlich die Objekte nested von elasticsearch betrachten, um Probleme zu vermeiden, wenn Ihre Abfragen mehr Elemente ergeben, als Sie erwarten würden .

Das Problem hier ist die Art, wie elasticsearch (und in der Tat Lucene) die Daten speichert. Da es kein solches Konzept von Listen verschachtelter Objekte direkt gibt, sind die Daten abgeflacht und die Verbindung zwischen z.B. XYz und 12000 ist verloren. So würden Sie auch dieses Dokument als Ergebnis erhalten, wenn Sie für XYz und 12500 abfragen, da der Preis von 12500 auch dort in der Liste der Werte für goods.price ist. Um dies zu vermeiden, können Sie die Objektfunktion nested von elasticsearch verwenden, die im Grunde alle inneren Objekte in einen versteckten Index extrahiert und die Abfrage mehrerer Felder ermöglicht, die in einem bestimmten Objekt statt "in einem der Objekte" vorkommen. Für weitere Details, werfen Sie einen Blick auf the docs on nested objects, die auch das ziemlich gut erklärt.

In Ihrem Fall könnte ein Mapping wie folgt aussehen. Ich gehe davon aus, dass Sie nur nach dem addresses.location Text suchen möchten, ohne die ID anzugeben, damit diese Liste der einfache Objekttyp bleiben kann, anstatt auch ein verschachtelter Typ zu sein. Außerdem nehme ich an, dass Sie nach genauen Übereinstimmungen fragen. Ist dies nicht der Fall ist, müssen Sie keyword-text wechseln und die term Abfrage anpassen einige match ein ...

PUT nesting-sample 
{ 
    "mappings": { 
    "item": { 
     "properties": { 
     "addresses": { 
      "properties": { 
      "id": {"type": "integer"}, 
      "location": {"type": "keyword"} 
      } 
     }, 
     "goods": { 
      "type": "nested", 
      "properties": { 
      "id": {"type": "integer"}, 
      "name": {"type": "keyword"}, 
      "price": {"type": "integer"} 
      } 
     } 
     } 
    } 
    } 
} 

Sie dann eine Bool-Abfrage auf der location und einer verschachtelten Abfrage verwenden können, um sein Passen Sie die inneren Dokumente Ihrer goods Liste an.

GET nesting-sample/item/_search 
{ 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "term": { 
      "addresses.location": "New Delhi" 
      } 
     }, 
     { 
      "nested": { 
      "path": "goods", 
      "query": { 
       "bool": { 
       "must": [ 
        { 
        "range": { 
         "goods.price": { 
         "gte": 12200, 
         "lt": 12999 
         } 
        } 
        }, 
        { 
        "term": { 
         "goods.name": { 
         "value": "XYz" 
         } 
        } 
        } 
       ] 
       } 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

Diese Abfrage wird das Dokument nicht überein, da die Preisklasse wie die genaue Bezeichnung des Guten nicht in dem gleichen verschachtelten Objekt ist. Wenn Sie die untere Grenze zu 12000 ändern, wird es übereinstimmen.

Bitte überprüfen Sie Ihren Anwendungsfall und beachten Sie die Warnung unten in der Dokumentation zu the mapping explosion when using nested fields.