当前位置: 首页 > news >正文

【ElasticSearch实用篇-02】基本增删改查

ElasticSearch实用篇整体栏目


内容链接地址
【一】ElasticSearch实用篇-需求分析和数据制造https://zhenghuisheng.blog.csdn.net/article/details/149178534
【二】ElasticSearch实用篇-基本增删改查https://zhenghuisheng.blog.csdn.net/article/details/149202330

ElasticSearch实用篇

    • 1,mapping映射
    • 2,关键字简单查询(CRUD)
      • 2.1,term精确查询
      • 2.2,match匹配
      • 2.3,range范围查询
      • 2.4,exists过滤
    • 3,关键字部分匹配查询
      • 3.1,prefix前缀查询
      • 3.2,wildcard通配符查询
      • 3.3,fuzzy迷糊查询

如需转载,请附上链接:https://blog.csdn.net/zhenghuishengq/article/details/149202330
上一篇完成了数据的生成,接下来这篇查看一下官网,看一下官方文档,对一些开发中常用的重点知识熟悉一下。其官方地址如下:https://www.elastic.co/guide/cn/elasticsearch/guide/current/data-in-data-out.html

实际开发都是通过canal将数据库中的数据同步到es中,因此此系列也不讲数据的增删改,主要是讲解数据的查询,elasticsearch顾名思义,就是为了查询而生,如果还需要涉及到大量的增删改,那么此非关系型数据库也得好好考虑下是否合适当前业务。

1,mapping映射

获取某一个索引的mapping得到命令如下,在kibana上面就可以详细的展示出来

GET /user/_mapping

在es的官方文档中,支持的基本数据映射类型如下,分别是字符串类型,整型,浮点数据类型,布尔数据类型和date日期类型。基础数据类型适合精确匹配或者范围匹配,同时也支持排序等

  • 字符串: string
  • 整数 :byte, short, integer, long
  • 浮点数: float, double。一般优先推荐使用double,适用于精度要求高的金额、评分
  • 布尔型:boolean
  • 日期:date。支持多种格式,比如说 "yyyy-MM-dd HH:mm:ss"和"yyyy-MM-dd"等

除了基本数据类型之外,还有es核心的两个数据类型,text数据类型和keyword数据类型,text数据类型会根据对应的分词器进行分词,适合通过match关键字进行匹配,keyword关键字不进行分词,得通过term进行精确匹配

  • text:全文匹配数据类型,可以分词,不支持排序,适合match匹配查询,如用户评论、标题、文章内容
  • keyword:精确匹配数据类型,不能分词,支持排序,适合term匹配查询,如性别、城市、手机号、状态码

当然如果text字段也想支持聚合或者排序,那么也可以使用以下这种方式

"title": {"type": "text","fields": {"keyword": { "type": "keyword" }}
}

再次看一下上文index索引手动制造数据的mapping,其内容如下

{"user" : {"mappings" : {"properties" : {"_class" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"birthDay" : {"type" : "long"},"birthMonth" : {"type" : "long"},"birthYear" : {"type" : "long"},"delFlag" : {"type" : "long"},"eduLevel" : {"type" : "long"},"height" : {"type" : "long"},"id" : {"type" : "long"},"liveCity" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"liveProvince" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"nickName" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"regCity" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"regProvince" : {"type" : "text","fields" : {"keyword" : {"type" : "keyword","ignore_above" : 256}}},"sex" : {"type" : "long"},"weight" : {"type" : "long"}}}}
}

2,关键字简单查询(CRUD)

以官方文档的查询为主:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_finding_exact_values.html

2.1,term精确查询

比如通过id查询,可以直接通过以下命令进行查询,id是一个基本数据类型

GET /user/_search
{"query": {"term": {"id":"1937084380169277574"}}
}

如果是一个text文本数据类型,比如设置的liveCity生活城市,那么可以在字段强制加一个keyword

GET /user/_search
{"query": {"term": {"liveCity.keyword": "贵阳市"}}
}

如果完全不想打分,不想有任何加权,可以直接使用filter表达式,这样默认分值是1.0,这个是默认值,内部并没有参与打分

GET /user/_search
{"query": {"constant_score": {"filter": {"term": {"liveCity.keyword": "贵阳市"}}}}
}

对应的java代码如下,后续的代码统一在 buildBoolQueryBuilder 这个方法里改构造条件

