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


版权声明:本文为weixin_39974557原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_39974557/article/details/111801912