2016-05-14 84 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

非常感謝您提供寶貴的解決方案 –