c# - 如何根据 Elastic Search DSL 的范围/过滤器进行优先级排序,以便可以过滤列表,首先显示可用性 > 60%,然后 <
问题描述
申请人的相关性需要根据当月的可用性百分比进行排序。首先,可用性百分比超过 60% 的申请人应该来,然后可用性百分比低于 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 的值,那也不起作用
解决方案
您的查询不正确;它序列化为
{
"query": {
"bool": {
"boost": 1.2,
"filter": [
{
"range": {
"AvailablePercentage": {
"gt": 0.0,
"lt": 60.0
}
}
}
],
"must": [
{
"match_all": {}
}
]
}
}
}
- 提升应用于整个
bool
查询 - 最后
Filter
分配的覆盖任何以前的过滤器 - 过滤器已
and
编辑,因此需要满足所有条件才能进行匹配
在开发过程中观察客户端发送给 Elasticsearch 的 JSON 是很有用的。有很多方法可以做到这一点,其中一种有用的是
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
子句结合起来,并指定至少一个必须匹配 using MinimumShouldMatch
。这是必要的,因为存在一个must
子句,这意味着should
子句充当文档的增强信号,但文档不必满足任何被视为匹配的子句。设置为 1 时,必须满足MinimumShouldMatch
至少一个should
子句才能被视为匹配。
由于在这种情况下该must
子句是一个match_all
查询,我们可以简单地省略它并删除它MinimumShouldMatch
。should
没有子句的子句must
意味着至少有一个子句必须匹配。
为简洁起见,我们还可以使用运算符重载来组合查询。最终查询看起来像
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
}
}
}
]
}
}
}
推荐阅读
- python - 如何修复权限被拒绝错误?(发生在任何 IDE 中)
- java - 如果未提供密码,则使用 keytool 创建的受密码保护的信任库不显示任何条目
- python-3.x - 通过 configparser 模块使用当前日期时间戳更新日期格式字段
- c# - 我如何从不同的“公共无效”中堆叠相同的“int”?
- d3.js - D3.js V4:如何使用时间和 %H:%M:%S 格式创建 X 轴
- python - 如何按某个日期过滤df?
- go - 如何用中间件包装 API Endpoint
- dart - 将列表视图放入列中
- protractor - 量角器选项在 package.json 脚本中不起作用
- dart - 如何告诉 Visual Studio Code 关于 Dart 库源文件的位置