У нас есть довольно простой запрос, который мы используем, чтобы позволить пользователям предоставлять текст запроса, а затем он увеличивает совпадения в разных полях. Теперь мы хотим добавить еще один повышение на основе голосов, но не уверены, куда вложить 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
и текстом запроса. Я нашел этот ответ, но он не распространяется на включение текста запроса.
Я почти уверен, что это сводится к моему все еще туманному пониманию того, как работают эластичные запросы, но я просто не нахожу много, чтобы охватить (что я считаю довольно распространенным) сценарием:
Ваш запрос 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"
]
}
}
}
}
}