Как получить сумму похожих тегов из текста в эластичном поиске

Я пытаюсь использовать Elastic Search (версия 6.8), чтобы найти наиболее похожие теги из текста, и я ожидаю получить сумму оценок похожих тегов вместо расчета эластичного поиска по умолчанию (формула).

Например, я создаю my_test_index и вставляю три документа:

POST my_test_index/_doc/17
{
  "id": 17,
  "tags": ["devops", "server", "hardware"]
}

POST my_test_index/_doc/20
{
  "id": 20,
  "tags": ["software", "application", "developer", "develop"]
}

POST my_test_index/_doc/21
{
  "id": 21,
  "tags": ["electronic", "electric"]
}

Сопоставления нет, оно по умолчанию, как показано ниже:

{
  "my_test_index" : {
    "aliases" : { },
    "mappings" : {
      "_doc" : {
        "properties" : {
          "id" : {
            "type" : "long"
          },
          "tags" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1585820383702",
        "number_of_shards" : "5",
        "number_of_replicas" : "1",
        "uuid" : "05SgLog6S-GTSShTatrvQw",
        "version" : {
          "created" : "6080199"
        },
        "provided_name" : "my_test_index"
      }
    }
  }
}

Итак, я запрашиваю ниже запрос:

GET my_test_index/_search
{
  "query": {
    "more_like_this": {
      "fields": [
        "tags"
      ],
      "like": [
        "i like electric devices and develop some softwares."
      ],
      "min_term_freq": 1,
      "min_doc_freq": 1
    }
  }
}

И получить такой ответ:

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "my_test_index",
        "_type" : "_doc",
        "_id" : "21",
        "_score" : 0.2876821,
        "_source" : {
          "id" : 21,
          "tags" : [
            "electronic",
            "electric"
          ]
        }
      },
      {
        "_index" : "my_test_index",
        "_type" : "_doc",
        "_id" : "20",
        "_score" : 0.2876821,
        "_source" : {
          "id" : 20,
          "tags" : [
            "software",
            "application",
            "developer",
            "develop"
          ]
        }
      }
    ]
  }
}

