elasticsearch-query-builder, 一款可以基于配置化以及参数绑定的ES语句构造神器

前言

在这里,我想向大家推荐一个我自己开发的项目,也就是elasticsearch-query-builder,这个项目目前在github上已经开源,有兴趣的朋友可以去fork或者star,你的star就是对我最大的鼓励。同时,本项目长期维护和更新,我也接受并且很高兴有小伙伴向本项目pull request,或者协同开发,有兴趣的同学可以给我发邮件。

elasticsearch-query-builder是一个非常方便构造elasticsearch(后面简称ES) DSL 查询语句的工具包,在elasticsearch-query-builder中,我尝试基于配置化的操作去构建ES的查询语句,并且接受外界传入参数,这极大的减少了在Java代码中构建ES查询语句的工作,并同时减少了代码量,使代码更加直观和清晰。基于使ES中DSL构造语句和Java代码分离的思想,elasticsearch-query-builder诞生了。去GithubFork!

构建

elasticsearch-query-builder工程一般作为jar包为别的工程提供使用,当然,如果需要基于本项目做二次开发,这都需要将Github上克隆本项目到本地

1
git clone https://github.com/xiaowei1118/elasticsearch-query-builder.git

在将本项目克隆到本地后,执行mvn package 将本项目打成jar包,或者直接将本项目作为你们自己maven项目的module项目。

elasticsearch-query-builder使用详细说明

