ElasticSearch с фильтром через asticutils
В настоящее время я пытаюсь использовать filter
в существующем экземпляре ElasticSearch через библиотеку elasticutils
, К сожалению, я ничего не получаю. Я не уверен, что проблема в том, что я сделал что-то не так или в библиотеке есть проблема (вполне может быть, AFAICT).
У меня есть индекс с определенным отображением, содержащий поле (скажем, "A") типа string (без явного анализатора). Это поле всегда содержит список строк.
Я хотел бы отфильтровать документы, содержащие заданную строку в этом поле A, поэтому я попытался:
import elasticutils as eu
es = eu.S().es(urls=[ URL ]).indexes(INDEX).doctypes(DOCTYPE)
f = eu.F(A="text")
result = es.filter(f)
Но это возвращает пустой набор результатов. Я тоже пробовал это используя f = eu.F(A__in="text")
но это привело к большому сообщению об ошибке, самая интригующая часть которого была [terms] filter does not support [A]
,
Мне интересно, если я должен настроить свой индекс по-другому, может быть, мне нужно создать фасет, чтобы иметь возможность использовать фильтр? Но я не нашел намека на это в документации, которую прочитал.
Моя причина желания использовать filter
является то, что они могут свободно комбинироваться с помощью and
, or
, а также not
, Я также нашел некоторые спецификации, описывающие, что query
также может быть логическим, но они обычно относятся к must
, should
, а также must_not
которые не достаточно гибки для меня, я думаю. Но я также нашел некоторые спецификации, которые упоминали operator
флаг для query
s, которые можно установить на and
или же or
, Любая информация об этом приветствуется.
Итак, мои вопросы сейчас:
- Это проблема конфигурации? Есть ли у фасетов какое-то отношение к этому?
- Я хотел бы проверить, является ли это ошибкой библиотеки, пропустив библиотеку, так как я могу выполнить это действие фильтрации, используя, скажем, curl? Или любая другая библиотека (может быть
pyes
)? - Является гибким сочетанием (используя
and
,or
,not
и возможна ли их группировка по нескольким запросам (т.е. вообще без использования фильтров)? Как бы я это сделал? (Желательно вelasticutils
но другие библиотечные синтаксисы, напримерpyes
или простые CURL также приветствуются).
2 ответа
airza ударил по голове своим ответом в виде фильтра, который вы ищете, в формате CURL. Я подозреваю, что проблемы, которые вы видите, в основном связаны с использованием модуля абстракции, такого как elasticutils
- было бы хорошо сначала ознакомиться с базовым протоколом запросов ES. Это сделает понимание elasticutils
Полегче. Как и в моем комментарии выше, я рекомендую установить Sense, плагин для Google Chrome, который позволит вам легко запрашивать кластер ES: https://chrome.google.com/webstore/detail/sense/doinijnbnggojdlcjifpdckfokbbfpbo?hl=en.
Фильтры запросов Elasticsearch чрезвычайно гибкие и "встраиваемые". Вы можете довольно легко вложить or
фильтр внутри bool
must
фильтр. Пример:
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"or": [
{"exists": {"field": "sessions"}},
{"range": {"id": {"gte": 56000}}}
]
},
{
"term": {"age_min": "13"}
}
],
"should": [
{
"term": {"area": "1"}
}
]
}
}
}
}
}
В этом примере результаты должны соответствовать одному из двух must
or
фильтры и тому age_min
term
фильтр и элементы, соответствующие area
term
фильтр в should
пункт будет выше, чем несоответствующие элементы.
Запрос CURL для решения этой проблемы довольно прост:
curl -XPOST URL/INDEX/_search? -d '{
"filter": {
"term": {
"A": "val"
}
}
}'
Здесь нет особой связи с фасетами (это тип поискового запроса, который используется для получения размера различных подмножеств другого запроса), но если поле A не проиндексировано, вы не сможете его найти и что-нибудь найти. ОДНАКО, если это так, ваш запрос ES должен просто возвращать любые записи (поскольку, когда вы запрашиваете неиндексированное поле, вы, по сути, не даете ES никаких особых инструкций по фильтрации).
Запрос, выдвинутый моей попыткой выполнить эквивалентный поиск ES с использованием этой библиотеки, был следующим:
{'filter': {'term': {'language': 'EN'}
То, что вы видите, совпадает с тем, которое вы запускали. Что случилось, когда вы вызвали result.all()?