Elasticsearch-查询数组中的确切值,以便不返回包含该值和其他值的文档

时间:2018-11-21 10:06:32

标签: elasticsearch

我正在尝试创建一个查询来搜索一个值,该值将仅返回具有该确切值的文档(即使在数组中重复),而不会返回其他文档(即使该值中只有1个条目)数组)。因此,"bar" : [ "A", "A"]是有资格的,但没有"bar" : [ "A", "B"]

数据集示例:

"loren" : [
  {
    "id" : "1", 
    "foo": [{"bar": "A"},{"bar": "A"}]
  },
  {
    "id" : "2", 
    "foo": [{"bar": "A"},{"bar": "B"}]
  },
]

我期望的输出示例:

"hits": {
    "total": 1,
    "max_score": 0.3666863,
    "hits": [
        {
            "_index": "loren",
            "_type": "loren",
            "_id": "2",
            "_score": 0.3666863,
            "_source": {
                "foo": [
                    {
                        "bar": "A"
                    },
                    {
                        "bar": "A"
                    }
                ]
            }
        }
    ]
}

2 个答案:

答案 0 :(得分:1)

您可以根据需要使用以下Script Query

请注意,字段bar的类型应为keyword

POST <your_search_index>/_search
{
  "query": {
        "bool" : {
            "filter" : {
                "script" : {
                    "script" : {
                        "source" : """
                          List myList = doc['bar'];
                          int size = myList.size();
                          int count = Collections.frequency(myList,params.token);
                          if(count==size)
                            return true;
                          """,
                        "lang"   : "painless",
                        "params": {
                          "token": "test"
                        }
                    }
                }
            }
        }
    }
}

您将在响应中得到的是文档列表,其中字段bar仅具有test作为其值。

请注意,如果您的映射是动态创建的,则可以在上述查询中尝试使用bar.keyword

让我知道是否有帮助!

答案 1 :(得分:1)

@Kamal感谢您的启发。这使我得到了我认为的答案...但是让我知道您的想法。

过滤数组时,看起来像做doc['foo.bar'].size();一样,elasticsearch使count(distinct ...)等效于SQL,并为具有n个不同值的数组返回大小n

工作查询示例:

GET /loren/_search 
{
   "_source":[
      "foo.bar"
   ],
   "query":{
      "bool":{
         "must":[
            {
               "match":{
                  "foo.bar":"A"
               }
            }
         ],
         "filter":{
            "script":{
               "script":{
                  "source":"1==doc['foo.bar'].size();",
                  "lang":"painless"
               }
            }
         }
      }
   }
}