Как обрабатывать фразу из одинаковых слов?

Задача сделать поиск с запросом из двух одинаковых слов не равносильным поиску из одного.
То есть, если ищу пор-пор найти клен-клен, а не клен-дуб .

Управлять этим можно с помощью анализаторов и с помощью запросов.
Анализаторами мне это видится сложнее, есть ли комбинация запросов которая будет искать в документе два одинаковых слова, а не одно?

Или есть ли анализатор, которые индексировал клен-клен как {клен-клен, клен клен}, тогда мне не надо менять search анализатор.

Спасибо.

А если пользователь ищет клен-дуб, то поиск должен вернуть клен и где то-там дальше в конце поля дуб?

должен вернуть клен-дуб и только,
но если "клен дуб" то клен и где-то там дуб

Думаю, проще всего будет заменить все - на _ с помощью char_filter.

Но я не понимаю как токенизировать?)

Ну, как-то вот так

DELETE test
PUT test
{
  "settings": {
    "analysis": {
      "char_filter": {
        "replace_dash_char_filter": {
          "type": "mapping",
          "mappings": [
            "- => _"
          ]
        }
      },
      "analyzer": {
        "my_analyzer": {
          "char_filter": [
            "replace_dash_char_filter"
          ],
          "tokenizer": "standard",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "my_analyzer"
        }
      }
    }
  }
}

PUT test/doc/_bulk?refresh
{"index":{"_id":1}}
{"message" : "клен-дуб и грибы"}
{"index":{"_id":2}}
{"message" : "Клен или дуб, вот в чем вопрос"}
{"index":{"_id":3}}
{"message" : "Стоит дуб-дубом, ничего не отвечает"}
{"index":{"_id":4}}
{"message" : "Дуб-дуб это вам не клен и дуб"}

GET test/doc/_search
{
  "query": {
    "match": {
      "message": "клен-дуб"
    }
  }
}

GET test/doc/_search
{
  "query": {
    "match": {
      "message": "дуб-дуб"
    }
  }
}

GET test/doc/_search
{
  "query": {
    "match": {
      "message": "клен дуб"
    }
  }
}

Ага. Спасибо за подробный ответ, я посмотрела и вот не получается, чтобы на запрос клен был и клен-дуб и клен дуб и все где токен клен мог бы быть. Хочу не сужать выдачу , но если пользователь написал правильно через дефис - как оригинальное название, то выдаем только полное совпадение, если написал через пробел, то все, где слова по отдельности.

То есть, может быть в эластик просто добавить функцию, которая с неанализированными полями\токенами работает в первую очередь, атолько если в них нет ответа смотрит в анализированных? Реализовать можно и просто двумя запросами конечно...

Реализовать можно и просто двумя запросами конечно...

Да, я думаю проще одним запросом но по двум полям:

DELETE test
PUT test
{
  "settings": {
    "analysis": {
      "char_filter": {
        "replace_dash_char_filter": {
          "type": "mapping",
          "mappings": [
            "- => _"
          ]
        }
      },
      "analyzer": {
        "my_analyzer": {
          "char_filter": [
            "replace_dash_char_filter"
          ],
          "tokenizer": "standard",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "my_analyzer",
          "fields": {
            "standard": {
              "type": "text",
              "search_analyzer": "my_analyzer", 
              "analyzer": "standard"
            }
          }
        }
      }
    }
  }
}

PUT test/doc/_bulk?refresh
{"index":{"_id":1}}
{"message" : "клен-дуб и грибы"}
{"index":{"_id":2}}
{"message" : "Клен или дуб, вот в чем вопрос"}
{"index":{"_id":3}}
{"message" : "Стоит дуб-дубом, ничего не отвечает"}
{"index":{"_id":4}}
{"message" : "Дуб-дуб это вам не клен и дуб"}

GET test/doc/_search
{
  "query": {
    "multi_match": {
      "query": "клен-дуб",
      "fields": ["message^2", "message.standard"]
    }
  }
}

GET test/doc/_search?explain
{
  "query": {
    "multi_match": {
      "query": "клен",
      "fields": ["message^2", "message.standard"]
    }
  }
}
1 Like

Гениально!

Огромное спасибо)

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