Получить правильную релевантность для поиска многозначных полей - PullRequest
0 голосов
/ 30 мая 2018

У меня есть объект, который может иметь произвольное количество заголовков.В некоторых случаях существует несколько десятков и даже сотен заголовков на одну сущность.

Эти заголовки хранятся в эластичном поиске в одном поле в виде массива.У поля есть комплексный анализатор со сложным токенизатором.

Проблема состоит в том, что эластик рассматривает поле массива (поле с набором значений) как твую «строку», а релевантность результатов поиска вычисляется какполная релевантность по всей «строке».Но мне нужна релевантность одного конкретного элемента сопоставленного массива.

Ниже приведен очень упрощенный пример.

Создание индекса

curl -XDELETE 'http://localhost:9200/tests'
curl -XPUT 'http://localhost:9200/tests' -d'{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "type": "custom",
          "tokenizer": "edge_ngram_tokenizer",
          "filter": ["lowercase", "asciifolding"]
        }
      },
      "tokenizer": {
        "edge_ngram_tokenizer": {
          "type": "edgeNGram",
          "min_gram": "3",
          "max_gram": "12",
          "token_chars": ["letter", "digit"]
        }
      }
    }
  },
  "mappings": {
    "test": {
      "properties": {
        "name": {
          "type": "string",
          "analyzer": "my_analyzer"
        }
      }
    }
  }
}'

Заполнение индекса

curl -XPOST 'http://localhost:9200/tests/test' -d'{ "id": 1, "name": ["text"] }'
curl -XPOST 'http://localhost:9200/tests/test' -d'{ "id": 2, "name": ["text", "text"] }'

Поиск

curl -XGET 'http://localhost:9200/tests/test/_search' -d'{
  "query": {
    "match": {
      "name": "text"
    }
  }
}'

Результаты

{
  "took": 0,
  "timed_out": false,
  "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 },
  "hits": {
    "total": 2,
    "max_score": 0.7911257,
    "hits": [{
      "_index": "tests",
      "_type": "test",
      "_id": "AWOtIL2gdpqdbX7hdDXg",
      "_score": 0.7911257,
      "_source": { "id": 2, "name": [ "text", "text" ] }
    }, {
      "_index": "tests",
      "_type": "test",
      "_id": "AWOtIL0ldpqdbX7hdDXf",
      "_score": 0.51623213,
      "_source": { "id": 1, "name": [ "text" ] }
    }]
  }
}

Как видите, id: 2 имеет отношение 0.7911257 , и id: 1 имеет отношение 0.51623213 .

Мне нужны оба результата, чтобы иметь одинаковую релевантность.

Есть ли способ достичь этого?

Я знаю два решения проблемы, но оба меня не устраивают.Возможно, есть другие варианты?

a) Когда количество заголовков относительно мало, заголовки могут быть сохранены в отдельном поле: name_0, name_1, name_2 и т. Д. Эти поля могут быть запросами с использованием dis_max запрос с tie_breaker: 0 и релевантность будет хорошей.

"query": {
  "dis_max": {
    "queries": [
      { "match": { "name_0": "text" } },
      { "match": { "name_1": "text" } },
      { "match": { "name_2": "text" } }
    ],
    "tie_breaker": 0,
    "boost": 1
  }
}

b) Каждый заголовок может храниться в эластичном виде в отдельной строке

curl -XPOST 'http://localhost:9200/tests/test' -d'{ "product_id": 1, "name": "text" }'
curl -XPOST 'http://localhost:9200/tests/test' -d'{ "product_id": 2, "name": "text" }'
curl -XPOST 'http://localhost:9200/tests/test' -d'{ "product_id": 2, "name": "text" }'

В этом случае результаты должны быть дополнительно агрегированы по product_id.Таким образом, мы получаем проблемы с разбиением на страницы результатов и дальнейшей агрегацией результатов.

1 Ответ

0 голосов
/ 30 мая 2018

Я думаю, что добавление к вашему name полю:

"index_options": "docs"

сотворит магию.

Этот параметр скажет ES, что все равноо TF этого поля.

Отметьте Теория актуальности , если вы хотите узнать больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...