elastcisearch-query-builder接受配置文件(特定json格式)或者json格式的字符串配置,配置格式如下:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
{  "index": "user_portrait",  "type": "docs",  "from": "${from}",  "size": "10",  "include_source": ["name","age"],  //需要哪些字段  "exclude_source": ["sex"],  //排除哪些字段  "query_type": "terms_level_query",  "terms_level_query": {    "terms_level_type": "term_query",    "term_query": {      "value": "${value}",      "key": "key",      "boost": 2    }  },  "aggregations": [    {      "aggregation_type": "terms",      "name": "",      "field": "field",      "sub_aggregations": {        "aggregation_type": "terms",        "name": "sub",        "field": "field",        "size": "${size.value}",        "sort": "asc",        "sort_by": "_count"      }    }  ],  "highlight":{      "fields": [            {              "field": "content",              "number_of_fragment": 2,              "no_match_size": 150            }       ],      "pre_tags":["<em>"],      "post_tags":["</em>"]  },  "sort": [    "_score",    {      "field": "age",      "order": "asc"    }  ]}

参数说明

# index

index表示elasticSearch中的索引或者别名。

# type

type表示elasticSearch索引或者别名下的type。

# from

from表示检索文档时的偏移量,相当于关系型数据库里的offset。

# include_source

include_source 搜索结果中包含某些字段,格式为json数组,"include_source": ["name","age"]

# exclude_source

exclude_source 搜索结果中排除某些字段,格式为json数组,"exclude_source":["sex"]

# query_type

query_type表示查询类型,支持三种类型terms_level_query,text_level_query,bool_level_query,并且这三种类型
不可以一起使用。

  • terms_level_query 操作的精确字段是存储在反转索引中的。这些查询通常用于结构化数据, 如数字、日期和枚举, 而不是全文字段,包含term_query,terms_query,range_query,exists_query 等类型。
  • text_level_query 查询通常用于在完整文本字段 (如电子邮件正文) 上运行全文查询。他们了解如何分析被查询的字段, 并在执行之前将每个字段的分析器 (或 search_analyzer) 应用到查询字符串。

    包含 match_query,multi_match_query,query_string,simple_query_string 等类型。

  • bool_query 与其他查询的布尔组合匹配的文档匹配的查询。bool 查询映射到 Lucene BooleanQuery。它是使用一个或多个布尔子句生成的, 每个子句都有一个类型化的实例。 布尔查询的查询值包括: must,filter,should,must_not. 想要了解这几个类型的差异,可以查阅elasticSearch的相关文档 在每个布尔查询的查询类型值中, 可以包含terms_level_query 和 text_level_query中任意的查询类型,如此便可以构造非常复杂的查询情况。
# terms_level_query查询类型
terms_level_type

terms_level查询类型,支持term_query,terms_query,range_query,exists_query查询。

  • term_query

    • key 表示elasticSearch中需要查询的字段
    • value 表示要查询的值
    • boost 占搜索中的权重
      12345
      "term_query": {      "value": "",      "key": "",      "boost": 2    }
  • terms_query
    • key,value,boost解释同term_query
    • value 可以传入多个,以逗号隔开,如”[1,2]”。
      1234
      "terms_query": {     "value": "[1,2]", //数组     "key": ""   },
  • range_query,给定的查询条件使一个范围
    • key 表示elasticSearch中需要查询的字段
    • range 表示要搜索的值范围,格式如”[a,b]”,表示范围在a、b之间,a、b可以缺省,a缺省则表示没有下限,
      b缺省则表示没有上限,但ab不可以同时为空。a,b可以为时间或者数值。
    • boost 占搜索中的权重
    • format 如果范围使时间的化,format定义时间格式。
    • include_lower 布尔值,是否包含下限。
    • include_upper 布尔值,是否包含上限。
      12345678
      "range_query": {      "key": "",      "range": "", //[,]      "boost": "",      "format": "",      "include_lower": true,      "include_upper": false}
  • exists_query,存在查询,查找字段不存在的文档。
    • key elasticSearch字段。

      123
      "exists_query": {  "key": ""}
# text_level_query查询类型
text_query_type

text_level_query查询类型,支持match_query,multi_match_query,query_string,simple_query_string等。

  • match_query,普通的文本匹配查询。

    • key 供文本匹配的ES字段
    • value 需要搜索的文本关键字,会分词。
    • zero_terms_query 决定是否使用停词。all表示不使用停词,默认使none。
      12345
      "match_query": {  "key": "",  "value": "this is a test",  "zero_terms_query": "none" }
  • multi_match_query 在多个字段中进行文本匹配
    • value 需要搜索的文本关键字,会分词。
    • fields ES中的字段,可以多个,用逗号隔开,在字段旁边使用^表示该字段的权重,如”a^3,b”。
    • type 匹配类型,支持best_fields(默认),most_fields,cross_fields,phrase,phrase_prefix。
      12345
      "multi_match_query": {     "value": "",     "fields": "a^3,b",      "type": "best_fields" //most_fields,cross_fields,phrase,phrase_prefix   }
  • query_string 字符串文本匹配。
    • value 需要搜索的文本关键字,会分词。
    • fields ES中的字段,格式为数组,如”[a,b]”
      1234
      "query_string": {     "value": "",     "fields": ""//数组}
  • simple_query_string 简单字符串匹配

    • value fields 同 query_string
    • default_operate 匹配逻辑,值为and 或者 or
      12345
      "simple_query_string": {      "value": "",      "fields": "", //数组      "default_operate": "and"}
  • match_all_query 匹配所有文档
# bool_query 布尔查询

bool_query是其他查询的布尔组合,一般用于构建复杂的查询,而这正是elasticsearch-query-builder最拿手的地方。

bool_type
  • must查询
    must查询所有的查询条件都会用于做文档匹配(相当于and),并且用于计算相关度score的值。
  • filter查询
    filter查询所有的查询条件都会用于做文档匹配(相当于and),但是和must不同的是,filter查询里面的查询条件并不用于计算相关度。
  • should查询
    should查询条件只需要满足其中一个即可(相当于or)。
  • must_not
    must_not查询表示所有的查询条件同时不满足(相当于not)。
    如:
    1234567891011121314151617181920212223242526
    "query_type": "bool_query", "bool_query": [   {     "bool_type": "must",     "items": [       {         "value": "",         "key": "province_code",         "terms_method": "term" //term,terms,range,match       },       {         "value": "",         "key": "city_code",         "terms_method": "term" //term,terms,range,match       }     ]   },   {     "bool_type":"filter",     "items":[       "value": "",       "key": "sex",       "terms_method":"term"     ]   } ]
# aggregation 聚合

ES的聚合操作通常用于聚合查询结果数据,通常用于数据的分类和统计工作。同时ES本身支持多种聚合操作,为我们的数据分析和统计提供了便利,相应的,本项目也支持聚合操作的配置化和参数绑定。

Avg Aggregation 计算平均数
  • name 聚合名称。
  • aggregation_type 聚合类型。
  • field 查询结果中用于聚合的字段。
  • missing_value 如果文档中该字段为空时,设置的默认值。
    12345678
    "aggregations": [    {      "aggregation_type": "avg", // 聚合类型      "name": "",  //聚合的名称      "field": "",      "missing_value": 10    }]
Terms Aggregation 根据字段的值进行聚合
  • name 聚合名称。
  • aggregation_type 聚合类型。
  • field 查询结果中用于聚合的字段。
  • size 默认为10,设置为0即统计所有的字段值分类的文档个数。
  • sort asc || desc,确定是升序还是降序,default: asc。
  • min_doc_count 最小的匹配文档数,count低于该值的字段值不显示。
  • sort_by 设置聚合结果的排序,默认是根据聚合字段的值排序,可以设置成以聚合分类下的个数排序即_count。
  • sub_aggregations 子聚合,对聚合结果进行再聚合,子聚合可以是别的任意聚合类型。
    12345678910111213141516
    {     "aggregation_type": "terms",     "name": "",     "field": "",     "size": "${size.value}",     "sort": "asc",     "sort_by": "_count",     "sub_aggregations":{     //子聚合         "aggregation_type": "terms",         "name": "",         "field": "",         "size": "${size.value}",         "sort": "asc",         "sort_by": "_count"     }   }

因为aggregation聚合的类型比较多,另外还有,min, max, cardinality,extended_stats, stats,sum,top_hits,value_count,range,missing,date_range,ipv4_range,date_histogram等,这里就不再赘述,需要查看聚合类型怎么用的,可以查看配置文件样例

# highlight 文档高亮

ES可以设置对查询结果中包含搜索关键字的字段部分进行高亮。

  • fields 设置需要高亮的字段

    • field 字段名
    • fragment_size 字段高亮显示的片段的字符长度大小,default: 100
    • number_of_fragment 最多返回片段数,default: 5
  • pre_tags 匹配出来的文档的标签前缀, default: <em>
  • post_tags 匹配出来的文档的标签后缀, default: </em>
  • tags_schema
  • order 高亮片段的排序方式
    12345678910111213
    "highlight":{    "fields": [      {        "field": "content",        "number_of_fragment": 2,        "fragment_size": 150      }    ],    "pre_tags":[],    "post_tags":[],    "tags_schema":"", //styled    "order":"score"  }

参数绑定

# 单值参数绑定

单值绑定,这里我们以sex字段为例,我们需要查询出index中性别为女性的记录,我们可以用terms查询,如:

1234
"term_query": {  "value": "female",  "key": "sex",}

通过以上查询就可以查出性别为女性的文档。那如果我们的value值需要从外面传进来呢,比如我们的参数在一个json字符串中(非常适合application/json的传值:)),如:{ "sex": "female",type: 1},我们的配置文件应该怎么写?

elasticsearch-query-builder中,我们约定需要外界绑定的参数用${}将字段包括进来,如:${sex}这里的sex同json数据里面的key一致。那么在配置文件中就转换成了:

1234
"term_query": {  "value": "${sex}",  "key": "sex",}

如果json中的字段不在第一层呢?比方说:{ "a.sex": "female",type: 1}, 那么我们用.号来表示层级结构,${a.sex}, 不管层级多深都没有问题。

# 范围参数绑定

对于范围类型的参数绑定,比如:type 从 1->6 或者 date 从 2017-06-10 -> 2017-12-12, 我们应该怎么从外界进行参数绑定呢?在range查询中,我们已经定义了range的传参方式,如下:

1234
"range_query":{   "range": "[2017-06-10, 2017-12-12]"   "key": "date"}

其实,其实range的参数绑定和单值的参数绑定是一致的,虽然有范围,其实取的还是单值${date}, 只是我们对外界的json数据结构表示范围的字段有限制,我们规定json中表示范围的字段必须是[a,b]的形式,a和b可以单一缺省,表示无上界或者下界,但是a和b不可以同时缺省(同时缺省,这个范围查询是没有意义的)。
如json数据:{ "date": "[2017-06-10, 2017-12-12]" }即符合规范。

使用示例

这个例子也是elasticsearch-query-builder种的example。
我们先定义配置文件test.json:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
{  "index":"event",  "query_type":"bool_query",  "size":"${pageSize}",  "from":"${offset}",  "include_source": ["age"],  "sort":[    {      "field":"date_time",      "order":"desc"    }  ],  "bool_query":[    {      "bool_type":"filter",      "items":[        {          "terms_method":"term",          "value":"${is_success}",          "key":"is_success"        },        {          "terms_method":"range",          "range":"${date_time}",          "key":"date_time"        },        {          "terms_method":"term",          "value":"${id}}",          "key":"id"        }      ]    },    {      "bool_type":"must",      "items":[        {          "terms_method":"match",          "value":"${name}",          "key":"name"        }      ]    }  ],  "type":"docs"}

使用elasticsearch-query-builder生成ES的查询语句。

1234567891011121314151617181920212223242526
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import org.coryphaei.query.FileUtil;import org.coryphaei.query.parser.ZWSearchParser;import org.elasticsearch.search.builder.SearchSourceBuilder;

/** * Created by twist on 2017-08-05. */public class ElasticsearchParser {    public static void main(String[] args) throws Exception {        String dataStr = "{\n" +               //需要绑定的json格式参数                "\t\"pageSize\":10,\n" +                "\t\"from\": 10,\n" +                "\t\"id\": \"1\",\n" +                "\t\"date_time\":\"[2017-06-01,]\",\n" +                "\t\"is_success\":1,\n" +                "\t\"name\":\"Bob\"\n" +                "}";

JSONObject data = JSON.parseObject(dataStr);        String config = FileUtil.readResourceRemoveComments(ElasticsearchParser.class, "test.json");  //加载配置文件        SearchSourceBuilder searchSourceBuilder = ZWSearchParser.searchSourceBuilder(JSON.parseObject(config), data);  //生成DSL查询语句        System.out.println(searchSourceBuilder.toString());    }}

生成的ES的DSL查询语句:

1234567891011121314151617181920212223242526272829303132333435363738
{  "size" : 10,  "query" : {    "bool" : {      "must" : {        "match" : {          "name" : {            "query" : "Bob",            "type" : "boolean"          }        }      },      "filter" : [ {        "term" : {          "is_success" : "1"        }      }, {        "range" : {          "date_time" : {            "from" : "2017-06-01",            "to" : null,            "include_lower" : true,            "include_upper" : true          }        }      } ]    }  },  "_source" : {    "includes" : [ "age" ],    "excludes" : [ ]  },  "sort" : [ {    "date_time" : {      "order" : "desc"    }  } ]}

不足和待改进

本项目并没有涵盖ES的所有查询功能,同时,也没有包含ES的最新版本的功能,这些都是我后续需要逐渐完善的地方,我希望可以通过自己的努力,使本项目越来越完善。

致谢

本项目使用了阿里的fastjsonjar包,elasticsearch公司的elasticsearchjar包,以及io.searchboxjestjar包,这里表示由衷的感谢。

时间: 2024-11-09 01:14:14

elasticsearch-query-builder, 一款可以基于配置化以及参数绑定的ES语句构造神器的相关文章

Active Query Builder免费下载及简单介绍

原文来自龙博方案网http://www.fanganwang.com/product/1322转载请注明出处 Active Query Builder是一款数据库查询构建控件集,用于Borland Delphi和 C++Builder中,通过它,您可以为您的用户提供一个直接而直观的界面来创建复杂的包含公用体和子查询的SQl查询.它完全支持多种数据库,包括Oracle, Microsoft SQL Server, MySQL, PostgreSQL, InterBase, Informix 和其他

laravel的Eloquent中的get()和Query/Builder中的get()

Eloquent 中的get实际上是Eloquent/Builder中的get,得到的结果是个Collection对象,再调用Collection的first才得到collection中的一项,即一个Model对象. 而Query/Builder中的get得到的是个数组,实际上是直接执行了PDO的fetchAll的结果,这个结果不能再调用first,但是可以直接在Query/Builder上调用first,将得到一个stdClass对象. laravel的文档还是比较模糊的,很多地方都是简单的介

基于配置的自定义的简单struts(了解struts原理)

struts的基于配置的action跳转方式使用起来特别方便,对此我也模仿struts的action,实现一个自己定义的通过配置文件配置action进行简单的操作: 首先,可以知道sturts是通过过滤器来拦截浏览器发送的请求,再在过滤器里进行操作,实现这个流程. 那么,我们也定义一个filter在我们的程序中: public class StrutsFilter implements Filter{ public void doFilter(ServletRequest arg0, Servl

使用Flash Builder 4.6出现 新建配置 失败 java.lang.NullPointerException错误

当看到这个错误的时候有点莫名奇妙的感觉,随后的第一反应是: 这跟我前些天安装的java的jre 1.8 有没有关联性.修改了设定,方法如下 “运行” -> “外部工具” -> “外部工具 配置” ->  点击Ant构建下面的第一个子选项“新建配置”  右边会出现有“JRE”的字样,单击它.然后点击“已安装 JRE”,之后的配置是将JRE的文件地址改为和 环境变量中的“JAVA_HOME”的值(记得将原来的地址复制到 文档中保存起来,切记).然后调试,仍然还是无用,报相同的错误.  结果以

基于配置的Spring MVC3

网上查找的spring mvc3大部分都是基于注射的方式,总感觉注射有点怪怪,不利于后期扩展和项目管理,于是特意写下这篇基于xml配置的Spring MVC3,以供大家参考. 怎么建立web项目和下载相关jar这里就不说了,直接写下关键内容. 1. 所需jar aopalliance-1.0.0.jar commons-logging.jar jsp-api.jar jstl-1.2.jar servlet-api.jar spring-aop-3.2.9.RELEASE.jar spring-

基于配置的Spring AOP

前面几篇学习了Spring的依赖注入,这篇开始学习另一个核心功能——面向切面编程AOP. 通过本文,你可以了解到: 1 Spring xml规范 2 通过配置文件实现面向切面编程 3 对比与传统AOP编程 首先认识一下Spring的xml文件配置格式 Spring的xml一般起名叫做bean.xml或者xxxapplication.xml这种,然后放在src下通过ClassPathXmlApplicationContext进行加载.文件的内容如下: <?xml version="1.0&q

dbForge Query Builder for MySQL工具控件介绍及下载

dbForge Query Builder for MySQL它可以自动执行常规任务.提供重要的特性分析并使用检索数据突出优势,是一个不使用代码和查询结果扩展管理就能快速创建查询的专业工具. 具体功能: 可视化的查询创建 最尖端的图表并支持缩放 为复杂的查询提供查询计划窗口 支持撤消/重复 子查询的可视化编辑 简便的表达式构造器 浏览器窗口的代码模版 具有语法色彩.书签以及文本搜索功能的SQL编辑器 该编辑器具有扩展的SQL格式 自动SQL语法检查 查询结果高级管理 图表和数据打印 定制数据输出

Yii2 数据操作之Query Builder

Query Builder 1 $rows = (new \yii\db\Query()) 2 ->select(['dyn_id', 'dyn_name']) 3 ->from('zs_dynasty') 4 ->where(['between','dyn_id', 1,30]) 5 ->limit(10) 6 ->all(); 7 print_r($rows); 1 use yii\db\Query; 2 $query = (new Query()) 3 ->fro

如何使用 Studio 3T Query Builder 进行数据查询

最近在使用 Studio 3T 对 MongoDB 进行可视化的数据操作. 在 Studio 3T 中,我们可以借助 Query Builder 的 Drag & Drop 来构建查询条件. 具体的 Query Builder 使用方式可以阅读 Studio 3T 官方的这篇文章. 注意:在指定某个字段的值时,Ops 第一栏不要写: 原文地址:https://www.cnblogs.com/huangzejun/p/8675656.html