zoukankan      html  css  js  c++  java
  • Elastic Search查询DSL的生成器

    最近写了一个Elastic Search查询DSL的生成器(依赖Json.net)。代码如下 

    static class QueryBuilder
    {
        public static object Build(JToken template, object paraData)
        {
            return Build(template, JObject.FromObject(paraData));
        }
    
        public static object Build(JToken template, JObject para)
        {
            var output = FillPara(template, para);
            RemoveNullPara(output);
    
            if (output.Type == JTokenType.Null)
                return null;
    
            return output;
        }
    
    
        static JToken FillPara(JToken template, JObject para)
        {
            var output = template.DeepClone();
    
            foreach (var valueNode in output.AllChildren().OfType<JValue>())
            {
                var key = valueNode.Value<string>();
                if (key?.StartsWith('@') == true)
                {
                    var paraValue = para.Property(key[1..], StringComparison.OrdinalIgnoreCase)
                                       ?.Value;
    
                    var property = valueNode.Parent as JProperty;
                    property.Value = paraValue?.DeepClone();
                }
            }
    
            return output;
        }
    
        static void RemoveNullPara(JToken token)
        {
            foreach (var child in token.AllChildren().ToArray())
            {
                if (child.IsNull())
                    remove(child);
            }
        }
    
        static void remove(JToken token)
        {
            var parent = token.Parent;
            if (parent == null)
            {
                return;
            }
    
            if (parent is JProperty p)
            {
                token = parent;
            }
    
            token.Remove();
        }
    
        static bool IsNull(this JToken token)
        {
            if (token.Type == JTokenType.Null)
                return true;
    
            if (token is JValue)
                return false;
    
            return token.Children().FirstOrDefault() == null;
        }
    
        public static IEnumerable<JToken> AllChildren(this JToken token)
        {
            var children = token switch
            {
                JArray array => array,
                JObject obj => obj.Properties().Select(i => i.Value),
                _ => Enumerable.Empty<JToken>()
            };
    
            foreach (var child in children.SelectMany(AllChildren))
            {
                yield return child;
            }
    
            yield return token;
        }
    }
    View Code

    使用方式类似于dapper,要配套一个Json模板来使用,基本就是elastic search的查询语法,知识将需要注入的参数改为用@开头的占位字符串。

    {
        "query": {
            "bool": {
                "must": [
                    { "term": { "Status""@status" } },
                    { "term": { "Name""@name" } }
                ]
            }
        }
    }

    填充参数,会自动生成对应的json文件(ES的查询body)。

    QueryBuilder.Build(template, new {status = "ok"name="jim"});
    

    执行效果如下:

    {
        "query": {
            "bool": {
                "must": [
                    { "term": { "Status""ok" } },
                    { "term": { "Name""jim" } }
                ]
            }
        }
    }

    支持各种json类型,可以直接配置es查询模板。并且,当属性没有传入时,会自动将其从查询条件中去掉,非常方便,例如:

    QueryBuilder.Build(template, new {status = "ok"});
    

    生成结果如下:

    {
        "query": {
            "bool": {
                "must": [
                    { "term": { "Status""ok" } }
                ]
            }
        }
    }

    这个方式比较适合于查询条件随着输入参数动态增删,并且查询条件经常需要修改的场景: 当查询条件变化时,只需要修改模板即可,不需要修改代码,并且可读性非常好。也能根据参数自适应查询条件的增删。

  • 相关阅读:
    MongoDB
    新公司管理经营
    剪辑理论
    色彩理论
    商业模式
    电影手法
    [好文转载] 每个程序员都应该学习使用Python或Ruby
    File类递归
    【CF1447】div2复盘
    【心得体会】11.9-11.15
  • 原文地址:https://www.cnblogs.com/TianFang/p/13752464.html
Copyright © 2011-2022 走看看