elasticsearch通过作为数组的字段的大小过滤
如何过滤具有一个数组的字段并且包含N个以上元素的文档?
如何过滤具有为空数组的字段的文档?
是解决方案吗? 如果是这样,怎么办?
eran asked 2020-06-23T22:10:24Z
8个解决方案
53 votes
我将看一下脚本过滤器。 以下过滤器应仅返回params字段(包含数组)中至少包含10个元素的文档。 请记住,这可能很昂贵,具体取决于索引中有多少个文档。
“filter” : {
“script” : {
“script” : “doc[‘fieldname’].values.length > 10”
}
}
关于第二个问题:那里真的有一个空数组吗? 还是仅仅是一个没有值的数组字段? 您可以使用缺少的过滤器来获取对特定字段没有价值的文档:
“filter” : {
“missing” : { “field” : “user” }
}
否则,我想您需要再次使用脚本,类似于我上面建议的脚本,只是输入的长度不同。 如果长度是常数,则将其放在params中,以使脚本将被Elasticsearch缓存并重新使用,因为它始终是相同的:
“filter” : {
“script” : {
“script” : “doc[‘fieldname’].values.length > param1”
“params” : {
“param1” : 10
}
}
}
javanna answered 2020-06-23T22:10:42Z
13 votes
javanna的答案在Elasticsearch 1.3.x和更早版本上是正确的,从1.4开始,默认脚本模块已更改为groovy(以前是mvel)。
回答OP的问题。
在Elasticsearch 1.3.x和更早版本上,使用以下代码:
“filter” : {
“script” : {
“script” : “doc[‘fieldname’].values.length > 10”
}
}
在Elasticsearch 1.4.x和更高版本上,使用以下代码:
“filter” : {
“script” : {
“script” : “doc[‘fieldname’].values.size() > 10”
}
}
此外,在Elasticsearch 1.4.3及更高版本上,由于安全问题,您将需要启用动态脚本,因为默认情况下它已被禁用。 参见:[https://www.elastic.co/guide/zh-CN/elasticsearch/reference/1.4/modules-scripting.html]
MicroAleX answered 2020-06-23T22:11:19Z
6 votes
恕我直言,使用脚本按大小过滤数组的正确方法是:
“filter” : {
“script” : {
“script” : “_source.fieldName.size() > 1”
}
}
如果我按照@javanna的建议进行操作,则会引发异常groovy.lang.MissingPropertyException: No such property: length for class: java.lang.String
lisak answered 2020-06-23T22:11:44Z
5 votes
仍然张贴到这里与谁坚持我的情况相同。假设您的数据如下所示:
{
“_source”: {
“fieldName” : [
{
“f1”: “value 11”,
“f2”: “value 21”
},
{
“f1”: “value 12”,
“f2”: “value 22”
}
]
}
}
然后以长度> 1来过滤fieldName,例如:
“query”: {
“bool” : {
“must” : {
“script” : {
“script” : {
“inline”: “doc[‘fieldName.f1’].values.length > 1”,
“lang”: “painless”
}
}
}
}
}
脚本语法作为ES 5.4文档[https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-query.html。]
ThangTD answered 2020-06-23T22:12:12Z
4 votes
基于此:[https://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/collect/RegularImmutableList.java?r=707f3a276d4ea8e9d53621d137febb00cd2128da
并在lisak的答案上。
有size()函数可返回列表的长度:
“filter” : {
“script” : {
“script” : “doc[‘fieldname’].values.size() > 10”
}
}
treku answered 2020-06-23T22:12:41Z
3 votes
最简单的方法是对数据进行“非规范化”,以便您拥有一个包含计数和布尔值(如果存在或不存在)的属性。 然后,您可以仅搜索这些属性。
例如:
{
“id”: 31939,
“hasAttachments”: true,
“attachmentCount”: 2,
“attachments”: [
{
“type”: “Attachment”,
“name”: “txt.txt”,
“mimeType”: “text/plain”
},
{
“type”: “Inline”,
“name”: “jpg.jpg”,
“mimeType”: “image/jpeg”
}
]
}
superlogical answered 2020-06-23T22:13:06Z
0 votes
当您需要查找包含某些字段的文档,该文档的大小/长度应该更大时,则零@javanna给出了正确的答案。 如果您的字段是文本字段,并且您想查找包含该字段中某些文本的文档,那么我只能添加,您不能使用相同的查询。 您将需要执行以下操作:
GET index/_search
{
“query”: {
“bool”: {
“must”: [
{
“range”: {
“FIELD_NAME”: {
“gt”: 0
}
}
}
]
}
}
}
这不是对这个问题的确切答案,因为答案已经存在,但是我已经解决了类似问题,所以也许有人会觉得它有用。
Luka Lopusina answered 2020-06-23T22:13:31Z
0 votes
如果您有未映射为doc[‘attachments.size’].length的对象数组,请记住,Elastic会将其展平为:
attachments: [{size: 123}, {size: 456}] –> attachments.size: [123, 456]
因此,您要将字段引用为doc[‘attachments.size’].length,而不是doc[‘attachments’].length,这非常违反直觉。
与.values相同。
.values部件已弃用,不再需要。
user1306787 answered 2020-06-23T22:14:04Z