Найти документы с пустой строковой стоимостью на elasticsearch
Я пытаюсь фильтровать с помощью elasticsearch только те документы, которые содержат пустую строку в своем теле. Пока мне не повезло.
Прежде чем продолжить, я должен упомянуть, что я уже пробовал решения many ", распространяющиеся по Interwebz и StackOverflow.
Итак, ниже приведен запрос, который я пытаюсь запустить, а затем его копии:
{
"query": {
"filtered":{
"filter": {
"bool": {
"must_not": [
{
"missing":{
"field":"_textContent"
}
}
]
}
}
}
}
}
Я также пробовал следующее:
{
"query": {
"filtered":{
"filter": {
"bool": {
"must_not": [
{
"missing":{
"field":"_textContent",
"existence":true,
"null_value":true
}
}
]
}
}
}
}
}
И следующее:
{
"query": {
"filtered":{
"filter": {
"missing": {"field": "_textContent"}
}
}
}
}
Ничего из этого не было сделано. Я получаю пустой набор результатов, когда я точно знаю, что есть записи, содержащие пустое поле.
Если кто-нибудь может оказать мне какую-либо помощь, я буду очень благодарен.
Спасибо!
Ответы
Ответ 1
Если вы используете анализатор по умолчанию (standard
), анализировать его нечего, если это пустая строка. Поэтому необходимо дословно проиндексировать поле (не анализировать). Вот пример:
Добавьте отображение, которое будет индексировать поле без маркеров, если вам нужна также индексированная копия индексированного поля, вы можете использовать тип Multi Field.
PUT http://localhost:9200/test/_mapping/demo
{
"demo": {
"properties": {
"_content": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
Далее индексируйте пару документов.
/POST http://localhost:9200/test/demo/1/
{
"_content": ""
}
/POST http://localhost:9200/test/demo/2
{
"_content": "some content"
}
Выполнить поиск:
POST http://localhost:9200/test/demo/_search
{
"query": {
"filtered": {
"filter": {
"term": {
"_content": ""
}
}
}
}
}
Возвращает документ с пустой строкой.
{
took: 2,
timed_out: false,
_shards: {
total: 5,
successful: 5,
failed: 0
},
hits: {
total: 1,
max_score: 0.30685282,
hits: [
{
_index: test,
_type: demo,
_id: 1,
_score: 0.30685282,
_source: {
_content: ""
}
}
]
}
}
Ответ 2
Даже с помощью анализатора по умолчанию вы можете выполнить такой поиск: используйте script filter, который медленнее, но может обрабатывать пустая строка:
curl -XPOST 'http://localhost:9200/test/demo/_search' -d '
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "_source._content.length() == 0"
}
}
}
}
}'
Он вернет документ с пустой строкой как _content без специального сопоставления
Как указано @js_gandalf, это устарело для ES > 5.0. Вместо этого вы должны использовать: query- > bool- > filter → script, как в https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
Ответ 3
Для тех из вас, кто использует эластичный поиск 5.2 или выше, и все еще застревает. Самый простой способ - правильно перевести ваши данные с типом ключевого слова. Затем все поиски пустых значений сработали. Вот так:
"query": {
"term": {"MY_FIELD_TO_SEARCH": ""}
}
Собственно, когда я переиндексирую мою базу данных и повторно запускаю запрос. Он работал =)
Проблема заключалась в том, что мое поле было типом: text и NOT ключевым словом. Изменен индекс для ключевого слова и переиндексирован:
curl -X PUT https://username:[email protected]:9200/mycoolindex
curl -X PUT https://user:[email protected]:9200/mycoolindex/_mapping/mycooltype -d '{
"properties": {
"MY_FIELD_TO_SEARCH": {
"type": "keyword"
},
}'
curl -X PUT https://username:[email protected]:9200/_reindex -d '{
"source": {
"index": "oldindex"
},
"dest": {
"index": "mycoolindex"
}
}'
Я надеюсь, что это поможет кому-то, кто был застрял, когда я нашел эти пустые значения.
Ответ 4
чтобы найти пустую строку одного поля в вашем документе, она очень актуальна для сопоставления полей, другими словами, ее установкой index
/analyzer
.
Если его индекс not_analyzed
, это означает, что токен - это просто пустая строка, вы можете просто использовать запрос term
, чтобы найти его, как показано ниже:
{"from": 0, "size": 100, "query":{"term": {"name":""}}}
В противном случае, если параметр index
равен analyzed
, и я считаю, что большинство анализаторов будут обрабатывать пустую строку как нулевое значение So
вы можете использовать фильтр, чтобы найти пустую строку.
{"filter": {"missing": {"existence": true, "field": "name", "null_value": true}}, "query": {"match_all": {}}}
вот суть script вы можете ссылаться: https://gist.github.com/hxuanji/35b982b86b3601cb5571
Кстати, я проверю команды, которые вы предоставили, кажется, вы НЕ хотите пустой пустой документ.
И все мои вышеприведенные команды - это просто найти их, поэтому просто вставьте must_not
часть запроса bool
.
Моя ES 1.0.1.
Для ES 1.3.0 в настоящий момент я не могу найти пустую строку. Похоже, что было сообщено: https://github.com/elasticsearch/elasticsearch/issues/7348. Подождите и посмотрите, как это происходит.
В любом случае, он также предоставляет другую команду для поиска
{ "query": { "отфильтрован": { "filter": { "не": { "filter": { "ассортимент": { "имя": { } } } } } }}}
name
- это имя поля для поиска пустой строки. Я тестировал его на ES 1.3.2.
Ответ 5
Я использую Elasticsearch 5.3 и испытываю проблемы с некоторыми из приведенных выше ответов.
Для меня работал следующий орган.
{
"query": {
"bool" : {
"must" : {
"script" : {
"script" : {
"inline": "doc['city'].empty",
"lang": "painless"
}
}
}
}
}
}
Примечание. Возможно, вам потребуется включить текстовые поля fielddatastrong > , по умолчанию он отключен. Хотя я бы это прочитал: https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html, прежде чем делать это.
Чтобы включить полевые данные для поля, например. "city" в индексе "business" с типом "запись" вам нужно:
PUT business/_mapping/record
{
"properties": {
"city": {
"type": "text",
"fielddata": true
}
}
}
Ответ 6
Для вложенных полей используйте:
curl -XGET "http://localhost:9200/city/_search?pretty=true" -d '{
"query" : {
"nested" : {
"path" : "country",
"score_mode" : "avg",
"query" : {
"bool": {
"must_not": {
"exists": {
"field": "country.name"
}
}
}
}
}
}
}'
ПРИМЕЧАНИЕ: путь и поле вместе составляют для поиска. Измените, как вам нужно, чтобы работать.
Для регулярных полей:
curl -XGET 'http://localhost:9200/city/_search?pretty=true' -d'{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "name"
}
}
}
}
}'
Ответ 7
Мне не удалось найти пустые строки в текстовом поле. Однако, похоже, он работает с полем типа ключевого слова. Поэтому я предлагаю следующее:
delete /test_idx
put test_idx
{
"mappings" : {
"testMapping": {
"properties" : {
"tag" : {"type":"text"},
"content" : {"type":"text",
"fields" : {
"x" : {"type" : "keyword"}
}
}
}
}
}
}
put /test_idx/testMapping/1
{
"tag": "null"
}
put /test_idx/testMapping/2
{
"tag": "empty",
"content": ""
}
GET /test_idx/testMapping/_search
{
"query" : {
"match" : {"content.x" : ""}}}
}
}
Ответ 8
Вам нужно запустить индексатор ключевых слов, добавив .content к имени вашего поля. В зависимости от того, как был настроен исходный индекс, следующее "просто работает" для меня с помощью AWS ElasticSearch v6.x.
GET/my_idx/_search?q=my_field.content: ""
Ответ 9
Если вы не хотите или не можете переиндексировать, есть другой способ. :-)
Вы можете использовать оператор отрицания и подстановочный знак для сопоставления с любой непустой строкой *
GET /my_index/_search?q=!(fieldToLookFor:*)
Ответ 10
ИЛИ используя синтаксис строки запроса Lucene
д = (yourfield.keyword: "!")
См. Elastic Search Reference https://www.elastic.co/guide/en/elasticsearch/reference/6.5/query-dsl-query-string-query.html#query-string-syntax
Ответ 11
Нашел решение здесь https://github.com/elastic/elasticsearch/issues/7515 Работает без переиндексации.
PUT t/t/1
{
"textContent": ""
}
PUT t/t/2
{
"textContent": "foo"
}
GET t/t/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "textContent"
}
}
],
"must_not": [
{
"wildcard": {
"textContent": "*"
}
}
]
}
}
}