17

我正在寻找一种在弹性搜索中进行精确数组匹配的方法。假设这些是我的文件:

{"id": 1, "categories" : ["c", "d"]}
{"id": 2, "categories" : ["b", "c", "d"]}
{"id": 3, "categories" : ["c", "d", "e"]}
{"id": 4, "categories" : ["d"]}
{"id": 5, "categories" : ["c", "d"]}

有没有办法搜索所有具有“c”和“d”类别(文档 1 和 5)的文档,不多也不少

作为奖励:搜索“其中一个”类别应该仍然是可能的(例如,您可以搜索“c”并获得 1、2、3 和 5)

有什么聪明的方法来解决这个问题吗?

4

2 回答 2

19

如果您有一组离散的已知类别,则可以使用 bool 查询:

"bool" : {
    "must" : {
        "terms" : { "categories" : ["c", "d"],
             minimum_should_match : 2
         }
    },
    "must_not" : {
        "terms" : { "categories" : ["a", "b", "e"],
             minimum_should_match : 1
         }
    }
}

否则,我认为完成此任务的最简单方法可能是存储另一个字段作为类别关键字。

{"id": 1, "categories" : ["c", "d"], "categorieskey" : "cd"}

类似的东西。然后,您可以轻松地使用术语查询精确地查询您想要的结果,例如:

term { "categorieskey" : "cd" }

而且您仍然可以进行非排他性搜索,例如;

term { "categories" : "c" }

查询必须同时存在的两个类别很容易,但要阻止任何其他潜在类别存在则有点困难。你可以做到,也许。您可能想要编写一个查询来查找两者的记录,然后对其应用过滤器,以消除除指定类别之外的任何记录。据我所知,这并不是 Lucene 真正设计用来处理的一种搜索。

老实说,我在想出一个在这里使用的好过滤器时遇到了一些麻烦。您可能需要一个脚本过滤器,或者您可以在检索到结果后对其进行过滤。

于 2012-10-01T16:38:17.620 回答
1

我为我们的用例找到了一个似乎可行的解决方案。它依赖于两个过滤器和我们想要匹配多少类别的知识。我们使用术语过滤器和脚本过滤器来检查数组的大小。在此示例中,marketBasketList 类似于您的类别条目。

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "siteId": 4
          }
        },
        {
          "match": {
            "marketBasketList": {
              "query": [
                10,
                11
              ],
              "operator": "and"
            }
          }
        }
      ]
    },
    "boost": 1,
    "filter": {
      "and": {
        "filters": [
          {
            "script": {
              "script": "doc['marketBasketList'].values.length == 2"
            }
          },
          {
            "terms": {
              "marketBasketList": [
                10,
                11
              ],
              "execution": "and"
            }
          }
        ]
      }
    }
  }
}
于 2013-03-21T14:44:33.793 回答