2016-05-14 85 views
0

我有一个函数在基于布尔型标志的时间间隔内搜索文档,NEST查询将使用不同的LessThanOrEqual in if statment and 在else语句中使用的是如何在NEST C中编写动态弹性搜索查询#

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; 
} 

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

+0

请注意,在if语句中,日期范围查询包含结束时间(通过在NEST查询中使用“LessThanOrEqual”),否则语句通过在NEST查询中仅使用LessThan来排除结束时间。 –

回答

1

只要看看LessThanOrEquals和LessThan通用扩展方法是做什么的。基本上,它们扩展了T的DateRangeQueryDescriptor(在这种情况下,T是一本书),接受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(); 

    } 

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

+0

非常感谢您提供宝贵的解决方案 –