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 或空,并且您正在尝试从第一个元素访问 StartEnd 属性。如果您能够将请求 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"
          }
        }
      }
    ]
  }
}