ElasticSearch - повышение оценки с помощью сценариев - PullRequest
0 голосов
/ 10 июля 2019

У нас есть конкретный вариант использования для нашего экземпляра ElasticSearch: мы храним документы, которые содержат собственные имена, даты рождения, адреса, идентификационные номера и другую связанную информацию.

Мы используем плагин для сопоставления имен, который переопределяет оценку ES по умолчанию и назначает оценку релевантности от 0 до 1 в зависимости от того, насколько близко совпадает имя.

Что нам нужно сделать, это увеличить этот счет на определенную величину, если другие поля совпадают. Я начал читать на ES сценариев, чтобы достичь этого. Мне нужна помощь в части сценария запроса. Прямо сейчас наш запрос выглядит так:

{  
   "size":100,
   "query":{  
      "bool":{  
         "should":[  
            {"match":{"Name":"John Smith"}}
            ]
         }
   },
   "rescore":{  
         "window_size":100,
         "query":{  
            "rescore_query":{  
               "function_score":{  
                  "doc_score":{  
                     "fields":{
                       "Name":{"query_value":"John Smith"},
                       "DOB":{
                        "function":{
                            "function_score":{
                                "script_score":{
                                    "script":{
                                        "lang":"painless",
                                        "params":{
                                            "query_value":"01-01-1999"
                                                 },
                               "inline":"if **<HERE'S WHERE I NEED ASSISTANCE>**"
                             }
                           }
                         }
                       }
                     }
                   }
                 }
               }
             },
             "query_weight":0.0,
             "rescore_query_weight":1.0
           }
         }

Поле Name всегда будет требоваться в запросе и является основой для оценки, которая возвращается в поле _score по умолчанию; для простоты демонстрации мы просто добавим еще одно поле, DOB, которое в случае совпадения должно повысить оценку на 0,1. Я считаю, что я ищу что-то вроде if(query_value == doc['DOB'].value add 0.1 to _score) или что-то вроде этого.

Итак, какой будет правильным синтаксисом, который будет введен в строку inline для достижения этой цели? Или, если запрос требует другого пересмотра синтаксиса, пожалуйста, сообщите.

РЕДАКТИРОВАТЬ # 1 - важно подчеркнуть, что наше поле DOB является полем text, а не date.

Ответы [ 2 ]

1 голос
/ 11 июля 2019

Разделение на отдельный ответ, так как это решает проблему по-разному (т. Е. С использованием script_score в качестве предложенного OP вместо попытки переписать сценарии).

При условии, что отображение и данные совпадают с предыдущим ответом , версия запроса в виде сценария может выглядеть следующим образом:

POST /employee/_search
{
  "size": 100,
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "Name": "John"
          }
        },
        {
          "match": {
            "Name": "Will"
          }
        }
      ]
    }
  },
  "rescore": {
    "window_size": 100,
    "query": {
      "rescore_query": {
        "function_score": {
          "query": {
            "bool": {
              "should": [
                {
                  "match": {
                    "Name": "John"
                  }
                },
                {
                  "match": {
                    "Name": "Will"
                  }
                }
              ]
            }
          },
          "functions": [
            {
              "script_score": {
                "script": {
                  "source": "double boost = 0.0; if (params['_source']['State'] == 'FL') { boost += 0.1; } if (params['_source']['DOB'] == '1965-05-24') { boost += 0.3; } return boost;",
                  "lang": "painless"
                }
              }
            }
          ],
          "score_mode": "sum",
          "boost_mode": "sum"
        }
      },
      "query_weight": 0,
      "rescore_query_weight": 1
    }
  }
}

Две заметки о скрипте:

  1. Сценарий использует params['_source'][field_name] для доступа к документу, что является единственным способом получить доступ к текстовым полям. Это значительно медленнее, поскольку требует доступа к документам непосредственно на диске, хотя это может быть не слишком плохо в контексте восстановления. Вместо этого вы можете использовать doc[field_name].value, если поле имеет тип агрегируемого типа, например keyword, date или что-то числовое
  2. DOB здесь сравнивается непосредственно со строкой. Это возможно, потому что мы используем поле _source, а JSON для документов имеет даты, указанные в виде строк. Это несколько хрупко, но, вероятно, сработает
1 голос
/ 10 июля 2019

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

  1. Составляет запросы для дополнительных полей в предложении should для основной оценки функции query (т. Е. Будет производить оценки только для документов, соответствующих хотя бы одному дополнительному полю)
  2. Использует одну функцию для каждого дополнительного поля, с filter, установленным для выбора документов с некоторым значением для этого поля, и weight, чтобы указать, насколько должен увеличиваться счет (или какой-либо другой оценочной функцией, если необходимо)

Отображение (как шаблон)

Добавление поля State и DOB для примера (убедившись, что несколько дополнительных полей вносят корректный вклад в счет)

PUT _template/employee_template
{
  "index_patterns": ["employee"],
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "_doc": {
      "properties": {
        "Name": {
          "type": "text"
        },
        "State": {
          "type": "keyword"
        },
        "DOB": {
          "type": "date"
        }
      }
    }
  }
}

Пример данных

POST /employee/_doc/_bulk
{"index":{}}
{"Name": "John Smith", "State": "NY", "DOB": "1970-01-01"}
{"index":{}}
{"Name": "John C. Reilly", "State": "CA", "DOB": "1965-05-24"}
{"index":{}}
{"Name": "Will Ferrell", "State": "FL", "DOB": "1967-07-16"}

Запрос

РЕДАКТИРОВАТЬ: Обновлен запрос для включения исходного запроса в новую оценку функции в попытке компенсировать пользовательские плагины скоринга.

Несколько замечаний по поводу запроса ниже:

  • Установка восстановителей score_mode: max - это, по сути, replace, поскольку вновь вычисленная функциональная оценка должна быть только больше или равна исходной оценке
  • query_weight и rescore_query_weight установлены на 1, так что они сравниваются в равных масштабах во время score_mode: max сравнения
  • В запросе function_score:
    • score_mode: sum сложит все оценки из functions
    • boost_mode: sum добавит сумму functions к баллу query
POST /employee/_search
{
  "size": 100,
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "Name": "John"
          }
        },
        {
          "match": {
            "Name": "Will"
          }
        }
      ]
    }
  },
  "rescore": {
    "window_size": 100,
    "query": {
      "rescore_query": {
        "function_score": {
          "query": {
            "bool": {
              "should": [
                {
                  "match": {
                    "Name": "John"
                  }
                },
                {
                  "match": {
                    "Name": "Will"
                  }
                }
              ],
              "filter": {
                "bool": {
                  "should": [
                    {
                      "term": {
                        "State": "CA"
                      }
                    },
                    {
                      "range": {
                        "DOB": {
                          "lte": "1968-01-01"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "functions": [
            {
              "filter": {
                "term": {
                  "State": "CA"
                }
              },
              "weight": 0.1
            },
            {
              "filter": {
                "range": {
                  "DOB": {
                    "lte": "1968-01-01"
                  }
                }
              },
              "weight": 0.3
            }
          ],
          "score_mode": "sum",
          "boost_mode": "sum"
        }
      },
      "score_mode": "max",
      "query_weight": 1,
      "rescore_query_weight": 1
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...