Порядок слов в полнотекстном поиске

Доброго дня.

Есть такой индекс:

{
    "ta": {
        "mappings": {
            "properties": {
                "address": {
                    "type": "text"
                },
                "obj_id": {
                    "type": "keyword"
                }
            }
        }
    }
}

В него грузятся адреса примерно в формате "Москва г, Центральная ул, дом 7, квартира 15".
Нужно по адресу получать obj_id. Строка для поиска может быть примерно такой
"моск цент 7 15", т.е. пользователь вводит сокращенные данные.

Сейчас поиск выглядит так:

{
"size": 21,    
"query": {
        "bool": {
            "must": [
                {
                    "query_string": {
                        "query": "*моск* *цент* 7 15",
                        "fields": [
                            "address"
                        ]
                    }
                }
            ],
            "must_not": []
        }
    }
}

Полей на самом деле больше и запрос может быть сложнее, поэтому есть секция bool, но сейчас это не важно.
В таком виде запрос вернет адреса:
"Москва г, Центральная ул, дом 7, квартира 15"
"Москва г, Центральная ул, дом 15, квартира 7"

Если ли возможность задать порядок слов при поиске?
Т.е. если я задам
"моск цент 7 15" - возвращается только "Москва г, Центральная ул, дом 7, квартира 15"
"моск цент 15 7" - возвращается только "Москва г, Центральная ул, дом 15, квартира 7"?

Порядок слов учитывается только при поиске фразы. В данном случае нужно запрос заключать в кавычки и использовать параметр phrase_slop

Такой запрос

{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "query": "\"15 7\"",
            "fields": [
              "address"
            ],
            "phrase_slop": 1
          }
        }
      ],
      "must_not": []
    }
  }
}

вернёт только "Москва г, Центральная ул, дом 15, квартира 7"

Если взять в кавычки строку не работает полнотекстность.
Например

"\"*моск* *цент* 7 15\""

уже не работает.
Как это побороть?

wildcard в match_phrase не работает.
Поэтому можно искать так:

{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "query": "\"москва Центральная 7 15\"",
            "fields": [
              "address"
            ],
            "phrase_slop": 4
          }
        }
      ],
      "must_not": []
    }
  }
}

или

{
  "query": {
    "bool": {
      "must": [
        {
          "match_phrase": {
            "address": {
              "query": "москва Центральная 7 15",
              "slop": 4
            }
          }
        }
      ],
      "must_not": []
    }
  }
}

но для большего контроля лучше использовать Span near query

{
  "query": {
    "bool": {
      "must": [
        {
          "span_near": {
            "clauses": [
              {
                "span_multi": {
                  "match": {
                    "wildcard": {
                      "address": {
                        "value": "*моск*"
                      }
                    }
                  }
                }
              },
              {
                "span_multi": {
                  "match": {
                    "wildcard": {
                      "address": {
                        "value": "*цент*"
                      }
                    }
                  }
                }
              },
              {
                "span_term": {
                  "address": "7"
                }
              },
              {
                "span_term": {
                  "address": "15"
                }
              }
            ],
            "slop": 4,
            "in_order": true
          }
        }
      ],
      "must_not": []
    }
  }
}

Но я перед индексацией разбирал бы адрес на составляющие (город, улица, дом и т.д.) и помещал все в соответствующие поля. Тогда запросы делать было легче.

Спасибо, попробую.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.