Как я могу фильтровать документы, у которых есть поле, которое является массивом, и имеет более N элементов?
Как я могу фильтровать документы, у которых есть поле, которое является пустым массивом?
Является ли грани решением? Если да, то как?
Как я могу фильтровать документы, у которых есть поле, которое является массивом, и имеет более N элементов?
Как я могу фильтровать документы, у которых есть поле, которое является пустым массивом?
Является ли грани решением? Если да, то как?
Я бы посмотрел на script фильтр. Следующий фильтр должен возвращать только документы, в которых есть не менее 10 элементов в поле fieldname
, которое представляет собой массив. Имейте в виду, что это может быть дорогостоящим в зависимости от того, сколько документов у вас есть в вашем индексе.
"filter" : {
"script" : {
"script" : "doc['fieldname'].values.length > 10"
}
}
Относительно второго вопроса: у вас действительно есть пустой массив? Или это просто поле массива без значения? Вы можете использовать отсутствующий фильтр для получения документов, которые не имеют значения для определенного поля:
"filter" : {
"missing" : { "field" : "user" }
}
В противном случае, я думаю, вам нужно снова использовать скрипты, аналогично тому, что я предложил выше, только с другой длиной в качестве входных данных. Если длина является постоянной, я бы поместил ее в раздел params
, чтобы script был кэширован elasticsearch и повторно использован, так как он всегда один и тот же:
"filter" : {
"script" : {
"script" : "doc['fieldname'].values.length > param1"
"params" : {
"param1" : 10
}
}
}
Ответ 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
Imho правильный способ фильтрации массивов по размеру с использованием сценариев:
"filter" : {
"script" : {
"script" : "_source.fieldName.size() > 1"
}
}
Если я это сделаю, как @javanna предлагает исключение groovy.lang.MissingPropertyException: No such property: length for class: java.lang.String
Все еще отправляю сюда для того, кто застрял в той же ситуации со мной. Допустим, ваши данные выглядят так:
{
"_source": {
"fieldName" : [
{
"f1": "value 11",
"f2": "value 21"
},
{
"f1": "value 12",
"f2": "value 22"
}
]
}
}
Затем отфильтровать fieldName
с длиной> 1, например:
"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.
И на лизак ответьте здесь.
Существует функция size(), которая возвращает длину списка:
"filter" : {
"script" : {
"script" : "doc['fieldname'].values.size() > 10"
}
}
Самый простой способ сделать это - "денормализовать" ваши данные, чтобы у вас было свойство, которое содержит счетчик и логическое, если оно существует или нет. Затем вы можете просто выполнить поиск по этим свойствам.
Например:
{
"id": 31939,
"hasAttachments": true,
"attachmentCount": 2,
"attachments": [
{
"type": "Attachment",
"name": "txt.txt",
"mimeType": "text/plain"
},
{
"type": "Inline",
"name": "jpg.jpg",
"mimeType": "image/jpeg"
}
]
}
Когда вам нужно найти документы, которые содержат какое-то поле, размер/длина которого должен быть больше нуля, @javanna дала правильный ответ. Я только хотел добавить, если ваше поле является текстовым полем, и вы хотите найти документы, которые содержат некоторый текст в этом поле, вы не можете использовать тот же запрос. Вам нужно будет сделать что-то вроде этого:
GET index/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"FIELD_NAME": {
"gt": 0
}
}
}
]
}
}
}
Это не точный ответ на этот вопрос, потому что ответ уже существует, но решение для аналогичной проблемы, которое у меня было, так что, возможно, кто-то найдет его полезным.
Если у вас есть массив объектов, которые не сопоставлены с nested
, имейте в виду, что Elastic упростит их в:
attachments: [{size: 123}, {size: 456}] --> attachments.size: [123, 456]
Итак, вы хотите сослаться на свое поле как doc['attachments.size'].length
, а не doc['attachments'].length
, что очень нелогично.
То же самое для doc.containsKey(attachments.size)
.
Часть .values
устарела и больше не нужна.