如何在NEST C#中编写动态弹性搜索查询

时间:2016-05-14 10:46:50

标签: c# dynamic elasticsearch nest

我有一个函数,它根据布尔标志在一个时间间隔内搜索文档,NEST查询不同,如果使用 LessThanOrEqual ,则 LessThan in else statement。

public IEnumerable<Book> GetBooks(DateTime startTime, DateTime endTime,  string author, bool includeEnd)
{
  var readRecords;
  if (includeEnd){
      readRecords = elastic.Search<Book>(s => s.Index(IndexName)
      .Query(q => q.Term(book => book.Author, author) &&
            q.DateRange(i => i.Field(book => book.Author)    
            .GreaterThanOrEquals(startTime)
            .LessThanOrEquals(endTime)))).Documents.ToArray();      
  }
  else{
    readRecords = elastic.Search<Book>(s => s.Index(IndexName)
           .Query(q => q.Term(book => book.Author, author) &&
            q.DateRange(i => i.Field(book => book.Author)
            .GreaterThanOrEquals(startTime)
            .LessThan(endTime)))).Documents.ToArray();
    }   
    return readRecords;
}

如何使用布尔标志“includeEnd”使这个NEST查询动态化,这样我就不需要使用if语句了?

1 个答案:

答案 0 :(得分:1)

只需看看LessThanOrEquals和LessThan通用扩展方法的作用。基本上,它们扩展了T的DateRangeQueryDescriptor(在本例中,T是Book),接受DateMath参数,并返回另一个DateRangeQueryDescriptor。因此,我们可以打破一个函数,该函数取决于includeEnd标志,返回正确的函数以期望查询描述符。

 public IEnumerable<Book> GetBooks(DateTime startTime, DateTime endTime, string author, bool includeEnd)
    {
        var dateFilter = includeEnd ?
            // you have to do a little casting for the lambdas to know what type we're returning
            (Func<DateRangeQueryDescriptor<Book>, DateRangeQueryDescriptor<Book>>)
            (q => q.LessThanOrEquals(endTime))
            : q => q.LessThan(endTime);

        return elastic.Search<Book>(s => s
            .Index(IndexName)
            .Query(q => q.Term(book => book.Author, author) &&
                        q.DateRange(i =>
                        {
                            i = i.Field(book => book.Author)
                            .GreaterThanOrEquals(startTime);
                            return dateFilter(i);
                        }
                )))
                .Documents
                .ToArray();
    }

为了进一步理解这个想法,你可以编写自己的扩展方法:

 public static class DateQueryExtensions
{
    public static DateRangeQueryDescriptor<T> LessThanWithOption<T>(this DateRangeQueryDescriptor<T> q, DateMath to, bool includeEnd)
        where T : class
    {
        return includeEnd ? q.LessThanOrEquals(to) : q.LessThan(to);
    }
}

然后你可以像这样使用它:

 public IEnumerable<Book> GetBooksUsingExtension(DateTime startTime, DateTime endTime, string author, bool includeEnd)
    {
        return elastic.Search<Book>(s => s
           .Index(IndexName)
           .Query(q => q.Term(book => book.Author, author) &&
                       q.DateRange(i => i.Field(book => book.Author)
                           .GreaterThanOrEquals(startTime)
                           .LessThanWithOption(endTime, includeEnd)
                       )))
               .Documents
               .ToArray();

    }

大多数Nest流畅的接口扩展以类似的方式对查询描述符进行操作。