c# - 需要帮助在 Nest 查询中实现多个 Or 条件

标签 c# elasticsearch nest

我正在尝试在 Nest ElasticSearch 中实现以下 SQL 伪代码。

我没有在 Nest 文档中找到与此问题匹配的任何类似 StackOverflow 问题。感谢您提供的任何指导。

select * 
from curator..published
where accountId = 10
  and ( 
        (publishStatusId = 3 and scheduledDT > '2015-09-01')
        or
        (publishStatusId = 4 and publishedDT > '2015-09-01')
      )

我创建了以下 ElasticSearch 查询,但无法将其成功转换为 Nest 语法。

GET curator/published/_search
{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "accountID": 1781
              }
            }
          ],
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "term": {
                      "publishStatusID": 4
                    }
                  },
                  {
                    "range": {
                      "publishedDT": {
                        "gte": "2015-09-01T00:00:00.000"
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "term": {
                      "publishStatusID": 3
                    }
                  },
                  {
                    "range": {
                      "scheduleDT": {
                        "gte": "2015-09-01T00:00:00.000"
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

此 Nest 查询通过了语法检查,但只有最后一个“应该”条件出现在生成的 ElasticSearch 查询中。

var results = this.Client.Count<Data>(c => c
    .Query(q => q
        .Filtered(f1 => f1
            .Filter(f2 => f2
                .Bool(b => b
                    .Must(
                        f => f.Term(FieldName.AccountID, "10")
                    )
                    .Should(s => s
                        .Bool(b1 => b1
                            .Must(
                                f => f.Term(FieldName.PublishStatusID, "3"),
                                f => f.Range(m => m.OnField(FieldName.ScheduleDT).GreaterOrEquals("2015-09-01"))
                            )
                        )
                    )
                    .Should(s => s
                        .Bool(b1 => b1
                            .Must(
                                f => f.Term(FieldName.PublishStatusID, "4"),
                                f => f.Range(m => m.OnField(FieldName.PublishedDT).GreaterOrEquals("2015-09-01"))
                            )
                        )
                    )
                )
            )
        )
    )
);

此 Nest 查询与原始 ElasticSearch 查询更匹配,但在第二个 Bool 上引发以下错误:错误 51 'Nest.FilterContainer' 不包含 'Bool' 的定义并且没有扩展方法 'Bool' 接受第一个参数可以找到“Nest.FilterContainer”类型(您是否缺少 using 指令或程序集引用?)

var results = this.Client.Count<Data>(c => c
    .Query(q => q
        .Filtered(f1 => f1
            .Filter(f2 => f2
                .Bool(b => b
                    .Must(
                        f => f.Term(FieldName.AccountID, AccountID)
                    )
                    .Should(s => s
                        .Bool(b1 => b1
                            .Must(
                                f => f.Term(FieldName.PublishStatusID, "3"),
                                f => f.Range(m => m.OnField(FieldName.ScheduleDT).GreaterOrEquals("2015-09-01"))
                            )
                        )
                        .Bool(b2 => b2
                            .Must(
                                f => f.Term(FieldName.PublishStatusID, "4"),
                                f => f.Range(m => m.OnField(FieldName.PublishedDT).GreaterOrEquals("2015-09-01"))
                            )
                        )
                    )
                )
            )
        )
    )
);    

最佳答案

您的第一个查询不远,只是传递给第二个 Should() 的表达式需要是另一个传递给第一个 Should() 的表达式(Should() 采用一个 params Func[] 过滤器)。这是查询(我在这里使用 dynamic 作为通用类型):

void Main()
{
    var settings = new ConnectionSettings(new Uri("http://localhost:9200"));
    var connection = new InMemoryConnection(settings);
    var client = new ElasticClient(connection: connection);

    var docs = client.Count<dynamic>(c => c
        .Query(q => q
            .Filtered(f1 => f1
                .Filter(f2 => f2
                    .Bool(b => b
                        .Must(
                            f => f.Term(FieldName.AccountID, "10")
                        )
                        .Should(s => s
                            .Bool(b1 => b1
                                .Must(
                                    f => f.Term(FieldName.PublishStatusID, "3"),
                                    f => f.Range(m => m.OnField(FieldName.ScheduleDT).GreaterOrEquals("2015-09-01"))
                                )
                            ),
                                s => s
                            .Bool(b1 => b1
                                .Must(
                                    f => f.Term(FieldName.PublishStatusID, "4"),
                                    f => f.Range(m => m.OnField(FieldName.PublishedDT).GreaterOrEquals("2015-09-01"))
                                )
                            )
                        )
                    )
                )
            )
        )
    );

    Console.WriteLine(Encoding.UTF8.GetString(docs.RequestInformation.Request));
}

public static class FieldName
{
    public static string AccountID = "AccountID";
    public static string ScheduleDT = "ScheduleDT";
    public static string PublishedDT = "PublishedDT";
    public static string PublishStatusID = "PublishStatusID";
}

产生

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "AccountID": "10"
              }
            }
          ],
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "term": {
                      "PublishStatusID": "3"
                    }
                  },
                  {
                    "range": {
                      "ScheduleDT": {
                        "gte": "2015-09-01"
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "term": {
                      "PublishStatusID": "4"
                    }
                  },
                  {
                    "range": {
                      "PublishedDT": {
                        "gte": "2015-09-01"
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

这与您上面的查询 DSL 匹配

关于c# - 需要帮助在 Nest 查询中实现多个 Or 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32855343/

相关文章:

c# - 下拉列表数据源

c# - 使用 LINQ 如何检查一个数组和另一个数组中的数字实例?

Elasticsearch - 2个字段的乘法然后求和聚合

c# - 使用 ElasticSearch Nest 索引动态对象 - StackOverflow Exception

c# - 弹性NEST返回不一致的结果

c# - 遍历 XML

c# - 如何检查 MongoDB C# 中的索引(是否存在),因为 IndexExist 从新版本中已弃用

elasticsearch - 集群已打开最大分片

mongodb - 使用Logstash具有多个输出

elasticsearch - 在 Nest 中,如何在索引时指定子文档的父文档?