我正在玩Elasticsearch和NEST.
我在理解可用于创建和构建静态查询的各种类和接口时遇到一些麻烦.
这是我想要实现的简化示例:
using Nest;
using System;
using System.Text;
namespace NestTest
{
public class Product
{
public string Name { get; set; }
public int Price { get; set; }
}
public class ProductFilter
{
public string[] IncludeNames { get; set; }
public string[] ExcludeNames { get; set; }
public int MaxPrice { get; set; }
}
class Program
{
static void Main(string[] args)
{
var filter = new ProductFilter();
filter.MaxPrice = 100;
filter.IncludeNames = new[] { "Notebook", "Workstation" };
filter.ExcludeNames = new[] { "Router", "Modem" };
var query = CreateQueryFromFilter(filter);
var client = new ElasticClient();
// Test Serialization
var serialized = Encoding.UTF8.GetString(client.Serializer.Serialize(query));
Console.WriteLine(serialized);
// TODO: How to convert the IQuery to QueryContainer?
//client.Search(s => s.Query(q => query));
}
private static IQuery CreateQueryFromFilter(ProductFilter filter)
{
var baseBoolean = new BoolQueryDescriptor();
if (filter.IncludeNames != null && filter.IncludeNames.Length > 0)
{
foreach (var include in filter.IncludeNames)
{
// TODO: This overwrites the previous must
baseBoolean.Must(q => q.Term(t => t.Name, include));
}
}
if (filter.ExcludeNames != null && filter.ExcludeNames.Length > 0)
{
foreach (var exclude in filter.ExcludeNames)
{
// TODO: This overwrites the previous must
baseBoolean.MustNot(q => q.Term(t => t.Name, exclude));
}
}
if (filter.MaxPrice > 0)
{
// TODO: This overwrites the previous must
baseBoolean.Must(q => q.Range(r => r.LowerOrEquals(filter.MaxPrice).OnField(f => f.Price)));
}
return baseBoolean;
}
}
}
如您所见,我想创建某种查询对象(很可能是BoolQuery),然后再填充此对象.我在代码中添加了一些TODOS,我遇到了实际问题.但总的来说,有太多的可能性(IQuery,QueryContainer,XXXQueryDescriptor,SearchDescriptor,SearchRequest),我无法弄清楚如何逐个成功地"构建"查询.
谁能开导我?
这里的文档描述了组合布尔查询:
http://nest.azurewebsites.net/nest/writing-queries.html
该页面稍微过时,很快就会更新,但大部分仍然适用我更新了您的CreateQueryFromFilter
方法,以展示您可以制定查询的几种方法:
private static IQueryContainer CreateQueryFromFilter(ProductFilter filter) { QueryContainer queryContainer = null; if (filter.IncludeNames != null && filter.IncludeNames.Length > 0) { foreach (var include in filter.IncludeNames) { //using object initializer syntax queryContainer &= new TermQuery() { Field = Property.Path<Product>(p => p.Name), Value = include }; } } if (filter.ExcludeNames != null && filter.ExcludeNames.Length > 0) { foreach (var exclude in filter.ExcludeNames) { //using static Query<T> to dispatch fluent syntax //note the ! support here to introduce a must_not clause queryContainer &= !Query<Product>.Term(p => p.Name, exclude); } } if (filter.MaxPrice > 0) { //fluent syntax through manually newing a descriptor queryContainer &= new QueryDescriptor<Product>() .Range(r => r.LowerOrEquals(filter.MaxPrice).OnField(f => f.Price) ); } return queryContainer; }
以下是将其传递给搜索操作的方法:
static void Main(string[] args) { //using the object initializer syntax client.Search<Product>(new SearchRequest() { Query = query }); //using fluent syntax client.Search<Product>(s => s.Query(query)); }