Elasticsearch嵌套组合过滤器问题
Elasticsearch nest combination filter issue
我在 asp.net mvc 应用程序中使用 elasticsearch nest。
以下 elasticsearch 查询引发异常,因为类别和品牌等字段可能为 null 或为空。如何添加 if 语句并有条件地构建过滤器。谢谢!
我必须使用 bool & must 来组合 (AND) 搜索条件过滤器。例如,用户想要 "shoes" 类别和零售商 "macys" 中的产品。
s.Query(q => q
.Bool(bq => bq
.Must(
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("Categories", request.Categories))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("BrandName", request.Brands))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("RetailerName", request.Retailers))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("RetailerName", request.Retailers))
),
mq => mq.Range(r => r
.OnField("SellingPrice")
.GreaterOrEquals((double)request.PriceRanges[0].Start)
.LowerOrEquals((double)request.PriceRanges[0].End)
)
)
)
);
您不必关心传递给查询的 null 或空值,因为 NEST 具有称为 Conditionless Queries 的功能。文档说
If any of the queries would result in an empty query they won't be
sent to Elasticsearch.
异常的原因是这些代码行:
mq => mq.Range(r => r
.OnField("SellingPrice")
.GreaterOrEquals((double)request.PriceRanges[0].Start)
.LowerOrEquals((double)request.PriceRanges[0].End)
)
可能 PriceRanges
为 null 或空,并且您正在尝试从第一个元素访问 Start
和 End
属性。如果您能够将请求 class 更改为类似下面的内容,那就太好了,以防您仅使用 PriceRanges
:
中的第一项
class Request
{
public List<string> Categories { get; set; }
public List<string> Brands { get; set; }
public double? PriceRangeStart { get; set; }
public double? PriceRangeEnd { get; set; }
}
那么您的 NEST 查询将如下所示:
s.Query(q => q
.Bool(bq => bq
.Must(
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("Categories", request.Categories))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("BrandName", request.Brands))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("RetailerName", request.Retailers))
),
mq => mq.Range(r => r
.OnField("SellingPrice")
.GreaterOrEquals(request.PriceRangeStart)
.LowerOrEquals(request.PriceRangeEnd)
)
)
));
对于这个请求对象
var request = new Request
{
Brands = new List<string>{"brand"},
PriceRangesEnd = 100
};
NEST 生成以下 elasticsearch 查询
"query": {
"bool": {
"must": [
{
"filtered": {
"filter": {
"terms": {
"BrandName": [
"brand"
]
}
}
}
},
{
"range": {
"SellingPrice": {
"lte": "100"
}
}
}
]
}
}
我在 asp.net mvc 应用程序中使用 elasticsearch nest。
以下 elasticsearch 查询引发异常,因为类别和品牌等字段可能为 null 或为空。如何添加 if 语句并有条件地构建过滤器。谢谢!
我必须使用 bool & must 来组合 (AND) 搜索条件过滤器。例如,用户想要 "shoes" 类别和零售商 "macys" 中的产品。
s.Query(q => q
.Bool(bq => bq
.Must(
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("Categories", request.Categories))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("BrandName", request.Brands))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("RetailerName", request.Retailers))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("RetailerName", request.Retailers))
),
mq => mq.Range(r => r
.OnField("SellingPrice")
.GreaterOrEquals((double)request.PriceRanges[0].Start)
.LowerOrEquals((double)request.PriceRanges[0].End)
)
)
)
);
您不必关心传递给查询的 null 或空值,因为 NEST 具有称为 Conditionless Queries 的功能。文档说
If any of the queries would result in an empty query they won't be sent to Elasticsearch.
异常的原因是这些代码行:
mq => mq.Range(r => r
.OnField("SellingPrice")
.GreaterOrEquals((double)request.PriceRanges[0].Start)
.LowerOrEquals((double)request.PriceRanges[0].End)
)
可能 PriceRanges
为 null 或空,并且您正在尝试从第一个元素访问 Start
和 End
属性。如果您能够将请求 class 更改为类似下面的内容,那就太好了,以防您仅使用 PriceRanges
:
class Request
{
public List<string> Categories { get; set; }
public List<string> Brands { get; set; }
public double? PriceRangeStart { get; set; }
public double? PriceRangeEnd { get; set; }
}
那么您的 NEST 查询将如下所示:
s.Query(q => q
.Bool(bq => bq
.Must(
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("Categories", request.Categories))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("BrandName", request.Brands))
),
mq => mq.Filtered(fq => fq
.Filter(f => f.Terms("RetailerName", request.Retailers))
),
mq => mq.Range(r => r
.OnField("SellingPrice")
.GreaterOrEquals(request.PriceRangeStart)
.LowerOrEquals(request.PriceRangeEnd)
)
)
));
对于这个请求对象
var request = new Request
{
Brands = new List<string>{"brand"},
PriceRangesEnd = 100
};
NEST 生成以下 elasticsearch 查询
"query": {
"bool": {
"must": [
{
"filtered": {
"filter": {
"terms": {
"BrandName": [
"brand"
]
}
}
}
},
{
"range": {
"SellingPrice": {
"lte": "100"
}
}
}
]
}
}