ElasticSearch查询笔记目录
涉及的常用查询内容较多,将分多个章节进行笔记整理,具体如下:
主要是依据精准的查询条件来查询,查询速度快,也是最常用的几类查询方式,具体种类如下:
- term查询
- terms查询
- match_all查询
- match查询
- 布尔match查询
- multi_match查询
- 根据文档id查询(单个id)
- 根据文档ids查询(多个id)
主要是涉及ElasticSearch查询条件相对模糊,查询速度相对慢,实时查询时应尽量避免这些方式,但是这些查询方式又具有自己独特不可代替的功能,还是还有必要,具体如下:
- prefix查询
- fuzzy查询
- wildcard查询
- range查询
- regexp查询
主要涉及ElasticSearch的一些常用的杂项查询;
- 深分页scroll查询
- delete-by-query
- bool查询
- boosting查询
- filter查询
- highlight(高亮)查询
主要涉及ES的聚合查询Aggregations;
- cardinality(去重计数)查询
- range(范围统计)查询
- extended_stats(统计聚合)查询
. 主要涉及ES的地图检索geo相关的查询;
- geo_distance查询
- geo_bounding_box查询
- geo_polygon查询
整体Java代码的测试用例项目
整个章节的Java代码放在CSDN资源ElasticSearch常用查询的Java实现;路径效果如下图,欢迎下载访问;
prefix查询
前缀查询,可以通过一个关键字 去指定一个field的前缀,从而查询到指定的文档
实现要求,查询公司corpName字段查以上海开头的文档。
注意:这里要和match查询区分开来,因为我们定义的公司corpName字段是keyword类型,所以单独的上海
并不在分词库中,所以用match查询根本查不到单纯的以上海
开头的公司。,但是prefix机制是可以的。
RESTFUL代码如下;
#prefix前缀查询
POST /sms-logs-index/_search
{
"query": {
"prefix": {
"corpName": {
"value": "上海"
}
}
}
}
Java代码如下;
static RestHighLevelClient myClient= EsClient.getClient(); //获取操作ES的
String index="sms-logs-index";
@Test
public void findByPrefix() throws IOException {
//1。创建request对象,查询用的对象一般都是SearchRequest对象
SearchRequest request = new SearchRequest(index);
//2,指定查询条件,依赖查询条件的对象SearchSourceBuilder的对象
SearchSourceBuilder builder = new SearchSourceBuilder();
//查询代码一般只要修改这一块
//--------------------------------------------------------------------
builder.query(QueryBuilders.prefixQuery("corpName","上海"));
//--------------------------------------------------------------------
builder.size(20); //ES默认只查询10条记录,即默认size=10,如果需要查询更多,则需要加到size的值
request.source(builder);
//3. 执行查询
SearchResponse response = myClient.search(request, RequestOptions.DEFAULT);
//4. 获取到_source中的数据,并展示
//遍历输出每个文档
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
//输出总文档数
System.out.println(response.getHits().getHits().length);
}
fuzzy查询
模糊查询,我们输入字符的大概,ES就可以根据输入的内容去大概匹配一下结果,同时也支持输入关键字的错别字,所以fuzzy查询本身相对不太精确和稳定,即错别字太多也可能导致查询无结果,需要则中使用。
不同于MySQL的like查询,比Like查询要强大。
实现要求,根据corpName字段模糊匹配公司名称。我们的ES库里面有个中威集团
,这里我们通过输入中文集团
,也能匹配到想要的效果。
fuzzy查询会用到两个很重要的参数,fuzziness,prefix_length
fuzziness:表示输入的关键字通过几次操作可以转变成为ES库里面的对应field的字段,操作是指:新增一个字符,删除一个字符,修改一个字符,每次操作可以记做编辑距离为1,如中文集团
到中威集团
编辑距离就是1,只需要修改一个字符;该参数默认值为0,即不开启模糊查询,一样的,如果fuzziness值在这里设置成2,会把编辑距离为2的东东集团
也抓出来。
prefix_length:表示限制输入关键字和ES对应查询field的内容开头的第n个字符必须完全匹配,不允许错别字匹配,如这里等于1,则表示开头的中
字必须匹配,不匹配则不返回,默认值也是0,加大prefix_length的值可以提高效率和准确率。
注意:这两个参数不是只适用于fuzzy查询,match查询一样适用,后续将es的参数优化我们会细讲,这里简单说明下,会使用即可。
RESTFUL代码如下;
# fuzzy查询1
GET /sms-logs-index/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "中文集团"
,"fuzziness":1
,"prefix_length": 1
}
}
}
}
#fuzzy查询2 允许编辑两次距离
GET /sms-logs-index/_search
{
"query": {
"fuzzy": {
"corpName": {
"value": "中文集团"
,"fuzziness":2
}
}
}
}
Kibana查询结果如下
# fuzzy查询1
# GET /sms-logs-index/_search
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.9029796,
"hits" : [
{
"_index" : "sms-logs-index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.9029796,
"_source" : {
"createDate" : "2020-09-16",
"senDate" : "2020-09-16",
"longCode" : "5478434123",
"moblie" : 18056587445,
"corpName" : "中威集团",
"smsContent" : "中威集团,服务于你的身边!",
"state" : "0",
"opratorId" : "3",
"province" : "杭州",
"ipAddr" : "10.248.19.45",
"replyTotal" : "4",
"fee" : "20"
}
}
]
}
}
#fuzzy查询2 允许编辑两次距离,东东集团也可以匹配到
# GET /sms-logs-index/_search
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.9029796,
"hits" : [
{
"_index" : "sms-logs-index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.9029796,
"_source" : {
"createDate" : "2020-09-16",
"senDate" : "2020-09-16",
"longCode" : "5478434123",
"moblie" : 18056587445,
"corpName" : "中威集团",
"smsContent" : "中威集团,服务于你的身边!",
"state" : "0",
"opratorId" : "3",
"province" : "杭州",
"ipAddr" : "10.248.19.45",
"replyTotal" : "4",
"fee" : "20"
}
},
{
"_index" : "sms-logs-index",
"_type" : "_doc",
"_id" : "5",
"_score" : 0.6019864,
"_source" : {
"createDate" : "2020-09-16",
"senDate" : "2020-09-16",
"longCode" : "24514635",
"moblie" : 18545427895,
"corpName" : "东东集团",
"smsContent" : "数据驱动,AI推动,新零售模型让你的购买更心怡!",
"state" : "1",
"opratorId" : "1",
"province" : "北京",
"ipAddr" : "10.254.19.45",
"replyTotal" : "1",
"fee" : "6000"
}
}
]
}
}
Java代码如下;
static RestHighLevelClient myClient= EsClient.getClient(); //获取操作ES的
String index="sms-logs-index";
@Test
public void findByFuzzy() throws IOException {
//1。创建request对象,查询用的对象一般都是SearchRequest对象
SearchRequest request = new SearchRequest(index);
//2,指定查询条件,依赖查询条件的对象SearchSourceBuilder的对象
SearchSourceBuilder builder = new SearchSourceBuilder();
//查询代码一般只要修改这一块
//--------------------------------------------------------------------
builder.query(QueryBuilders.fuzzyQuery("corpName","中文集团").prefixLength(0).fuzziness(Fuzziness.TWO));
//--------------------------------------------------------------------
builder.size(20); //ES默认只查询10条记录,即默认size=10,如果需要查询更多,则需要加到size的值
request.source(builder);
//3. 执行查询
SearchResponse response = myClient.search(request, RequestOptions.DEFAULT);
//4. 获取到_source中的数据,并展示
//遍历输出每个文档
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
//输出总文档数
System.out.println(response.getHits().getHits().length);
}
Java代码测试结果如下图;
wildcard查询
通配查询,和MySQL中的like是一个套路,可以在查询时,在字符串中指定通配符*和占位符?
实现要求,依据corpName字段查询查询以集团
结尾的公司或者某某集团
为公司名的记录(某某只限两个字)
RESTFUL代码如下;
# wildcard 查询 利用*做通配符
POST /sms-logs-index/_search
{
"query": {
"wildcard": {
"corpName": {
"value": "*集团"
}
}
}
}
# wildcard 查询 利用?做占位符
POST /sms-logs-index/_search
{
"query": {
"wildcard": {
"corpName": {
"value": "??集团"
}
}
}
}
Java代码如下;
static RestHighLevelClient myClient= EsClient.getClient(); //获取操作ES的
String index="sms-logs-index";
@Test
public void findByWildCard() throws IOException {
//1。创建request对象,查询用的对象一般都是SearchRequest对象
SearchRequest request = new SearchRequest(index);
//2,指定查询条件,依赖查询条件的对象SearchSourceBuilder的对象
SearchSourceBuilder builder = new SearchSourceBuilder();
//查询代码一般只要修改这一块
//--------------------------------------------------------------------
builder.query(QueryBuilders.wildcardQuery("corpName","*集团"));
//--------------------------------------------------------------------
builder.size(20); //ES默认只查询10条记录,即默认size=10,如果需要查询更多,则需要加到size的值
request.source(builder);
//3. 执行查询
SearchResponse response = myClient.search(request, RequestOptions.DEFAULT);
//4. 获取到_source中的数据,并展示
//遍历输出每个文档
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
//输出总文档数
System.out.println(response.getHits().getHits().length);
}
Java代码测试结果如下图;
range查询
范围查询,只针对数值类型(字符类型则不适用),对某一个field进行大于或者小于的范围查询。
实现要求,依据fee字段查询所有消费大于等于100,小于等于500的公司。
RESTFUL代码如下;
# range查询
POST /sms-logs-index/_search
{
"query": {
"range": {
"fee": {
"gte": 100,
"lte": 500
}
}
}
}
gt 大于
gte 大于等于
lt 小于
lte 小于等于
Java代码如下;
static RestHighLevelClient myClient= EsClient.getClient(); //获取操作ES的
String index="sms-logs-index";
@Test
public void findByRange() throws IOException {
//1。创建request对象,查询用的对象一般都是SearchRequest对象
SearchRequest request = new SearchRequest(index);
//2,指定查询条件,依赖查询条件的对象SearchSourceBuilder的对象
SearchSourceBuilder builder = new SearchSourceBuilder();
//查询代码一般只要修改这一块
//--------------------------------------------------------------------
builder.query(QueryBuilders.rangeQuery("fee").gte(100).lte(500));
//--------------------------------------------------------------------
builder.size(20); //ES默认只查询10条记录,即默认size=10,如果需要查询更多,则需要加到size的值
request.source(builder);
//3. 执行查询
SearchResponse response = myClient.search(request, RequestOptions.DEFAULT);
//4. 获取到_source中的数据,并展示
//遍历输出每个文档
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
//输出总文档数
System.out.println(response.getHits().getHits().length);
}
regexp查询
正则表达式查询,通过编写的正则表达式进行内容匹配
注意:prefix,fuzzy,wildcard,regexp查询相对都是精确的条件,查询效率也是相抵较低,业务要求实时性高的场景,应该避免使用。
实现要求,依据moblie字段查询查询13手机号开头的公司信息。
RESTFUL代码如下;
# regexp查询
POST /sms-logs-index/_search
{
"query": {
"regexp": {
"moblie": "13[0-9]{9}"
}
}
}
Java代码如下;
static RestHighLevelClient myClient= EsClient.getClient(); //获取操作ES的
String index="sms-logs-index";
@Test
public void findByRegexp() throws IOException {
//1。创建request对象,查询用的对象一般都是SearchRequest对象
SearchRequest request = new SearchRequest(index);
//2,指定查询条件,依赖查询条件的对象SearchSourceBuilder的对象
SearchSourceBuilder builder = new SearchSourceBuilder();
//查询代码一般只要修改这一块
//--------------------------------------------------------------------
builder.query(QueryBuilders.regexpQuery("moblie","13[0-9]{9}"));
//--------------------------------------------------------------------
builder.size(20); //ES默认只查询10条记录,即默认size=10,如果需要查询更多,则需要加到size的值
request.source(builder);
//3. 执行查询
SearchResponse response = myClient.search(request, RequestOptions.DEFAULT);
//4. 获取到_source中的数据,并展示
//遍历输出每个文档
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
//输出总文档数
System.out.println(response.getHits().getHits().length);
}