将FunctionScore / FieldValueFactor添加到MultiMatch查询

时间:2018-10-25 22:24:30

标签: elasticsearch nest

我们有一个非常基本的查询,我们正在使用该查询来允许用户提供查询文本,然后它可以促进不同字段上的匹配。现在我们要添加另一个boost based on votes,但不确定将value嵌套在何处。

我们的原始查询是:

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的{​​{1}}字段可以增强结果)。

与此相关的文档有些模糊,尤其是对于某些组合,例如votesFieldValueFactor和查询文本。我确实找到了this answer,但是在包含查询文本时却没有涵盖。

我敢肯定,这归因于我对弹性查询的工作方式仍不甚了解,但我只是没有找到很多东西来涵盖以下情况(我认为这是很常见的):

  • 用户输入查询
  • 提升查询与某些字段的匹配程度
  • 基于数字字段的值提升所有结果

1 个答案:

答案 0 :(得分:1)

您的function_score查询是正确的,但是未看到预期结果的原因是由于NEST中的一项名为conditionless queries的功能。对于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"
          ]
        }
      }
    }
  }
}