【问题标题】:How to priortize based on range/filter of Elastic Search DSL, such that a list can be filtered, first to show with availability > 60% first and then <如何根据 Elastic Search DSL 的范围/过滤器进行优先级排序,以便可以过滤列表,首先显示可用性 > 60%,然后 <
【发布时间】:2019-05-29 23:10:26
【问题描述】:

申请人的相关性需要根据当月的可用性百分比进行排序。 首先,%availability 大于 60% 的申请人应该来,然后 %availability 小于 60% 的申请人应该来。

我正在尝试使用 ElasticSearch.net 的 Fluent DSL 查询

var response = await 
_elasticClient.SearchAsync<ApplicantsWithDetailsResponse>(s =>
                             s.Aggregations(a => a

.Filter("higer_average", f => f.Filter(fd => fd.Range(r => r.Field(p 
=> p.AvailablePercentage).GreaterThanOrEquals(60).Boost(5))))

.Filter("lower_average", f => f.Filter(fd => fd.Range(r => r.Field(p 
=> p.AvailablePercentage).GreaterThan(0).LessThan(60).Boost(3)))
                             )));

var response = await _elasticClient.SearchAsync<ApplicantsWithDetailsResponse>(
        s => s
          .Query(q => q
           .Bool(p =>
                    p.Must(queryFilter => queryFilter.MatchAll())
                            .Filter(f => f.Range(r => r.Field("AvailablePercentage").GreaterThanOrEquals(60)))
                            .Boost(5)
                            .Filter(f => f.Range(r => r.Field("AvailablePercentage").GreaterThan(0).LessThan(60)))
                            .Boost(1.2)
                             )));

申请人的名单不符合逻辑。他们混在一起。

即使我尝试过滤以仅显示大于 60 的值,这也不起作用

【问题讨论】:

    标签: c# elasticsearch .net-core nest elasticsearch.net


    【解决方案1】:

    您的查询不正确;它序列化为

    {
      "query": {
        "bool": {
          "boost": 1.2,
          "filter": [
            {
              "range": {
                "AvailablePercentage": {
                  "gt": 0.0,
                  "lt": 60.0
                }
              }
            }
          ],
          "must": [
            {
              "match_all": {}
            }
          ]
        }
      }
    }
    
    • 提升应用于整个 bool 查询
    • 最后分配的Filter 会覆盖之前的所有过滤器
    • 过滤器是anded,所以需要满足所有条件才能匹配

    在开发过程中观察客户端发送给 Elasticsearch 的 JSON 是很有用的。有numerous ways that you can do this,还有一个好用的是

    var defaultIndex = "default-index";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    
    var settings = new ConnectionSettings(pool)
        .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 response = client.Search<ApplicantsWithDetailsResponse>(s => s
        .Query(q => q
            .Bool(p => p
                .Must(queryFilter => queryFilter
                    .MatchAll()
                )
                .Should(f => f
                    .Range(r => r
                        .Field("AvailablePercentage")
                        .GreaterThanOrEquals(60)
                        .Boost(5)
                    ), f => f
                    .Range(r => r
                        .Field("AvailablePercentage")
                        .GreaterThan(0)
                        .LessThan(60)
                        .Boost(1.2)
                    )
                )
                .MinimumShouldMatch(1)
            )
        )
    );
    

    发出以下查询

    {
      "query": {
        "bool": {
          "minimum_should_match": 1,
          "must": [
            {
              "match_all": {}
            }
          ],
          "should": [
            {
              "range": {
                "AvailablePercentage": {
                  "boost": 5.0,
                  "gte": 60.0
                }
              }
            },
            {
              "range": {
                "AvailablePercentage": {
                  "boost": 1.2,
                  "gt": 0.0,
                  "lt": 60.0
                }
              }
            }
          ]
        }
      }
    }
    

    将范围查询与should 子句结合起来,并使用MinimumShouldMatch 指定至少一个必须匹配。这是必需的,因为存在must 子句,这意味着should 子句充当文档的增强信号,但文档不必满足任何被视为匹配的子句。将 MinimumShouldMatch 设置为 1 时,必须满足至少一个 should 子句才能被视为匹配项。

    由于在这种情况下must 子句是match_all 查询,我们可以简单地省略它并删除MinimumShouldMatch。没有must 子句的should 子句意味着至少有一个子句必须匹配。

    我们也可以combine queries using operator overloading,为简洁起见。最终查询看起来像

    var response = client.Search<ApplicantsWithDetailsResponse>(s => s
        .Query(q => q
            .Range(r => r
                .Field("AvailablePercentage")
                .GreaterThanOrEquals(60)
                .Boost(5)
            ) || q
            .Range(r => r
                .Field("AvailablePercentage")
                .GreaterThan(0)
                .LessThan(60)
                .Boost(1.2)
            )
        )
    );
    

    发出查询

    {
      "query": {
        "bool": {
          "should": [
            {
              "range": {
                "AvailablePercentage": {
                  "boost": 5.0,
                  "gte": 60.0
                }
              }
            },
            {
              "range": {
                "AvailablePercentage": {
                  "boost": 1.2,
                  "gt": 0.0,
                  "lt": 60.0
                }
              }
            }
          ]
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 2022-11-27
      • 2012-04-29
      • 1970-01-01
      • 2018-05-15
      • 2017-06-18
      • 1970-01-01
      相关资源
      最近更新 更多