【问题标题】:How to dynamically create query using NEST for Elasticsearch如何使用 NEST for Elasticsearch 动态创建查询
【发布时间】:2017-11-28 14:43:38
【问题描述】:

我正在尝试使用 NEST 根据用户的输入动态创建搜索查询。

我有一个带有用户输入的过滤器类:

Public class ProductFilter
{
    public string Name { get; set; }
    public DateTime? PublishDateFrom { get; set; }
}

但对于 Name 和 PublishDateFrom 等属性,如果用户未指定,它们可能为空或 null。

所以在使用 NEST 进行搜索时,如下代码:

var response1 = await client.SearchAsync<ProjectDocument>(s => s
      .Index(Indices.Parse("products"))
      .From(0)
      .Size(10000)
      .Type("product")
      .Query(q => q
           .....
      )
);

我想在一次搜索中涵盖 Name 或 PublishDateFrom 为空或 null 的情况。

如果我现在使用:

 ...
  .Query(q => q
         .Term(p => p.Name, filter.Name)

当 filter.Name 为空或 null 时,则搜索结果为空。我想要类似的东西:如果 filter.Name 为空或 null,则与 Name 相关的术语查询不会执行或包含在 SearchAsync 调用中。当 Name 和 PublishDateFrom 都为空或 null 时,查询应该使用 .MatchAll()。

我正在尝试使用 Bool Query,但也无法处理这种情况。

有什么好的方法可以解决这个问题吗?

【问题讨论】:

    标签: c# elasticsearch nest


    【解决方案1】:

    NEST 已经通过 Conditionless queries 的概念支持这一点。检查以下每个中的输出

    var filter = new ProductFilter();
    
    client.Search<ProjectDocument>(s => s
        .Index("products")
        .From(0)
        .Size(10000)
        .Query(q => +q
            .Term(p => p.Name, filter.Name) && +q 
            .DateRange(d => d
                .Field(f => f.PublishDateFrom)
                .GreaterThan(filter.PublishDateFrom)
            )
        )
    );
    

    此查询利用query operator overloading 更轻松地构建bool 查询。

    filter 实例上同时具有null 属性,搜索请求是

    POST http://localhost:9200/products/projectdocument/_search?pretty=true 
    {
      "from": 0,
      "size": 10000
    }
    

    未指定querymatch_all 查询相同。


    如果我们将filter 更改为

    var filter = new ProductFilter
    {
        Name = "foo"
    };
    

    然后我们得到以下请求

    POST http://localhost:9200/products/projectdocument/_search?pretty=true 
    {
      "from": 0,
      "size": 10000,
      "query": {
        "bool": {
          "filter": [
            {
              "term": {
                "name": {
                  "value": "foo"
                }
              }
            }
          ]
        }
      }
    }
    

    如果我们将 filter 更改为

    var filter = new ProductFilter
    {
        Name = "foo",
        PublishDateFrom = DateTime.UtcNow.Date
    };
    

    我们得到

    POST http://localhost:9200/products/projectdocument/_search?pretty=true 
    {
      "from": 0,
      "size": 10000,
      "query": {
        "bool": {
          "filter": [
            {
              "term": {
                "name": {
                  "value": "foo"
                }
              }
            },
            {
              "range": {
                "publishDateFrom": {
                  "gt": "2017-06-25T00:00:00Z"
                }
              }
            }
          ]
        }
      }
    }
    

    【讨论】:

    • 这正是我想要的。我是 NEST 和 Elasticsearch 的新手。感谢您的回答,@Russ Cam!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多