Если я установлю объяснение: true, результат будет следующим:

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_shard" : "[my_test_index][1]",
        "_node" : "maQL1REnQHaff51ekrqMxA",
        "_index" : "my_test_index",
        "_type" : "_doc",
        "_id" : "21",
        "_score" : 0.2876821,
        "_source" : {
          "id" : 21,
          "tags" : [
            "electronic",
            "electric"
          ]
        },
        "_explanation" : {
          "value" : 0.2876821,
          "description" : "weight(tags:electric in 0) [PerFieldSimilarity], result of:",
          "details" : [
            {
              "value" : 0.2876821,
              "description" : "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:",
              "details" : [
                {
                  "value" : 0.2876821,
                  "description" : "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
                  "details" : [
                    {
                      "value" : 1.0,
                      "description" : "docFreq",
                      "details" : [ ]
                    },
                    {
                      "value" : 1.0,
                      "description" : "docCount",
                      "details" : [ ]
                    }
                  ]
                },
                {
                  "value" : 1.0,
                  "description" : "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",
                  "details" : [
                    {
                      "value" : 1.0,
                      "description" : "termFreq=1.0",
                      "details" : [ ]
                    },
                    {
                      "value" : 1.2,
                      "description" : "parameter k1",
                      "details" : [ ]
                    },
                    {
                      "value" : 0.75,
                      "description" : "parameter b",
                      "details" : [ ]
                    },
                    {
                      "value" : 2.0,
                      "description" : "avgFieldLength",
                      "details" : [ ]
                    },
                    {
                      "value" : 2.0,
                      "description" : "fieldLength",
                      "details" : [ ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      {
        "_shard" : "[my_test_index][2]",
        "_node" : "maQL1REnQHaff51ekrqMxA",
        "_index" : "my_test_index",
        "_type" : "_doc",
        "_id" : "20",
        "_score" : 0.2876821,
        "_source" : {
          "id" : 20,
          "tags" : [
            "software",
            "application",
            "developer",
            "develop"
          ]
        },
        "_explanation" : {
          "value" : 0.2876821,
          "description" : "weight(tags:develop in 0) [PerFieldSimilarity], result of:",
          "details" : [
            {
              "value" : 0.2876821,
              "description" : "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:",
              "details" : [
                {
                  "value" : 0.2876821,
                  "description" : "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:",
                  "details" : [
                    {
                      "value" : 1.0,
                      "description" : "docFreq",
                      "details" : [ ]
                    },
                    {
                      "value" : 1.0,
                      "description" : "docCount",
                      "details" : [ ]
                    }
                  ]
                },
                {
                  "value" : 1.0,
                  "description" : "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:",
                  "details" : [
                    {
                      "value" : 1.0,
                      "description" : "termFreq=1.0",
                      "details" : [ ]
                    },
                    {
                      "value" : 1.2,
                      "description" : "parameter k1",
                      "details" : [ ]
                    },
                    {
                      "value" : 0.75,
                      "description" : "parameter b",
                      "details" : [ ]
                    },
                    {
                      "value" : 4.0,
                      "description" : "avgFieldLength",
                      "details" : [ ]
                    },
                    {
                      "value" : 4.0,
                      "description" : "fieldLength",
                      "details" : [ ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

Но для меня это неподходящий результат, я хочу рассчитать сумму баллов похожих тегов, как показано ниже: У меня есть слово «electric» в тексте и тегах и равно «electric ", он получает 1,0 балла, а по аналогии с тегом "electrical" он получает ~0,7 балла. И слово «develop» в тексте и тегах, равное тегу «develop», получает 1,0 балла, сходство с тегом «developer», он получает ~0,8 балла и сходство с "программным обеспечением" он получает ~0,9 балла и так далее...

Итак, я ожидаю, что этот результат ==> сумма баллов _id: 20 = ~ 2,7, _id: 21 = ~ 1,7 и ....

Я надеялся, что кто-то может привести пример того, как это сделать, или, по крайней мере, указать мне правильное направление.

Спасибо.


person ali reza    schedule 02.04.2020    source источник
comment
Спасибо за предоставление большей части информации, если вы можете просто добавить отображение, я могу быстро воспроизвести и дать ответ   -  person user156327    schedule 02.04.2020
comment
@OpsterElasticsearchNinja Нет сопоставления, это значение по умолчанию.   -  person ali reza    schedule 02.04.2020
comment
Не уверен, почему в вашем результате оба идентификатора имеют одинаковую оценку, я попытался создать собственное сопоставление для тегов с полем text и идентификатором 21, как и ожидалось, с более высокой оценкой, чем 20   -  person user156327    schedule 02.04.2020


Ответы (1)


Я думаю, что вы не используете поле text для поля tags в своем сопоставлении, из-за чего оба идентификатора 20 и 21 имеют одинаковую оценку, я определил его как text в своем сопоставлении и получил высокий балл для идентификатора 21, что и ожидалось.

ниже мое решение.

Определение индекса

{
    "mappings": {
        "properties": {
            "id": {
                "type": "integer"
            },
            "tags" : {
                "type" : "text" --> note this
            }
        }
    }
}

Проиндексированы предоставленные вами образцы документов с использованием того же поискового запроса.

Поисковый запрос

{
  "query": {
    "more_like_this": {
      "fields": [
        "tags"
      ],
      "like": [
        "i like electric devices and develop some softwares."
      ],
      "min_term_freq": 1,
      "min_doc_freq": 1
    }
  }
}

Результат поиска

 "hits": [
         {
            "_index": "so_array",
            "_type": "_doc",
            "_id": "3",
            "_score": 1.135697, --> note score
            "_source": {
               "id": 21,
               "tags": [
                  "electronic",
                  "electric"
               ]
            }
         },
         {
            "_index": "so_array",
            "_type": "_doc",
            "_id": "2",
            "_score": 0.86312973, --> note score
            "_source": {
               "id": 20,
               "tags": [
                  "software",
                  "application",
                  "developer",
                  "develop"
               ]
            }
         }
      ]
person user156327    schedule 02.04.2020
comment
я отредактировал свой пост и добавил настройки сопоставления, я ничего не менял, спасибо - person ali reza; 02.04.2020
comment
какая версия ЕС? - person user156327; 02.04.2020
comment
Я написал в своем посте, версия 6.8 - person ali reza; 02.04.2020
comment
@alireza, извините, я использовал 7.6, и для меня он дал другую оценку, и даже ES 6.8 использовал BM25, поэтому не уверен, почему существует разница - person user156327; 02.04.2020
comment
я добавил объяснение: правда в свой запрос и добавил в свой пост, вы можете увидеть детали результата, спасибо. - person ali reza; 02.04.2020