Запрос оценки функции с field_value_factor для (еще) не существующего поля

Я довольно долго возился с этой проблемой и не могу решить ее.

Возьмем следующий случай:

В моей компании есть 2 сотрудника, у которых есть собственная страница в блоге:

POST blog/page/1
{
  "author": "Byron",
  "author-title": "Junior Software Developer",
  "content" : "My amazing bio"
}

и

POST blog/page/2
{
  "author": "Jason",
  "author-title": "Senior Software Developer",
  "content" : "My amazing bio is better"
}

После того, как они создали свои сообщения в блогах, мы хотели бы отслеживать «просмотры» их блогов и повышать результаты поиска на основе их «просмотров».

Это можно сделать с помощью запрос оценки функции:

GET blog/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "author-title": "developer"
        }
      },
      "functions": [
        {
          "filter": {
            "range": {
              "views": {
                "from": 1
              }
            }
          }, 
          "field_value_factor": {
            "field": "views"
          }
        }
      ]
    }
  }
}

Я использую фильтр диапазона, чтобы убедиться, что field_value_factor не влияет на оценку, когда количество просмотров равно 0 (оценка также будет равна 0).

Теперь, когда я попытаюсь запустить этот запрос, я получу следующее исключение:

nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }]

Что имеет смысл, потому что поля нет нигде в индексе. Если бы я добавил views = 0 во время индексирования, у меня не было бы вышеуказанной проблемы, поскольку поле известно в индексе. Но в моем случае я не могу добавить это ни во время индексации, ни в сопоставление.

Основываясь на возможности использовать диапазонный фильтр в запросе оценки функции, я подумал, что смогу использовать exists filter, чтобы убедиться, что часть field_value_factor будет выполняться только тогда, когда поле действительно присутствует в индексе, но не повезло:

GET blog/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "author-title": "developer"
        }
      },
      "functions": [
        {
          "filter": {
            "bool": {
              "must": [
                {
                  "exists": {
                    "field": "views"
                  }
                },
                {
                  "range": {
                    "views": {
                      "from": 1
                    }
                  }
                }
              ]
            }
          },
          "field_value_factor": {
            "field": "views"
          }
        }
      ]
    }
  }
}

Еще дает:

nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }]

Где я ожидаю, что Elasticsearch сначала применит фильтр, прежде чем анализировать field_value_factor.

Любые мысли о том, как решить эту проблему, без использования файлов сопоставления или исправления во время индексации или сценариев??


person Byron Voorbach    schedule 03.12.2014    source источник
comment
У меня такая же проблема в данный момент. Удалось ли вам найти решение для этого?   -  person tschubotz    schedule 22.04.2015
comment
Здесь есть запись об ошибке: github.com/elastic/elasticsearch/issues/10948   -  person OrangeDog    schedule 30.09.2015


Ответы (1)


Ошибка, которую вы видите, возникает во время синтаксического анализа запроса, т. е. еще ничего не выполнено. В то время FieldValueFactorFunctionParser создает функцию filter_value_factor для последующего выполнения, но замечает, что поле views не существует в типе сопоставления.

Обратите внимание, что фильтр еще не был выполнен, как и функция filter_value_factor, он был только проанализирован FunctionScoreQueryParser.

Мне интересно, почему вы не можете просто добавить поле в свой тип сопоставления, это так же просто, как запустить это

curl -XPUT 'http://localhost:9200/blog/_mapping/page' -d '{
    "page" : {
        "properties" : {
            "views" : {"type" : "integer"}
        }
    }
}'

Если это ДЕЙСТВИТЕЛЬНО не вариант, другой возможностью было бы использовать вместо этого script_score, например так:

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "author-title": "developer"
        }
      },
      "functions": [
        {
          "filter": {
            "range": {
              "views": {
                "from": 1
              }
            }
          }, 
          "script_score": {
            "script": "_score * doc.views.value"
          }
        }
      ]
    }
  }
}
person Val    schedule 01.09.2015