Здесь нужно рассмотреть несколько проблем.
- Не используйте query_string , если вы точно не знаете, что делаете. Обратите особое внимание, если ввод поступает от пользователя. Вместо этого предпочитайте использовать simple_query_string .
- Я сомневаюсь, что вы хотите, чтобы имя имело тип
keyword
. Этот тип означает, что строка не будет проанализирована (в нижнем регистре, токены и т. Д. c). Так что, если вы ищете что-то, кроме того же самого ввода, то оно не будет совпадать. например, Doug Small
. Можно подумать, что, поскольку вы выполняете поиск с точно таким же вводом, по крайней мере, этот документ вернется, но это не так. Причина в том, что входные данные query_string
или simple_query_string
анализируются (и, как следствие, токенизируются). Если вы не укажете свои данные как один термин, они не будут совпадать. Для этого вам нужно заключить в термин двойные кавычки (" \" Doug Small \ ""). Но если вы сделаете это, вы потеряете все остальные совпадения. - Я считаю, что вам нужно имя и тип, чтобы иметь тип
text
. Это означает, что сохраненная строка будет проанализирована (tokenized, в нижнем регистре и т. Д. c, отметьте простой анализатор (который используется по умолчанию, если вы не указали другой) . - У вас есть оператор указано как
AND
для query_string
. Это означает, что все термины запроса должны совпадать либо по имени, либо по типу. Но вы заявляете, что вам нужно, чтобы все документы возвращались вместе с вашим запросом. Только у одного документа есть оба Doug
и Small
. Если вам это нужно, оператор должен изменить на OR
(по умолчанию).
Полный пример
PUT test
{
"mappings": {
"properties": {
"uid": {
"type": "keyword"
},
"name": {
"type": "text"
},
"type": {
"type": "text"
}
}
}
}
POST test/_bulk
{ "index" : { "_id" : "1" } }
{ "name": "Doug", "type": "Large"}
{ "index" : { "_id" : "2" } }
{ "name": "Doug Small", "type":"Large"}
{ "index" : { "_id" : "3" } }
{ "name": "Smal", "type": "Medium"}
{ "index" : { "_id" : "4" } }
{ "name": "Peter", "type": "Small"}
GET test/_search
{
"query": {
"bool": {
"must": [
{
"simple_query_string": {
"fields": [
"name",
"type"
],
"query": "*Doug Small*",
"default_operator": "OR"
}
}
]
}
}
}
Приведенный выше запрос теперь возвращает все три документа, которые имеют Doug
или Small
или оба. Более того, регистр не учитывается (поскольку он теперь анализируется), поэтому этот *doug small*
даст те же 3 результата.
Поскольку теперь поля анализируются, вам не нужно использовать подстановочный символ, потому что теперь он используется для первого токена и последнего. Значение
*Doug Small*
: сопоставить все, что имеет <ANYTHING>Dog
ИЛИ Small<Anything>
Итак, давайте удалим Подстановочный знак также
GET test/_search
{
"query": {
"bool": {
"must": [
{
"simple_query_string": {
"fields": [
"name",
"type"
],
"query": "Doug Small",
"default_operator": "OR"
}
}
]
}
}
}
Это дает те же самые 3 результата. Вам все еще не хватает Smal
. Теперь вам нужно добавить нечеткое соответствие, чтобы включить это.
GET test/_search
{
"query": {
"bool": {
"must": [
{
"simple_query_string": {
"fields": [
"name",
"type"
],
"query": "Doug Small~",
"default_operator": "OR"
}
}
]
}
}
}
Это Doug Small~
означает, что вы можете принести все, что имеет Doug
ИЛИ Small
, где Small
может быть НЕ точным соответствием ,
Нечеткое совпадение для всех ваших терминов
GET test/_search
{
"query": {
"bool": {
"must": [
{
"simple_query_string": {
"fields": [
"name",
"type"
],
"query": "Dg~ Small~",
"default_operator": "OR"
}
}
]
}
}
}
Причина, по которой Dg
совпадает с Doug
, связана с уровнем нечеткости https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness
Максимально допустимое расстояние редактирования Левенштейна (или количество правок)