@Service
@Slf4j
public class UserTermSearchServiceImpl implements UserTermSearchService {@Resourceprivate RestHighLevelClient restHighLevelClient;@Overridepublic AjaxResult matchSearch() {// 构建查询BoolQueryBuilder queryBuilder = buildBoolQueryBuilder();// 设置查询源SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();sourceBuilder.query(queryBuilder);// 这里可以查看详细的请求 直接拿到kibana上执行log.info("构建条件为:,{}", sourceBuilder);sourceBuilder.size(10);// 构建查询请求SearchRequest searchRequest = new SearchRequest("user");searchRequest.source(sourceBuilder);List<UserEO> userMatchList = new ArrayList<>();try {SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);SearchHit[] hits = response.getHits().getHits();log.info("匹配的返回结果为,{}", hits.length);// 强转eo返回userMatchList = convertToUserEoList(hits);}catch (Exception e){log.error("matchSearch error:", e);}return AjaxResult.success(userMatchList);}/*** 构造查询条件* @return*/private BoolQueryBuilder buildBoolQueryBuilder(){BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();// 精确查询// 添加查询条件// boolQueryBuilder.filter(QueryBuilders.termQuery("id", "拉萨市"));boolQueryBuilder.filter(QueryBuilders.termQuery("liveCity.keyword", "拉萨市"));return boolQueryBuilder;}public List<UserEO> convertToUserEoList(SearchHit[] hits) {if (hits.length == 0){return new ArrayList<>();}JSONArray jsonArray = new JSONArray();for (SearchHit hit : hits) {JSONObject jsonObject = JSONUtil.parseObj(hit.getSourceAsMap());jsonArray.add(jsonObject);}return JSONUtil.toList(jsonArray, UserEO.class);}
}

除了单值查询之外,terms也可以实现多值的精确匹配查询

GET /user/_search
{"query": {"terms": {"liveCity.keyword": ["贵阳市","北京市"]}}
}

对应的代码如下,通过termsQuery 关键字实现

boolQueryBuilder.filter(QueryBuilders.termsQuery("liveCity.keyword", Arrays.asList("贵阳市", "北京市")));

2.2,match匹配

match用于全文匹配,如果是text数据类型,那么会直接分词,比如即使没有完整的西藏数据,也会根据这个分词找到这些数据

GET /user/_search
{"query": {"match": {"liveProvince": "西藏"}}
}

如果是其他基础数据类型或者keyword,那么只能全文精确匹配,如果分析就会找不到,比如以下分词之后就会找不到

GET /user/_search
{"query": {"match": {"liveProvince.keyword": "西藏"}}
}

对应的代码如下,因为match一般设计的是全文分词检索,所以外部用must而不是filter

boolQueryBuilder.must(QueryBuilders.matchQuery("liveProvince", "西藏"));

除了单字段匹配之外,也可以通过multi_match实现多字段匹配,比如查老家城市和居住城市都带有北京的

GET /user/_search
{"query": {"multi_match": {"query": "北京市","fields": ["liveCity", "regCity"]}}
}

其对应的代码如下

boolQueryBuilder.must(QueryBuilders.multiMatchQuery("北京市", new String[]{"liveCity","regCity"}));

2.3,range范围查询

这个用于范围1查询,比如查身高,体重,年龄等,如下查询身高170-175的,

GET /user/_search
{"query": {"range": {"height": {"gte": 170,"lte": 175}}}
}

同时满足三个的,查询身高170-175的,1998-2001年出生的,体重在120-140的,也可以直接使用filter组合的方式

GET /user/_search
{"query": {"bool": {"filter": [{"range": {"height": {"gte": 170,"lte": 175}}},{"range": {"birthYear": {"gte": 1998,"lte": 2001}}},{"range": {"weight": {"gte": 120,"lte": 140}}}]}}
}

对应的代码如下,基本数据类型直接选择filter就行,效果和must一样,filter因为有缓存,filter效率会更快

// 身高170-175
boolQueryBuilder.filter(QueryBuilders.rangeQuery("height").gte(170).lte(175));
// 1998-2001年出生的
boolQueryBuilder.filter(QueryBuilders.rangeQuery("birthYear").gte(1998).lte(2001));
// 体重在120-140
boolQueryBuilder.filter(QueryBuilders.rangeQuery("weight").gte(120).lte(140));

2.4,exists过滤

exist类似于mysql的is not null,就是文档包含这个字段的所有值,当然也包含空字符串""

GET /user/_search
{"query": {"exists": {"field": "nickName"}}
} 

如果想过滤这种"",那么写法如下

GET /user/_search
{"query": {"bool": {"must": [{"exists": {"field": "nickName"}}],"must_not": [{"term": {"nickName.keyword": ""}}]}}
}

对应的代码如下

boolQueryBuilder.must(QueryBuilders.existsQuery("nickName"));
boolQueryBuilder.mustNot(QueryBuilders.termQuery("nickName.keyword", ""));

3,关键字部分匹配查询

2的那几个关键字使用的频率相对较高,接下来是用的频率没那么高的关键字查询,比如前缀查询,模糊查询和通配符查询等

3.1,prefix前缀查询

用官网的话说在这个前缀查询更像是一个过滤器而不是查询,将所有匹配的文档都返回,然后赋值评分为1。比如下面这个例子,我查询居住省份带有江字的数据

GET /user/_search
{"query": {"prefix": {"liveProvince":"江"}}
}

如果查询的字符串短,且es中的数据量大,那么使用这种方式效率可能会比较低一些,mysql对应的语句如下

select * from user where liveProvince like '%江'

3.2,wildcard通配符查询

通配符字段一般适用于keyword字段类型,不太适用于text类型,因为text类型会分词。改匹配一般也是用于模糊匹配,也是需要全文及检索,效率较差。它使用标准的 shell 通配符查询: ? 匹配任意字符, * 匹配 0 或多个字符

?任意字符匹配

?相当于一个占位符,允许让任意一个值去替换它,比如下面的查询就会将江西省和江苏省的一起查询出来

GET /user/_search
{"query": {"wildcard": {"liveProvince.keyword": "江?省"}}
}

比如a?c,那么可以匹配的就是abc,adc;不能匹配的就是ac,abdc

** *匹配字符 **

如我要查询居住城市中带有京字的,下面这个查询就是会将北京市,南京市给查询出来

GET /user/_search
{"query": {"wildcard": {"liveCity.keyword": "*京*"}}
}

*匹配符就是对应mysql的like, *在哪边%就加在哪边

**: like '%京%'
*: like '%京'*: like '京%'

3.3,fuzzy迷糊查询

查询用于在拼写可能有错误或不完全匹配的情况下,找到“最接近”的字符串。fuzzy只能用于text类型,keyword字段不会分词,所以不推荐使用。举例子如下,因为ik分词器的原因,所以都用英文代替下

字符串 A字符串 B编辑距离
catcut1
catcats1
catact2
catdog3

如查询江西,那么能查出来的就有陕西省,山西省,江苏省,西藏自治区,广西壮族自治区

GET /user/_search
{"query": {"fuzzy": {"liveProvince": {"value": "江西","fuzziness": 1}}}
}

用一句话来形容fuzzy就是智能但是低效

http://www.dtcms.com/a/270305.html

相关文章:

