Взвешенная случайная выборка в Elasticsearch

Мне нужно получить случайную выборку из индекса ElasticSearch, т.е. выполнить запрос, который извлекает некоторые документы из заданного индекса со взвешенной вероятностью Wj/ΣWi (где Wj — вес строки j, а Wj/ΣWi — сумма весов всех документов в этом запрос).

В настоящее время у меня есть следующий запрос:

GET products/_search?pretty=true

{"size":5,
  "query": {
    "function_score": {
      "query": {
        "bool":{
          "must": {
            "term":
              {"category_id": "5df3ab90-6e93-0133-7197-04383561729e"}
          }
        }
      },
      "functions":
        [{"random_score":{}}]
    }
  },
  "sort": [{"_score":{"order":"desc"}}]
}

Он возвращает 5 предметов из выбранной категории случайным образом. У каждого элемента есть поле weight. Итак, я, вероятно, должен использовать

"script_score": {
  "script": "weight = data['weight'].value / SUM; if (_score.doubleValue() > weight) {return 1;} else {return 0;}"
}

как описано здесь.

У меня есть следующие проблемы:

  • Каков правильный способ сделать это?
  • Нужно ли включать динамические сценарии?
  • Как посчитать общую сумму запроса?

Спасибо большое за вашу помощь!


person dpaluy    schedule 07.12.2015    source источник


Ответы (2)


Если это кому-то поможет, вот как я недавно реализовал взвешенное перемешивание.

В этом примере мы перемешиваем компании. Каждая компания имеет значение «company_score» в диапазоне от 0 до 100. При такой простой взвешенной перетасовке компания с оценкой 100 в 5 раз чаще появляется на первой странице, чем компания с оценкой 20.

json_body = {
    "sort": ["_score"],
    "query": {
        "function_score": {
            "query": main_query,  # put your main query here
            "functions": [
                {
                    "random_score": {},
                },
                {
                    "field_value_factor": {
                        "field": "company_score",
                        "modifier": "none",
                        "missing": 0,
                    }
                }
            ],
            # How to combine the result of the two functions 'random_score' and 'field_value_factor'.
            # This way, on average the combined _score of a company having score 100 will be 5 times as much
            # as the combined _score of a company having score 20, and thus will be 5 times more likely
            # to appear on first page.
            "score_mode": "multiply",
            # How to combine the result of function_score with the original _score from the query.
            # We overwrite it as our combined _score (random x company_score) is all we need.
            "boost_mode": "replace",
        }
    }
}
person Vermeer Grange    schedule 19.01.2018

Я знаю, что этот вопрос старый, но ответ для любых будущих искателей.

комментарий перед вашим в ветке GitHub, кажется, содержит ответ. Если каждый из ваших документов имеет относительный вес, вы можете выбрать случайную оценку для каждого документа и умножить ее на вес, чтобы создать новую взвешенную случайную оценку. Это имеет дополнительный бонус, заключающийся в том, что не требуется сумма весов.

например если два документа имеют веса 1 и 2, то вы ожидаете, что второй будет иметь в два раза большую вероятность выбора, чем первый. Дайте каждому документу случайную оценку от 0 до 1 (что вы уже делаете с "random_score"). Умножьте случайную оценку на вес, и вы получите первый документ с оценкой от 0 до 1, а второй — с оценкой от 0 до 2, так что вероятность того, что вас выберут, будет в два раза выше!

person Brent Axthelm    schedule 22.02.2017