Elasticsearch 匹配完整的术语数组
Elasticsearch match complete array of terms
我需要用 elasticsearch 匹配完整的词组。
只应返回具有包含相同元素的数组的文档。
文档数组中不应有更多元素或元素子集。
元素的顺序无关紧要。
示例:
filter:
id: ["a", "b"]
documents:
id: ["a", "b"] -> match
id: ["b", "a"] -> match
id: ["a"] -> no match
id: ["a", "b", "c"] -> no match
最终我想使用 Java 高级 REST 客户端来实现查询,尽管 elasticsearch dsl 的示例也可以。
虽然这似乎不受本地支持,但您可以继续使用脚本过滤器来实现此行为,如下所示:
GET your_index/_search
{
"query": {
"bool": {
"must": [
{
"script": {
"script": "doc['tags'].values.length == 2"
}
},
{
"term": {
"tags": {
"value": "a"
}
}
},
{
"term": {
"tags": {
"value": "b"
}
}
}
]
}
}
}
脚本过滤器通过数组大小限制搜索结果,而术语过滤器指定该数组的值。确保在标签 字段 上启用 fielddata 以便在其上执行脚本。
我想提出一些建议,一旦您的要求发生变化(例如,假设您有一个包含六个项目的数组要匹配),将阻止您维护一长串 "must" 条件。我将依赖脚本查询,它可能看起来设计过度,但可以很容易地从中创建搜索模板 (https://www.elastic.co/guide/en/elasticsearch/reference/7.5/search-template.html)。
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"source": """
def ids = new ArrayList(doc['id.keyword']);
def param = new ArrayList(params.terms);
def isSameSize = ids.size() == param.size();
def isSameContent = ids.containsAll(param);
return isSameSize && isSameContent
""",
"lang": "painless",
"params": {
"terms": [ "a", "b" ]
}
}
}
}
}
}
}
这样,您唯一需要更改的是 terms
参数的值。
我需要用 elasticsearch 匹配完整的词组。 只应返回具有包含相同元素的数组的文档。 文档数组中不应有更多元素或元素子集。 元素的顺序无关紧要。
示例:
filter:
id: ["a", "b"]
documents:
id: ["a", "b"] -> match
id: ["b", "a"] -> match
id: ["a"] -> no match
id: ["a", "b", "c"] -> no match
最终我想使用 Java 高级 REST 客户端来实现查询,尽管 elasticsearch dsl 的示例也可以。
虽然这似乎不受本地支持,但您可以继续使用脚本过滤器来实现此行为,如下所示:
GET your_index/_search
{
"query": {
"bool": {
"must": [
{
"script": {
"script": "doc['tags'].values.length == 2"
}
},
{
"term": {
"tags": {
"value": "a"
}
}
},
{
"term": {
"tags": {
"value": "b"
}
}
}
]
}
}
}
脚本过滤器通过数组大小限制搜索结果,而术语过滤器指定该数组的值。确保在标签 字段 上启用 fielddata 以便在其上执行脚本。
我想提出一些建议,一旦您的要求发生变化(例如,假设您有一个包含六个项目的数组要匹配),将阻止您维护一长串 "must" 条件。我将依赖脚本查询,它可能看起来设计过度,但可以很容易地从中创建搜索模板 (https://www.elastic.co/guide/en/elasticsearch/reference/7.5/search-template.html)。
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"source": """
def ids = new ArrayList(doc['id.keyword']);
def param = new ArrayList(params.terms);
def isSameSize = ids.size() == param.size();
def isSameContent = ids.containsAll(param);
return isSameSize && isSameContent
""",
"lang": "painless",
"params": {
"terms": [ "a", "b" ]
}
}
}
}
}
}
}
这样,您唯一需要更改的是 terms
参数的值。