如何在 NEST C# 中编写动态弹性搜索查询
how to write dynamic elastic search query in NEST C#
我有一个基于布尔标志在一个时间间隔内搜索文档的函数,NEST 查询将不同于在 if 语句中使用 LessThanOrEqual 和 LessThan 在 else 语句中。
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 语句?
看看 LessThanOrEquals 和 LessThan 泛型扩展方法的作用。基本上,它们扩展了 T 的 DateRangeQueryDescriptor(在这种情况下,T 是一本书),接受 DateMath 参数,并且 return 另一个 DateRangeQueryDescriptor。因此,我们可以根据 includeEnd 标志分解出一个函数,return 是期望查询描述符的正确函数。
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 流畅接口扩展都以类似的方式对查询描述符进行操作。
我有一个基于布尔标志在一个时间间隔内搜索文档的函数,NEST 查询将不同于在 if 语句中使用 LessThanOrEqual 和 LessThan 在 else 语句中。
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 语句?
看看 LessThanOrEquals 和 LessThan 泛型扩展方法的作用。基本上,它们扩展了 T 的 DateRangeQueryDescriptor(在这种情况下,T 是一本书),接受 DateMath 参数,并且 return 另一个 DateRangeQueryDescriptor。因此,我们可以根据 includeEnd 标志分解出一个函数,return 是期望查询描述符的正确函数。
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 流畅接口扩展都以类似的方式对查询描述符进行操作。