如何使用 NEST for Elasticsearch 动态创建查询

cod*_*ube 3 c# elasticsearch nest

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

我有一个带有用户输入的 Filter 类:

Public class ProductFilter
{
    public string Name { get; set; }
    public DateTime? PublishDateFrom { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但对于 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
           .....
      )
);
Run Code Online (Sandbox Code Playgroud)

我想介绍一次搜索中 Name 或 PublishDateFrom 为空或为 null 时的情况。

现在如果我使用:

 ...
  .Query(q => q
         .Term(p => p.Name, filter.Name)
Run Code Online (Sandbox Code Playgroud)

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

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

有什么好的办法解决这个问题吗?

Rus*_*Cam 6

NEST 已经通过无条件查询的概念支持这一点。检查以下各项中的输出

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)
        )
    )
);
Run Code Online (Sandbox Code Playgroud)

此查询利用查询运算符重载来更轻松地构建bool查询。

对于实例上的两个null属性filter,搜索请求是

POST http://localhost:9200/products/projectdocument/_search?pretty=true 
{
  "from": 0,
  "size": 10000
}
Run Code Online (Sandbox Code Playgroud)

没有query指定与查询相同match_all


如果我们filter改为

var filter = new ProductFilter
{
    Name = "foo"
};
Run Code Online (Sandbox Code Playgroud)

然后我们得到以下请求

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

如果我们filter改为

var filter = new ProductFilter
{
    Name = "foo",
    PublishDateFrom = DateTime.UtcNow.Date
};
Run Code Online (Sandbox Code Playgroud)

我们得到

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"
            }
          }
        }
      ]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)