2014-03-07 6 views
6

Ich habe Probleme beim Kombinieren von Begriff, muss nicht Abfragen auf verschachtelten Dokumenten. http://sense.qbox.io/gist/be436a1ffa01e4630a964f48b2d5b3a1ef5fa176Begriff, verschachtelte Dokumente und muss nicht Abfrage in ElasticSearch inkompatibel sein?

Hier meine Mapping:

{ 
    "mappings": { 
     "docs" : { 
      "properties": { 
       "tags" : { 
        "type": "nested", 
        "properties" : { 
         "type": { 
          "type": "string", 
          "index": "not_analyzed" 
         } 
        } 
       }, 
       "label" : { 
        "type": "string" 
       } 
      } 
     } 
    } 
} 

mit zwei Dokumente in diesem Index:

{ 
    "tags" : [ 
     {"type" : "POST"}, 
     {"type" : "DELETE"} 
    ], 
    "label" : "item 1" 
}, 
{ 
    "tags" : [ 
     {"type" : "POST"} 
    ], 
    "label" : "item 2" 
} 

Wenn ich so abfragen, diesen Index:

Sense Beispiel kann hier gefunden werden

{ 
    "query": { 
    "nested": { 
     "path": "tags", 
     "query": { 
     "bool": { 
      "must": { 
      "term": { 
       "tags.type": "DELETE" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Ich habe einen Treffer erhielt (was richtig ist)

Wenn ich will Dokumente erhalten, die nicht den Tag enthalten "DELETE", mit dieser Abfrage:

{ 
    "query": { 
    "nested": { 
     "path": "tags", 
     "query": { 
     "bool": { 
      "must_not": { 
      "term": { 
       "tags.type": "delete" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

I‘ Habe 2 Treffer (was falsch ist). Dieses Problem scheint sehr ähnlich zu diesem (Elasticsearch array must and must_not) aber es ist nicht ...

Können Sie mir einige Hinweise geben, um dieses Problem zu lösen?

Danke

Antwort

0

Dieses Ihr Problem beheben sollte: http://sense.qbox.io/gist/f4694f542bc76c29624b5b5c9b3ecdee36f7e3ea

Zwei wichtigsten Dinge:

  1. include_in_root auf "tags.type". Dies teilt ES mit, die Tag-Typen als "doc.tags.types" : ['DELETE', 'POSTS'] zu indizieren, damit Sie auf ein Array dieser Werte zugreifen können, die im Root-Dokument "abgeflacht" sind. Das bedeutet, dass Sie keine verschachtelte Abfrage mehr benötigen (siehe Nr. 2)

  2. Löschen Sie die verschachtelte Abfrage.

 

{ 
    "mappings": { 
     "docs" : { 
      "properties": { 
       "tags" : { 
        "type": "nested", 
        "properties" : { 
         "type": { 
          "type": "string", 
          "index": "not_analyzed" 
         } 
        }, 
        "include_in_root": true 
       }, 
       "label" : { 
        "type": "string" 
       } 
      } 
     } 
    } 
} 

 

{ 
    "query": { 
     "bool": { 
     "must_not": { 
      "term": { 
       "tags.type": "DELETE" 
      } 
     } 
     } 
    } 
} 
+0

Danke, es funktioniert. Kannst du erklären, warum du so warst? – user3393203

+0

Einfach weil es ohne "include_in_root" nicht möglich war. Anstatt ein komplexes geschachteltes Filter-/Abfragesystem zu haben, können Sie nun einfach alle "tags.type" als Array behandeln. Auf diese Weise können Sie etwas wie "Geben Sie mir alle Dokumente ohne" DELETE "im Array" Tag-Typen "sagen. Es ist nicht leicht, dieses Zeug manchmal zu verbalisieren, aber hoffentlich macht das Sinn! –

+0

Es funktioniert nicht für mich. Das ist komisch und traurig zugleich. Vielleicht, weil ich 'terms' und' integer' verwende? –

9

Ihre ursprüngliche Abfrage in jedem einzelnen verschachtelten Objekt suchen würde und diese Objekte eliminieren, die nicht einverstanden ist, aber wenn es einige verschachtelten Objekte sind links, stimmen sie Ihrer Anfrage zu und Sie erhalten Ihre Ergebnisse. Dies liegt daran, verschachtelte Objekte indiziert als verstecktes separates Dokument

Originalcode sind:

{ 
    "query": { 
    "nested": { 
     "path": "tags", 
     "query": { 
     "bool": { 
      "must_not": { 
      "term": { 
       "tags.type": "delete" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Die Lösung ist dann eigentlich ganz einfach, sollten Sie die Bool Abfrage außerhalb der verschachtelten Dokumente bringen. Jetzt werden alle Dokumente verworfen, die ein verschachteltes Objekt mit dem Typ "DELETE" haben. Genau was du wolltest!

Die Lösung:

{ 
    "query": { 
    "bool": { 
     "must_not": { 
     "nested": { 
      "path": "tags", 
      "query": { 
      "term": { 
       "tags.type": "DELETE" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

HINWEIS: strings "nicht analysiert" werden und Sie nach "Löschen" anstelle von "DELETE". Wenn Sie nach Groß- und Kleinschreibung suchen möchten, machen Sie Ihre Strings analysiert

+0

Wenn ich es so mache, sind Daten, die kein Feld enthält, nicht im Ergebnis enthalten –

+0

Sind Sie sicher? Welche Elasticsearch Version verwendest du? – rvheddeg

+0

ElasticSearch 2.2.1. Nach der erneuten Überprüfung funktioniert eine große Anzahl von Abfragen in meinem Laptop, aber auf dem Server. Die Elasticsearch-Version spielt möglicherweise eine Rolle. –

Verwandte Themen