【问题标题】:Static Query Building with NEST使用 NEST 构建静态查询
【发布时间】:2014-08-11 21:11:52
【问题描述】:

我在玩 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<Product>(s => s.Query(q => query));
        }

        private static IQuery CreateQueryFromFilter(ProductFilter filter)
        {
            var baseBoolean = new BoolQueryDescriptor<Product>();

            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),我无法弄清楚如何逐部分成功地“构建”查询。

哪位大神可以解惑一下?

【问题讨论】:

    标签: c# static elasticsearch builder nest


    【解决方案1】:

    这里的文档中描述了组合布尔查询:

    http://nest.azurewebsites.net/nest/writing-queries.html

    该页面有些过时,很快就会更新,尽管其中大部分内容仍然适用

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

    【讨论】:

    • 谢谢!到目前为止很好。还有一种方法可以将“应该”部分添加到查询中,还是我需要将所有“应该”保存在我自己的数组中并在最后添加?
    • 应该可以使用|= 添加注意布尔查询不完全遵循代数布尔逻辑!如此处所述stackoverflow.com/a/20004283/47020
    • 我遇到的一个“问题”是QueryContainer 声明。我有QueryContainer query = new QueryContainer();,而不是设置为null。然后使用|= new TermQuery { } 组合术语。这导致了一个空的 QueryContainer 并且 API 调用返回“错误请求”。
    • 我无法在 Nest 2.3.1 中找到 Property.Path&lt;T&gt;。有人知道吗?
    猜你喜欢
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-17
    相关资源
    最近更新 更多