ElasticSearch - script_score с вложенными в фильтры не влияет на оценки - почему? - PullRequest
2 голосов
/ 09 июля 2020

Используемые свойства:

{
 "mappings": {
   "properties": {
     "attribute_must_1": {
       "type": "nested"
     },
     "attribute_1": {
       "type": "nested"
     },
     "attribute_2": {
       "type": "nested"
     },
   }
 }

}

Входные документы для тестирования:

POST _bulk
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":9},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":9},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":8},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":7},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":11},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":5},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":10},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":6},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":7},"attribute_2":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":1},"attribute_1":{"id":7},"attribute_2":{"id":3}}

Фактический запрос:

q = {
    "size": 10,
    "query": {
        "function_score": {
            "query": {
    "bool": {
      "filter": [
      ],
      "must": [
        {
          "nested": {
            "path": "attribute_must_1",
            "query": {
              "term": {
                "attribute_must_1.id": "1"
              }
            }
          }
        }
      ]
    }
  },
  "boost": 1,
  "functions": [
    {
      "filter": {
        "nested": {
          "path": "attribute_1",
          "query": {
              "script_score": {
                "query": {
                      "match_all": {}
                  },
                  "script": {
                      "source": "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['attribute_1.id'].value)",
                      "params": {
                          "origin": 10,
                          "scale": 5,
                          "decay": 2,
                          "offset": 0
                      }
                  }
              }
          },
        }
      },
      "weight": 30
    },
    {"filter": {"nested": {"path": "attribute_2", "query": {"term": {"attribute_2.id": "3"}}}}, "weight": 70},

  ],
  "score_mode": "sum",
  "boost_mode": "replace"
 }
},
"sort": [
  "_score",
   {
     "date_deposit": {
     "order": "desc"
   }
   }
   ]
  }

Я пытаюсь добавить новый фильтр с вложенным полем "attribute_1", где я хочу вычислить расстояние между фактическим значением и значением из всех других документов, но это не влияет на оценки, которые я вижу:

для атрибута_1 найденного:

документов = [9, 9, 9, 10, 9, 9, 4, 9, 3, 9]

Я получаю (сумма 30% и 70 % весов из 2 атрибутов):

оценки = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100]

, поэтому он кажется довольно двоичным, хотя должен быть каким-то образом линейной функцией. Что я хочу примерно так:

для найденных значений документов: [10, 9, 8, 3, 10] и входное значение 10 -> Я хотел бы иметь:

оценки (скажем, в процентах): [100%, 90%, 80%, 30%, 100%]

Я хотел бы получить простой результат в диапазоне от 0 до 100%, но включая частичные оценки по нескольким атрибутам (attribute_1, attribute_2, ...) таким образом, что:

  • оценка из attribute_1 в линейной оценке на основе расстояния (т.е. любое значение от 0% до 30%)
  • оценка по атрибуту_2 составляет 0% или 70% (запрос термина)

Я пробовал разные варианты, но ничего не работает - как правильно это сделать? У меня такое впечатление, что запрос filter не может каким-то образом выполнить script_scores ...

Надеюсь, кто-нибудь может мне с этим помочь? Огромный THNX!

Ответы [ 2 ]

1 голос
/ 07 августа 2020

Я пробовал разные варианты, но ничего не работает - как правильно это сделать? У меня сложилось впечатление, что фильтрующий запрос каким-то образом не может делать script_scores ...

Да, вы правы. Как упоминалось в документации - «В контексте фильтра предложение запроса отвечает на вопрос« Соответствует ли этот документ этому предложению запроса? » Ответ прост: да или нет - баллы не рассчитываются . Контекст фильтра в основном используется для фильтрации структурированных данных, например, «

. Я рекомендую вам не использовать фильтр в запросах, которые требуют быть оцененным.

0 голосов
/ 05 августа 2020

Я не уверен, в чем разница между attribute_must_1 и attribute_1 в вашем примере. Но, сделав шаг назад, элементарный расчет процентного отношения может быть осуществлен гораздо проще:

Настройка вложенного сопоставления:

PUT scores
{
  "mappings": {
    "properties": {
      "attribute_must_1": {
        "type": "nested"
      }
    }
  }
}

Syn c образцы документов ([9, 9, 9, 10, 9, 9, 4, 9, 3, 9] ):

POST _bulk
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":10}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":4}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":3}}
{"index":{"_index":"scores","_type":"_doc"}}
{"attribute_must_1":{"id":9}}

Используйте запрос оценки скрипта вычитающей функции:

GET scores/_search
{
  "query": {
    "nested": {
      "path": "attribute_must_1",
      "query": {
        "function_score": {
          "query": {
            "match_all": {}
          },
          "script_score": {
            "script": {
              "source": "((float)doc['attribute_must_1.id'].value / params.origin) * 100",
              "params": {
                "origin": 10.0
              }
            }
          },
          "boost_mode": "replace"
        }
      }
    }
  }
}

Проверьте оценки:

[
  {
    "_score":100.0,
    "_source":{
      "attribute_must_1":{
        "id":10
      }
    }
  },
  {
    "_score":90.0,
    "_source":{
      "attribute_must_1":{
        "id":9
      }
    }
  },
  ...
  {
    "_score":40.0,
    "_source":{
      "attribute_must_1":{
        "id":4
      }
    }
  },
  {
    "_score":30.0,
    "_source":{
      "attribute_must_1":{
        "id":3
      }
    }
  }
]
...