Подтвердить что ты не робот

Найти документы с пустой строковой стоимостью на 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"}
            }
        }
    }
}

Ничего из этого не было сделано. Я получаю пустой набор результатов, когда я точно знаю, что есть записи, содержащие пустое поле.

Если кто-нибудь может оказать мне какую-либо помощь, я буду очень благодарен.

Спасибо!

4b9b3361

Ответ 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"
                     }
                }
            }
        }
    }
}

Примечание. Возможно, вам потребуется включить текстовые поля fielddata​​strong > , по умолчанию он отключен. Хотя я бы это прочитал: 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:*)

Ответ 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": "*"
          }
        }
      ]
    }
  }
}