64

如何过滤具有数组字段且具有 N 个以上元素的文档?

如何过滤具有空数组字段的文档?

方面是解决方案吗?如果是这样,怎么做?

4

10 回答 10

64

我会看看脚本过滤器。以下过滤器应仅返回字段中至少包含 10 个元素的文档,该fieldname字段是一个数组。请记住,这可能会很昂贵,具体取决于您的索引中有多少文档。

"filter" : {
    "script" : {
        "script" : "doc['fieldname'].values.length > 10"
    }
}

关于第二个问题:你那里真的有一个空数组吗?或者它只是一个没有值的数组字段?您可以使用缺少的过滤器来获取对特定字段没有值的文档:

"filter" : {
    "missing" : { "field" : "user" }
}

否则我猜你需要再次使用脚本,类似于我上面建议的,只是输入不同的长度。如果长度是恒定的,我会将它放在params部分中,以便脚本将被 elasticsearch 缓存并重用,因为它总是相同的:

"filter" : {
    "script" : {
        "script" : "doc['fieldname'].values.length > params.param1"
        "params" : {
            "param1" : 10
        }
    }
}
于 2013-03-21T13:25:23.097 回答
17

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/en/elasticsearch/reference/1.4/modules-scripting.html

于 2016-02-09T17:42:46.320 回答
8

仍然在这里发布与我相同情况的人。假设您的数据如下所示:

{
    "_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一样。

于 2017-05-14T07:33:44.490 回答
6

恕我直言,使用脚本按大小过滤数组的正确方法是:

"filter" : {
    "script" : {
        "script" : "_source.fieldName.size() > 1"
    }
}

如果我按照@javanna 的建议那样做,它会抛出异常groovy.lang.MissingPropertyException: No such property: length for class: java.lang.String

于 2015-05-25T09:29:13.453 回答
5

如果您有一组未映射为的对象nested,请记住 Elastic 会将它们展平为:

attachments: [{size: 123}, {size: 456}] --> attachments.size: [123, 456]

因此,您希望将您的字段引用为doc['attachments.size'].length,而不是doc['attachments'].length,这是非常违反直觉的。

doc.containsKey(attachments.size).

.values部分已弃用,不再需要。

于 2019-08-26T22:59:14.183 回答
4

基于此: 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"
    }
}
于 2015-05-27T11:16:33.637 回答
3

最简单的方法是“非规范化”您的数据,以便您拥有一个包含计数和布尔值(如果存在或不存在)的属性。然后你可以搜索这些属性。

例如:

{
   "id": 31939,
   "hasAttachments": true,
   "attachmentCount": 2,
   "attachments": [
      {
         "type": "Attachment",
         "name": "txt.txt",
         "mimeType": "text/plain"
      },
      {
         "type": "Inline",
         "name": "jpg.jpg",
         "mimeType": "image/jpeg"
      }
   ]  
}
于 2016-05-04T03:24:40.607 回答
0

当您需要查找包含某个大小/长度应大于零的字段的文档时,@javanna给出了正确答案。我只想添加如果您的字段是文本字段并且您想查找包含该字段中某些文本的文档,您不能使用相同的查询。您将需要执行以下操作:

GET index/_search 
{
    "query": {
        "bool": {
            "must": [
                {
                    "range": {
                        "FIELD_NAME": {
                            "gt": 0
                        }
                    }
                }
            ]
        }
    }
}

这不是这个问题的确切答案,因为答案已经存在,但是我遇到了类似问题的解决方案,所以也许有人会发现它很有用。

于 2019-01-16T08:53:31.247 回答
0

关于第二个问题的建议:

如何过滤具有空数组字段的文档?

{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "fieldname"
        }
      }
    }
  }
}

将返回带有空fieldname: []数组的文档。must(而不是must_not会返回相反的)。

于 2021-01-19T10:26:46.040 回答
-1

这对我有用:

GET index/search {
    "query": {
       "bool": {
          "filter" : {
             "script" : {
                "script" : "doc['FieldName'].length > 10"
                }
            }
         }
       }
}
于 2022-01-06T17:05:04.270 回答