  • LoRaWAN 有几种入网方式?
  • 4. 那在详细说一下 http 2.0 的特点
  • WinUI3入门16:Order自定义排序
  • ACE-Step:AI音乐生成基础模型
  • 代码详细注释:基于log.h的自定义日志库实现
  • 探索下一代云存储技术:对象存储、文件存储与块存储的区别与选择
  • Splunk练习 Boss of the SOC V1
  • 短视频矩阵系统的崛起:批量发布功能与多平台矩阵的未来
  • LeetCode 21. 合并两个有序链表
  • C#Halcon从零开发_Day18_OCR识别
  • 4. isaac sim4.2 教程-Core API-Hello robot
  • 【计算机组成原理】-CPU章节学习篇—笔记随笔
  • Linux 第一个系统程序 - 进度条
  • (C++)list列表相关基础用法(C++教程)(STL库基础教程)
  • 跨越NLP的三重曲线:从词法到叙事的进化之路
  • 使用python的 FastApi框架开发图书管理系统-前后端分离项目分享
  • huggingface笔记:文本生成Text generation
  • EXCEL(带图)转html
  • 基于LiteOS与SLE的多任务无线控制器项目实战
  • 深圳凭物联网软件开发构建智慧‘城市大脑‘
  • 什么是 3D 文件?
  • UE material advance 学习笔记
  • 【时时三省】(C语言基础)怎样引用指针变量
  • 免安装图片修改软件,一键批量处理
  • 16018.UE4+Airsim仿真环境搭建
  • 详细页智能解析算法:洞悉海量页面数据的核心技术
  • 软件系统测试的基本流程
  • 【PyTorch项目实战】VisRAG:基于视觉的多模态文档检索增强生成(文本+图像)
  • Android 事件分发机制深度解析
  • Android 中的多线程编程全面解析