- 写在之前
ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
在之前在项目开发中的不同的查询条件都需要单独些Java bean去封装查询语句,后面就想能不能让es也支持类似与sql where name=xxx and age=20这类的过滤条件。所以在这儿就写了个解析表达式同时生成es能够支持的query dsl的小工具 支持的操作符号有==,!= ,<,>,>=,<= 同时还支持加括号增加查询条件优先级的功能。 实现
源码中的conditionNode用到了二叉树的结构,表达不是很清楚,直接上个列子吧,比如我要查询的表达式为:name==yang and age==20
生成的conditionNode 的json结构为
{ "op":"eq", "type":"normal", "left":{ "field":"name", "value":"yang", "op":"eq", "type":"normal" }, "right":{ "field":"age", "value":"20", "op":"eq", "type":"normal" }, "relation":"and" }
可以看到在最外层的conditionNode的左右两个节点封装单独的两个conditionNode ,且其关系为and,最后将 解析后的condition生成query dsl:
{ "bool" : { "must" : [ { "bool" : { "must" : [ { "query_string" : { "query" : "name:\"yang\"" } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } }, { "bool" : { "must" : [ { "query_string" : { "query" : "age:\"20\"", } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } }
如果只是支持顺序解析倒也没有什么特别的,这里举个添加括号提高查询条件优先级的列子:
expression : (name==yang and age>20) or (name == wang and age<=18)
解析后的conditionNode为:{ "op":"eq", "type":"normal", "left":{ "op":"eq", "type":"normal", "left":{ "field":"name", "value":"yang", "op":"eq", "type":"normal" }, "right":{ "field":"age", "value":"20", "op":"gte", "type":"normal" }, "relation":"and" }, "right":{ "op":"eq", "type":"normal", "left":{ "field":"name", "value":"wang", "op":"eq", "type":"normal" }, "right":{ "field":"age", "value":"18", "op":"lte", "type":"normal" }, "relation":"and" }, "relation":"or" }
最后根据该conditionNode生成的dsl语句为:
{ "bool" : { "should" : [ { "bool" : { "must" : [ { "bool" : { "must" : [ { "query_string" : { "query" : "name:\"wang\"" } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } }, { "bool" : { "must" : [ { "range" : { "age" : { "from" : null, "to" : "18", "include_lower" : true, "include_upper" : true, "boost" : 1.0 } } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } }, { "bool" : { "must" : [ { "bool" : { "must" : [ { "query_string" : { "query" : "name:\"yang\"" } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } }, { "bool" : { "must" : [ { "range" : { "age" : { "from" : "20", "to" : null, "include_lower" : false, "include_upper" : true, "boost" : 1.0 } } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } } ], "disable_coord" : false, "adjust_pure_negative" : true, "boost" : 1.0 } }
冗余的东西有点多,大家将就着看吧,这里贴上源码地址