2014-01-16 5 views
8

Ich habe ein Dokument wie dies in meiner Elasticsearch DB suchen:Elasticsearch Array muss und must_not

{ 
    "tags" => [ 
     "tag-1", 
     "tag-2", 
     "tag-3", 
     "tag-A" 
    ] 
    "created_at" =>"2013-07-02 12:42:19 UTC", 
    "label" =>"Mon super label" 
} 

ich mit diesen Kriterien meiner Dokumente können filtern möchte: Dokumente Tags Array muss Tags-1 haben , tags-3 und tags-2, aber keine Tags-A.

Ich habe versucht, einen Bool-Filter zu verwenden, aber ich kann es nicht schaffen, es zu arbeiten!

Antwort

13

Dies ist eine Methode, die Sie erreichen wollen scheint: http://sense.qbox.io/gist/4dd806936f12a9668d61ce63f39cb2c284512443

Zuerst habe ich erstellt einen Index mit einer expliziten Mapping. Ich tat dies, damit ich die "tags" Eigenschaft auf "index": "not_analyzed" setzen konnte. Dies bedeutet, dass der Text in keiner Weise geändert wird, was den Abfrageprozess für dieses Beispiel vereinfacht.

curl -XPUT "http://localhost:9200/test_index" -d' 
{ 
    "mappings": { 
     "docs" : { 
      "properties": { 
       "tags" : { 
        "type": "string", 
        "index": "not_analyzed" 
       }, 
       "label" : { 
        "type": "string" 
       } 
      } 
     } 
    } 
}' 

und dann einige Dokumente hinzufügen:

curl -XPUT "http://localhost:9200/test_index/docs/1" -d' 
{ 
    "tags" : [ 
     "tag-1", 
     "tag-2", 
     "tag-3", 
     "tag-A" 
    ], 
    "label" : "item 1" 
}' 
curl -XPUT "http://localhost:9200/test_index/docs/2" -d' 
{ 
    "tags" : [ 
     "tag-1", 
     "tag-2", 
     "tag-3" 
    ], 
    "label" : "item 2" 
}' 
curl -XPUT "http://localhost:9200/test_index/docs/3" -d' 
{ 
    "tags" : [ 
     "tag-1", 
     "tag-2" 
    ], 
    "label" : "item 3" 
}' 

Dann können wir mit must und must_not Klauseln in einem bool Filter Abfrage wie folgt:

curl -XPOST "http://localhost:9200/test_index/_search" -d' 
{ 
    "query": { 
     "filtered": { 
     "query": { 
      "match_all": {} 
     }, 
     "filter": { 
      "bool": { 
       "must": [ 
        { 
        "terms": { 
         "tags": [ 
          "tag-1", 
          "tag-2", 
          "tag-3" 
         ], 
         "execution" : "and" 
        } 
        } 
       ], 
       "must_not": [ 
        { 
         "term": { 
         "tags": "tag-A" 
         } 
        } 
       ] 
      } 
     } 
     } 
    } 
}' 

, die das richtige Ergebnis liefert:

{ 
    "took": 3, 
    "timed_out": false, 
    "_shards": { 
     "total": 2, 
     "successful": 2, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 1, 
     "max_score": 1, 
     "hits": [ 
     { 
      "_index": "test_index", 
      "_type": "docs", 
      "_id": "2", 
      "_score": 1, 
      "_source": { 
       "tags": [ 
        "tag-1", 
        "tag-2", 
        "tag-3" 
       ], 
       "label": "item 2" 
      } 
     } 
     ] 
    } 
} 

Beachten Sie den Parameter "execution" : "and" im Filter terms im Abschnitt must. Dies bedeutet, dass nur Dokumente zurückgegeben werden, die alle angegebenen "tags" aufweisen (und nicht diejenigen, die mit einem oder mehreren übereinstimmen). Das war vielleicht das, was du vermisst hast. Sie können mehr über die Optionen in der ES docs lesen.

Ich machte ein lauffähiges Beispiel here mit dem Sie spielen können, wenn Sie ES installiert haben und unter localhost:9200 laufen, oder Sie können Ihren eigenen Endpunkt bereitstellen.

Verwandte Themen