Добавление FunctionScore / FieldValueFactor в запрос MultiMatch

У нас есть довольно простой запрос, который мы используем, чтобы позволить пользователям предоставлять текст запроса, а затем он увеличивает совпадения в разных полях. Теперь мы хотим добавить еще один повышение на основе голосов, но не уверены, куда вложить FunctionScore.

Наш исходный запрос:

var results = await _ElasticClient.SearchAsync<dynamic>(s => s
    .Query(q => q
        .MultiMatch(mm => mm
            .Fields(f => f
                .Field("name^5")
                .Field("hobbies^2")
            )
            .Query(queryText)
        )
    )
);

Если я попытаюсь вложиться в FunctionScore вокруг MultiMatch, он в основном игнорирует запрос / поля и просто возвращает все в индексе:

var results = await _ElasticClient.SearchAsync<dynamic>(s => s
    .Query(q => q
        .FunctionScore(fs => fs
            .Query(q2 => q2
                .MultiMatch(mm => mm
                    .Fields(f => f
                        .Field("name^5")
                        .Field("hobbies^2")
                    )
                    .Query(queryText)
                )
            )
        )
    )
);

Я ожидаю, что, поскольку я не предоставляю FunctionScore или какой-либо другой Functions, это должно в основном делать то же самое, что и выше. Затем простое добавление FunctionScore обеспечит повышение результатов на основе функций, которые я ему даю (в моем случае повышение на основе поля votes просто FieldValueFactor).

Документация по этому поводу немного нечеткая, особенно с некоторыми комбинациями, такими как MultiMatch, FunctionScore и текстом запроса. Я нашел этот ответ, но он не распространяется на включение текста запроса.

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

  • Пользователь вводит запрос
  • Увеличение совпадений этого запроса с определенными полями
  • Повышение всех результатов на основе значения числового поля
1
0
139
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш запрос function_score верен, но причина того, что вы не видите ожидаемых результатов, связана с функцией в NEST под названием безусловные запросы. В случае запроса function_score он считается безусловным, когда нет функций, исключая запрос из сериализованной формы, отправленной в запросе.

Самый простой способ убедиться в этом - на небольшом примере.

private static void Main()
{
    var defaultIndex = "my-index";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool, new InMemoryConnection())
        .DefaultIndex(defaultIndex)
        .DisableDirectStreaming()
        .PrettyJson()
        .OnRequestCompleted(callDetails =>
        {
            if (callDetails.RequestBodyInBytes != null)
            {
                Console.WriteLine(
                    $"{callDetails.HttpMethod} {callDetails.Uri} \n" +
                    $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");
            }
            else
            {
                Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
            }

            Console.WriteLine();

            if (callDetails.ResponseBodyInBytes != null)
            {
                Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                         $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                         $"{new string('-', 30)}\n");
            }
            else
            {
                Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                         $"{new string('-', 30)}\n");
            }
        });

    var client = new ElasticClient(settings);

    var queryText = "query text";

    var results = client.Search<dynamic>(s => s
        .Query(q => q
            .FunctionScore(fs => fs
                .Query(q2 => q2
                    .MultiMatch(mm => mm
                        .Fields(f => f
                            .Field("name^5")
                            .Field("hobbies^2")
                        )
                        .Query(queryText)
                    )
                )
            )
        )
    );
}

который выдает следующий запрос

POST http://localhost:9200/my-index/object/_search?pretty=true&typed_keys=true 
{}

Вы можете отключить функцию безусловный, пометив запрос как Verbatim

var results = client.Search<dynamic>(s => s
    .Query(q => q
        .FunctionScore(fs => fs
            .Verbatim() // <-- send the query *exactly as is*
            .Query(q2 => q2
                .MultiMatch(mm => mm
                    .Fields(f => f
                        .Field("name^5")
                        .Field("hobbies^2")
                    )
                    .Query(queryText)
                )
            )
        )
    )
);

Теперь это отправляет запрос

POST http://localhost:9200/my-index/object/_search?pretty=true&typed_keys=true 
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query": "query text",
          "fields": [
            "name^5",
            "hobbies^2"
          ]
        }
      }
    }
  }
}

Другие вопросы по теме