Добавление FunctionScore / FieldValueFactor в запрос MultiMatch - PullRequest
0 голосов
/ 26 октября 2018

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

Наш первоначальный запрос:

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 голосов
/ 26 октября 2018

Ваш запрос 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"
          ]
        }
      }
    }
  }
}
...