web-dev-qa-db-ja.com

Elasticsearch配列mustおよびmust_not

私のelasticsearchDBには、次のようなドキュメントがあります。

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

次の基準でドキュメントをフィルタリングできるようにしたいと思います。ドキュメントタグ配列にはtags-1、tags-3、tags-2が必要ですが、tags-Aは含まれていません。

ブールフィルターを使おうとしましたが、うまくいきません!

10
user2854544

これがあなたが望むことを達成しているように見える方法です: http://sense.qbox.io/Gist/4dd806936f12a9668d61ce63f39cb2c28451244

まず、明示的なマッピングを使用してインデックスを作成しました。これを行ったのは、"tags"プロパティを"index": "not_analyzed"に設定できるようにするためです。これは、テキストが変更されないことを意味します。これにより、この例のクエリプロセスが簡素化されます。

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

次に、いくつかのドキュメントを追加します。

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"
}'

次に、次のように、mustフィルターでbool句とmust_not句を使用してクエリを実行できます。

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"
                      }
                  }
               ]
            }
         }
      }
   }
}'

これにより、正しい結果が得られます。

{
   "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"
            }
         }
      ]
   }
}

terms句のmustフィルターの"execution" : "and"パラメーターに注意してください。これは、すべての"tags"が指定されているドキュメントのみが返されることを意味します(1つ以上に一致するドキュメントではありません)。それはあなたが欠けていたものだったかもしれません。オプションの詳細については、 ES docs を参照してください。

ESがインストールされてlocalhost:9200で実行されている場合、または独自のエンドポイントを提供できる場合は、実行可能な例 ここ を作成しました。

15
Sloan Ahrens