准备环境
1、上一篇文章中搭建的本地测试环境
2、springboot最新版本 2.4.1(但是里面整合的客户端是es 7.9.3 我们用的还是有点太新了,需要手动修改一下ES的客户端依赖)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<!--重写springboot给整理好的依赖用最新版本的ES客户端-->
<elasticsearch.version>7.10.1</elasticsearch.version>
<java.version>1.8</java.version>
</properties>
我们使用的是es的highlevel rest api。既然用就用点新货这是我们的原则!!!
开整
在一开始我们先将ES与传统mysql进行一个比较方便在后面的使用中进行横向比较方便理解
在比较完对应关系后看下es支持的字段数据类型,万变不离文档,参考文档地址 :https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
总结几个常用的项目中可能用到的。
下面总结一下我们项目中用到的数据结构以及他们的相关属性
- long 用于存储id信息
- keyword 用于存储手机号这种精准信息
这里简单介绍一下keywords famliy,ES 支持keyword(主要用于存储邮箱地址、id等信息比较合适)
constant_keyword(存储大量相同的内容比如用于存储日志的话日志级别就用这个比较合适),
wildcard 用于存储需要进行模糊搜索正则匹配的字段。 - text 需要对文本进行全文检索,ES会对该字段进行分词。
更多的的字段相关介绍 https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
项目中运用
- 建立索引就叫测算记录跟表名一样即可 t_company_measure_record 建索引的json格式为
PUT t_company_measure_record
{
"settings": {
"number_of_replicas": 3,
"number_of_shards": 5
},
"mappings":{
"properties": {
"mobile": {
"type": "keyword"
},
"company_id": {
"type": "long"
},
"company_name": {
"type": "text",
"analyzer":"ik_max_word"
},
"company_city": {
"type": "text",
"analyzer":"ik_max_word"
},
"company_county": {
"type": "text",
"analyzer":"ik_max_word"
},
"legal_person_type": {
"type": "text",
"analyzer":"ik_max_word"
}
}
}
}
在配置公司名的时候我们使用的是ik分词器
IK 分词器的两种模式 ik_max_word:最细力度切分。ik_smart:最粗力度切分,最佳实践往往是索引时用ik_max_word,在搜索时用ik_smart。
即:索引时最大化的将内容分词,搜索时更精确的搜索到想要的结果。
简单的crud
一、增
- 添加文档json
POST t_company_measure_record/_doc/1
{
"mobile":"13888888888",
"company_id":1,
"company_name":"天云",
"company_city":"北京",
"company_county":"海淀"
}
这里做个简单说明就是url里面的_doc 这是es里面的type,也就是有点像表的概念,但是这个会在ES8中彻底作废
作废原因如下
1、在关系型数据库中table是独立的(独立存储),但es中同一个index中不同type是存储在同一个索引中的(lucene的索引文件),因此不同type中相同名字的字段的定义(mapping)必须一致。
2、不同类型的“记录”存储在同一个index中,会影响lucene的压缩性能
- 添加文档api
public boolean saveRecord(String indexName, int id, Map<String,Object> map) {
try {
IndexRequest request = new IndexRequest(indexName); //index名称
request.id(String.valueOf(id));
request.source(map);
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
if (response.status().getStatus() == RestStatus.OK.getStatus()) {
return true;
}
} catch (Exception e) {
LOG.error("saveRecord error indexName = {},id = {}, map = {}",indexName,id, map, e);
}
return false;
}
二、删
- 删除文档json
DELETE t_company_measure_record/_doc/1
*删除文档api调用方式
public void delete() {
DeleteRequest deleteRequest = new DeleteRequest("t_company_measure_record");
deleteRequest.id("1");
try {
restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
}
三、改
更改分为两种一种是全量更新,一种是增量更新
全量更新只需要使用添加的方式就可以实现,下面将增量更新进行记录,也就是更新部分字段内容或者添加部分字段
- 更改json
POST t_company_measure_record/_update/2
{
"doc":{
"mobile":"15552797319"
}
}
- 更改api
/**
* 更新某一个字段
*/
public void updatePart(){
UpdateRequest updateRequest = new UpdateRequest("t_company_measure_record","2");
IndexRequest indexRequest = new IndexRequest();
Map<String,String> mobileMap = new HashMap<>();
mobileMap.put("mobile","13552797310");
indexRequest.source(mobileMap);
updateRequest.doc(indexRequest);
try {
restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
}
四、查询
查询相对来说复杂一些回想一下mysql where条件里面分为单个条件,多个条件,and、or查询
我们先看一个查一个字段的方法
- json请求
GET t_company_measure_record/_search
{
"query": {
"term": {
"mobile": "13552797310"
}
},
"from":0,
"size":10
}
term 与matchphrase的比较 term用于精确查找有点像 mysql里面的"=" match是先将查询关键字分词然后再进行查找,我们项目中为了让搜索公司名称更好所以使用了match的变种 matchphrase。term一般用在keywokrd类型的字段上进行精确查找。
- api调用
/**
* 精确查找
*/
public void term() {
SearchRequest request = new SearchRequest("t_company_measure_record");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("mobile","13552797310"));
searchSourceBuilder.from(0);
searchSourceBuilder.size(10);
request.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(search);
}
- and 查询也就是must查询
json请求形式
GET t_company_measure_record/_search
{
"query": {
"bool":{
"must": [
{
"match_phrase": {
"company_name": "天云"
}
},
{
"term": {
"mobile": "13552797310"
}
}
]
}
},
"from":0,
"size":10
}
api 接口调用形式
public void must() {
SearchRequest request = new SearchRequest("t_company_measure_record");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder must = QueryBuilders.boolQuery().must(QueryBuilders.matchPhraseQuery("company_name", "天云")).must(QueryBuilders.matchPhraseQuery("mobile", "13552797310"));
searchSourceBuilder.query(must);
searchSourceBuilder.from(0);
searchSourceBuilder.size(10);
request.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
System.out.println(search);
System.out.println(search.getHits().getTotalHits().value);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(search);
}
OR查找
json 格式
GET t_company_measure_record/_search
{
"query": {
"bool":{
"should": [
{
"match_phrase": {
"company_name": "天云"
}
},
{
"term": {
"mobile": "13552797310"
}
}
]
}
},
"from":0,
"size":10
}
API 形式调用
/**
* OR 查询
*/
public void should() {
SearchRequest request = new SearchRequest("t_company_measure_record");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder should = QueryBuilders.boolQuery().should(QueryBuilders.matchPhraseQuery("company_name", "天云")).should(QueryBuilders.matchPhraseQuery("mobile", "13552797310"));
searchSourceBuilder.query(should);
searchSourceBuilder.from(0);
searchSourceBuilder.size(10);
request.source(searchSourceBuilder);
SearchResponse search = null;
try {
search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
System.out.println(search);
System.out.println(search.getHits().getTotalHits().value);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(search);
}
基本使用方式暂时总结到这里,抽空接续补充