什么是网站开发流程,17.zwd一起做网站池尾站,手机网站html代码,公司主页网站制作文章目录 7#xff0e;Java api 文档管理7.1 es技术特点7.2 获取数据7.3 文档查询7.4 文档新增7.5 文档修改7.6 文档删除7.7 文档bulk 8#xff0e;图解es内部机制8.1 es分布式基础8.2 分片shard、副本replica8.3 单node环境创建index8.4 多node环境replica shard8.5 横向扩容… 文章目录 7Java api 文档管理7.1 es技术特点7.2 获取数据7.3 文档查询7.4 文档新增7.5 文档修改7.6 文档删除7.7 文档bulk 8图解es内部机制8.1 es分布式基础8.2 分片shard、副本replica8.3 单node环境创建index8.4 多node环境replica shard8.5 横向扩容8.6 es容错机制 master选举 replica容错 数据恢复 9图解文档存储机制9.1 数据路由9.2 文档增删改内部机制9.3 文档查询内部机制9.4 bulk api奇特的json格式 10Mapping映射入门10.1 什么是mapping映射10.2 精确匹配与全文搜索10.3 全文检索下倒排索引原理10.4 分词器 analyzer10.5 query string根据字段分词10.6 mapping回顾总结10.7 mapping的核心数据类型以及dynamic mapping10.8 手动管理mapping10.9 复杂数据类型 7Java api 文档管理
7.1 es技术特点
1 es技术比较特殊不像其他分布式、大数据es代码层面很好写难的是概念的理解。
2 es最重要的是他的rest api。跨语言的。在真实生产中探查数据、分析数据使用rest更方便。
7.2 获取数据
java api 文档 https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-overview.html low : 偏向底层。 high高级封装。
1 导包 dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactIdversion7.3.0/versionexclusionsexclusiongroupIdorg.elasticsearch/groupIdartifactIdelasticsearch/artifactId/exclusion/exclusions/dependencydependencygroupIdorg.elasticsearch/groupIdartifactIdelasticsearch/artifactIdversion7.3.0/version/dependency2 代码 //获取连接客户端RestHighLevelClient client new RestHighLevelClient(RestClient.builder(new HttpHost(localhost, 9200, http)));//构建请求GetRequest getRequest new GetRequest(book, 1);// 执行GetResponse getResponse client.get(getRequest, RequestOptions.DEFAULT);// 获取结果if (getResponse.isExists()) {long version getResponse.getVersion();String sourceAsString getResponse.getSourceAsString();//检索文档(String形式)System.out.println(sourceAsString);}7.3 文档查询
1 导包 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactIdversion2.0.6.RELEASE/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scopeversion2.0.6.RELEASE/version/dependency2 配置 application.yml
spring:application:name: service-search
heima:elasticsearch:hostlist: 127.0.0.1:9200 #多个结点中间用逗号分隔3 代码
SpringBootTest
RunWith(SpringRunner.class)
//查询文档
Test
public void testGet() throws IOException {//构建请求GetRequest getRequest new GetRequest(test_post, 1);//可选参数 start//为特定字段配置_source_include// String[] includes new String[]{user, message};// String[] excludes Strings.EMPTY_ARRAY;// FetchSourceContext fetchSourceContext new FetchSourceContext(true, includes, excludes);// getRequest.fetchSourceContext(fetchSourceContext);//为特定字段配置_source_excludes// String[] includes1 new String[]{user, message};// String[] excludes1 Strings.EMPTY_ARRAY;// FetchSourceContext fetchSourceContext1 new FetchSourceContext(true, includes1, excludes1);// getRequest.fetchSourceContext(fetchSourceContext1);//设置路由// getRequest.routing(routing);// 可选参数 end//查询//同步查询GetResponse getResponse client.get(getRequest, RequestOptions.DEFAULT);//异步查询// ActionListenerGetResponse listener new ActionListenerGetResponse() {// //查询成功时的立马执行的方法// Override// public void onResponse(GetResponse getResponse) {// long version getResponse.getVersion();// String sourceAsString getResponse.getSourceAsString();//检索文档(String形式)// System.out.println(sourceAsString);// }//// //查询失败时的立马执行的方法// Override// public void onFailure(Exception e) {// e.printStackTrace();// }// };// //执行异步请求// client.getAsync(getRequest, RequestOptions.DEFAULT, listener);// try {// Thread.sleep(5000);// } catch (InterruptedException e) {// e.printStackTrace();// }// 获取结果if (getResponse.isExists()) {long version getResponse.getVersion();String sourceAsString getResponse.getSourceAsString();//检索文档(String形式)System.out.println(sourceAsString);byte[] sourceAsBytes getResponse.getSourceAsBytes();//以字节接受MapString, Object sourceAsMap getResponse.getSourceAsMap();System.out.println(sourceAsMap);}else {}
}7.4 文档新增
rest api
PUT test_post/_doc/2
{user:tomas,postDate:2019-07-18,message:trying out es1
}代码
Test
public void testAdd() throws IOException {//1 构建请求IndexRequest requestnew IndexRequest(test_posts);request.id(3);//构建文档//构建方法1String jsonString{\n \user\:\tomas J\,\n \postDate\:\2019-07-18\,\n \message\:\trying out es3\\n };request.source(jsonString, XContentType.JSON);// 构建方法2// MapString,Object jsonMapnew HashMap();// jsonMap.put(user, tomas);// jsonMap.put(postDate, 2019-07-18);// jsonMap.put(message, trying out es2);// request.source(jsonMap);// 构建方法3// XContentBuilder builder XContentFactory.jsonBuilder();// builder.startObject();// {// builder.field(user, tomas);// builder.timeField(postDate, new Date());// builder.field(message, trying out es2);// }// builder.endObject();// request.source(builder);// 构建方法4// request.source(user,tomas,// postDate,new Date(),// message,trying out es2);//// 可选参数//设置超时时间request.timeout(TimeValue.timeValueSeconds(1));request.timeout(1s);//自己维护版本号// request.version(2);// request.versionType(VersionType.EXTERNAL);//2 执行//同步IndexResponse indexResponse client.index(request, RequestOptions.DEFAULT);//异步// ActionListenerIndexResponse listenernew ActionListenerIndexResponse() {// Override// public void onResponse(IndexResponse indexResponse) {//// }//// Override// public void onFailure(Exception e) {//// }// };// client.indexAsync(request,RequestOptions.DEFAULT, listener);// try {// Thread.sleep(5000);// } catch (InterruptedException e) {// e.printStackTrace();// }//3 获取结果String index indexResponse.getIndex();String id indexResponse.getId();//获取插入的类型if(indexResponse.getResult() DocWriteResponse.Result.CREATED){DocWriteResponse.Result resultindexResponse.getResult();System.out.println(CREATED:result);}else if(indexResponse.getResult() DocWriteResponse.Result.UPDATED){DocWriteResponse.Result resultindexResponse.getResult();System.out.println(UPDATED:result);}ReplicationResponse.ShardInfo shardInfo indexResponse.getShardInfo();if(shardInfo.getTotal()!shardInfo.getSuccessful()){System.out.println(处理成功的分片数少于总分片);}if(shardInfo.getFailed()0){for (ReplicationResponse.ShardInfo.Failure failure:shardInfo.getFailures()) {String reason failure.reason();//处理潜在的失败原因System.out.println(reason);}}
}7.5 文档修改
rest api
post /test_posts/_doc/3/_update
{doc: {usertomas J}
}代码
Test
public void testUpdate() throws IOException {//1 构建请求UpdateRequest request new UpdateRequest(test_posts, 3);MapString, Object jsonMap new HashMap();jsonMap.put(user, tomas JJ);request.doc(jsonMap);//可选参数//超时时间request.timeout(1s);//重试次数request.retryOnConflict(3);//设置在继续更新之前必须激活的分片数// request.waitForActiveShards(2);//所有分片都是active状态才更新// request.waitForActiveShards(ActiveShardCount.ALL);//2 执行//同步UpdateResponse updateResponse client.update(request, RequestOptions.DEFAULT);//异步//3 获取数据updateResponse.getId();updateResponse.getIndex();//判断结果if (updateResponse.getResult() DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result updateResponse.getResult();System.out.println(CREATED: result);} else if (updateResponse.getResult() DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result updateResponse.getResult();System.out.println(UPDATED: result);}else if(updateResponse.getResult() DocWriteResponse.Result.DELETED){DocWriteResponse.Result result updateResponse.getResult();System.out.println(DELETED: result);}else if (updateResponse.getResult() DocWriteResponse.Result.NOOP){//没有操作DocWriteResponse.Result result updateResponse.getResult();System.out.println(NOOP: result);}
}7.6 文档删除
rest api
DELETE /test_posts/_doc/3代码
Test
public void testDelete() throws IOException {//1 构建请求DeleteRequest request new DeleteRequest(test_posts,3);//可选参数//2 执行DeleteResponse deleteResponse client.delete(request, RequestOptions.DEFAULT);//3 获取数据deleteResponse.getId();deleteResponse.getIndex();DocWriteResponse.Result result deleteResponse.getResult();System.out.println(result);
}7.7 文档bulk
rest api
POST /_bulk
{action: {metadata}}
{data}代码
Test
public void testBulk() throws IOException {//1 创建请求BulkRequest request new BulkRequest();// request.add(new IndexRequest(post).id(1).source(XContentType.JSON, field, 1));// request.add(new IndexRequest(post).id(2).source(XContentType.JSON, field, 2));request.add(new UpdateRequest(post,2).doc(XContentType.JSON, field, 3));request.add(new DeleteRequest(post).id(1));//2 执行BulkResponse bulkResponse client.bulk(request, RequestOptions.DEFAULT);for (BulkItemResponse itemResponse : bulkResponse) {DocWriteResponse itemResponseResponse itemResponse.getResponse();switch (itemResponse.getOpType()) {case INDEX:IndexResponse indexResponse (IndexResponse) itemResponseResponse;indexResponse.getId();System.out.println(index: indexResponse.getResult());break;case CREATE:IndexResponse createResponse (IndexResponse) itemResponseResponse;indexResponse.getId();System.out.println(create: indexResponse.getResult());break;case UPDATE:UpdateResponse updateResponse (UpdateResponse) itemResponseResponse;updateResponse.getIndex();System.out.println(update: updateResponse.getResult());break;case DELETE:DeleteResponse deleteResponse (DeleteResponse) itemResponseResponse;System.out.println(delete: deleteResponse.getResult());break;}}
}8图解es内部机制
8.1 es分布式基础 8.1.1 es对复杂分布式机制的透明隐藏特性
分布式机制分布式数据存储及共享分片机制数据存储到哪个分片副本数据写入集群发现机制cluster discovery。新启动es实例自动加入集群shard负载均衡大量数据写入及查询es会将数据平均分配shard副本新增副本数分片重分配
8.1.2 Elasticsearch的垂直扩容与水平扩容
垂直扩容使用更加强大的服务器替代老服务器。单机存储及运算能力有上线且成本直线上升。如10t服务器1万单个10T服务器可能20万。
水平扩容采购更多服务器加入集群。大数据。
8.1.3 增加或减少节点时的数据rebalance
新增或减少es实例时es集群会将数据重新分配。
8.1.4 master节点
功能
创建删除节点创建删除索引
8.1.5 节点对等的分布式架构
节点对等每个节点都能接收所有的请求自动请求路由响应收集
8.2 分片shard、副本replica 8.2.1 shardreplica机制
1每个index包含一个或多个shard
2每个shard都是一个最小工作单元承载部分数据lucene实例完整的建立索引和处理请求的能力
3增减节点时shard会自动在nodes中负载均衡
4primary shard和replica shard每个document肯定只存在于某一个primary shard以及其对应的replica shard中不可能存在于多个primary shard
5replica shard是primary shard的副本负责容错以及承担读请求负载
6primary shard的数量在创建索引的时候就固定了replica shard的数量可以随时修改
7primary shard的默认数量是1replica默认是1默认共有2个shard1个primary shard1个replica shard
注意es7以前primary shard的默认数量是5replica默认是1默认有10个shard5个primary shard5个replica shard
8primary shard不能和自己的replica shard放在同一个节点上否则节点宕机primary shard和副本都丢失起不到容错的作用但是可以和其他primary shard的replica shard放在同一个节点上
8.3 单node环境创建index 1单node环境下创建一个index有3个primary shard3个replica shard 2集群status是yellow 3这个时候只会将3个primary shard分配到仅有的一个node上去另外3个replica shard是无法分配的 4集群可以正常工作但是一旦出现节点宕机数据全部丢失而且集群不可用无法承接任何请求
PUT /test_index1
{settings : {number_of_shards : 3,number_of_replicas : 1}
}8.4 多node环境replica shard 1replica shard分配3个primary shard3个replica shard1 node 2primary — replica同步 3读请求primary/replica
8.5 横向扩容 分片自动负载均衡分片向空闲机器转移每个节点存储更少分片系统资源给与每个分片的资源更多整体集群性能提高扩容极限节点数大于整体分片数则必有空闲机器超出扩容极限时可以增加副本数如设置副本数为2总共3*39个分片。9台机器同时运行存储和搜索性能更强容错性更好容错性只要一个索引的所有主分片在集群就就可以运行
8.6 es容错机制 master选举 replica容错 数据恢复 以3分片2副本数3节点为例介绍。
master node宕机自动master选举集群为redreplica容错新master将replica提升为primary shardyellow重启宕机nodemaster copy replica到该node使用原有的shard并同步宕机后的修改green
9图解文档存储机制
9.1 数据路由 9.1.1 文档存储如何路由到相应分片
一个文档最终会落在主分片的一个分片上到底应该在哪一个分片这就是数据路由。
9.1.2 路由算法
shard hash(routing) % number_of_primary_shards哈希值对主分片数取模。
举例
对一个文档经行crud时都会带一个路由值 routing number。默认为文档_id可能是手动指定也可能是自动生成
存储1号文档经过哈希计算哈希值为2,此索引有3个主分片那么计算2%32就算出此文档在P2分片上。
决定一个document在哪个shard上最重要的一个值就是routing值默认是_id也可以手动指定相同的routing值每次过来从hash函数中产出的hash值一定是相同的
无论hash值是几无论是什么数字对number_of_primary_shards求余数结果一定是在0~number_of_primary_shards-1之间这个范围内的。0,1,2。
9.1.3 手动指定 routing number
PUT /test_index/_doc/15?routingnum
{num: 0,tags: []
}场景在程序中架构师可以手动指定已有数据的一个属性为路由值好处是可以定制一类文档数据存储到一个分片中。缺点是设计不好会造成数据倾斜。
所以不同文档尽量放到不同的索引中。剩下的事情交给es集群自己处理。
9.1.4 主分片数量不可变
涉及到以往数据的查询搜索所以一旦建立索引主分片数不可变。
9.2 文档增删改内部机制 增删改可以看做update都是对数据的改动。一个改动请求发送到es集群经历以下四个步骤
1客户端选择一个node发送请求过去这个node就是coordinating node协调节点
2coordinating node对document进行路由将请求转发给对应的node有primary shard
3实际的node上的primary shard处理请求然后将数据同步到replica node
4coordinating node如果发现primary node和所有replica node都搞定之后就返回响应结果给客户端
9.3 文档查询内部机制 1、客户端发送请求到任意一个node成为coordinate node
2、coordinate node对document进行路由将请求转发到对应的node此时会使用round-robin随机轮询算法在primary shard以及其所有replica中随机选择一个让读请求负载均衡
3、接收请求的node返回document给coordinate node
4、coordinate node返回document给客户端
5、特殊情况document如果还在建立索引过程中可能只有primary shard有任何一个replica shard都没有此时可能会导致无法读取到document但是document完成索引建立之后primary shard和replica shard就都有了
9.4 bulk api奇特的json格式
POST /_bulk
{action: {meta}}\n
{data}\n
{action: {meta}}\n
{data}\n[{action:{method:create},data:{id:1,field1:java,field1:spring,}},{action:{method:create},data:{id:2,field1:java,field1:spring,}}
]
1、bulk中的每个操作都可能要转发到不同的node的shard去执行
2、如果采用比较良好的json数组格式
允许任意的换行整个可读性非常棒读起来很爽es拿到那种标准格式的json串以后要按照下述流程去进行处理
1将json数组解析为JSONArray对象这个时候整个数据就会在内存中出现一份一模一样的拷贝一份数据是json文本一份数据是JSONArray对象
2解析json数组里的每个json对每个请求中的document进行路由
3为路由到同一个shard上的多个请求创建一个请求数组。100请求中有10个是到P1
4将这个请求数组序列化
5将序列化后的请求数组发送到对应的节点上去
3、耗费更多内存更多的jvm gc开销
我们之前提到过bulk size最佳大小的那个问题一般建议说在几千条那样然后大小在10MB左右所以说可怕的事情来了。假设说现在100个bulk请求发送到了一个节点上去然后每个请求是10MB100个请求就是1000MB 1GB然后每个请求的json都copy一份为jsonarray对象此时内存中的占用就会翻倍就会占用2GB的内存甚至还不止。因为弄成jsonarray之后还可能会多搞一些其他的数据结构2GB的内存占用。
占用更多的内存可能就会积压其他请求的内存使用量比如说最重要的搜索请求分析请求等等此时就可能会导致其他请求的性能急速下降。
另外的话占用内存更多就会导致java虚拟机的垃圾回收次数更多跟频繁每次要回收的垃圾对象更多耗费的时间更多导致es的java虚拟机停止工作线程的时间更多。
4、现在的奇特格式
POST /_bulk
{ delete: { _index: test_index, _id: 5 }} \n
{ create: { _index: test_index, _id: 14 }}\n
{ test_field: test14 }\n
{ update: { _index: test_index, _id: 2} }\n
{ doc : {test_field : bulk test} }\n1不用将其转换为json对象不会出现内存中的相同数据的拷贝直接按照换行符切割json
2对每两个一组的json读取meta进行document路由
3直接将对应的json发送到node上去
5、最大的优势在于不需要将json数组解析为一个JSONArray对象形成一份大数据的拷贝浪费内存空间尽可能地保证性能
10Mapping映射入门
10.1 什么是mapping映射
概念自动或手动为index中的_doc建立的一种数据结构和相关配置简称为mapping映射。
插入几条数据让es自动为我们建立一个索引
PUT /website/_doc/1
{post_date: 2019-01-01,title: my first article,content: this is my first article in this website,author_id: 11400
}PUT /website/_doc/2
{post_date: 2019-01-02,title: my second article,content: this is my second article in this website,author_id: 11400
}PUT /website/_doc/3
{post_date: 2019-01-03,title: my third article,content: this is my third article in this website,author_id: 11400
}对比数据库建表语句
create table website(post_date date,title varchar(50), content varchar(100),author_id int(11) );动态映射dynamic mapping自动为我们建立index以及对应的mappingmapping中包含了每个field对应的数据类型以及如何分词等设置。
重点也可以手动在创建数据之前先创建index以及对应的mapping
GET /website/_mapping/
{website : {mappings : {properties : {author_id : {type : long},content : {type : text,fields : {keyword : {type : keyword,ignore_above : 256}}},post_date : {type : date},title : {type : text,fields : {keyword : {type : keyword,ignore_above : 256}}}}}}
}尝试各种搜索
GET /website/_search?q2019 0条结果
GET /website/_search?q2019-01-01 1条结果
GET /website/_search?qpost_date:2019-01-01 1条结果
GET /website/_search?qpost_date:2019 0 条结果搜索结果为什么不一致因为es自动建立mapping的时候设置了不同的field不同的data type。不同的data type的分词、搜索等行为是不一样的。所以出现了_all field和post_date field的搜索表现完全不一样。
10.2 精确匹配与全文搜索
10.2.1 exact value 精确匹配
2019-01-01exact value搜索的时候必须输入2019-01-01才能搜索出来
如果你输入一个01是搜索不出来的
select * from book where name ‘java’
10.2.2 full text 全文检索
搜“笔记电脑”笔记本电脑词条会不会出现。
select * from book where name like ‘%java%’
1缩写 vs. 全称cn vs. china
2格式转化like liked likes
3大小写Tom vs tom
4同义词like vs love
2019-01-012019 01 01搜索2019或者01都可以搜索出来
china搜索cn也可以将china搜索出来
likes搜索like也可以将likes搜索出来
Tom搜索tom也可以将Tom搜索出来
like搜索love同义词也可以将like搜索出来
就不是说单纯的只是匹配完整的一个值而是可以对值进行拆分词语后分词进行匹配也可以通过缩写、时态、大小写、同义词等进行匹配。深入 NPL自然语义处理。
10.3 全文检索下倒排索引原理
doc1I really liked my small dogs, and I think my mom also liked them.
doc2He never liked any dogs, so I hope that my mom will not expect me to liked him.
分词初步的倒排索引的建立
termdoc1doc2I**really*liked**my**small*dogs*and*think*mom**also*them*He*never*any*so*hope*that*will*not*expect*me*to*him*
演示了一下倒排索引最简单的建立的一个过程
搜索
mother like little dog不可能有任何结果
mother
like
little
dog
这不是我们想要的结果。同义词mom\mother在我们人类看来是一样。想进行标准化操作。
重建倒排索引
normalization正规化建立倒排索引的时候会执行一个操作也就是说对拆分出的各个单词进行相应的处理以提升后面搜索的时候能够搜索到相关联的文档的概率。时态的转换单复数的转换同义词的转换大小写的转换
mom ― mother
liked ― like
small ― little
dogs ― dog
重新建立倒排索引加入normalization再次用mother liked little dog搜索就可以搜索到了
termdoc1doc2normalizationI**really*like**liked ― likemy**little*small ― littledog*dogs ― dogand*think*mother**mom ― motheralso*them*He*never*any*so*hope*that*will*not*expect*me*to*him*
重新搜索
搜索mother liked little dog
对搜索条件经行分词 normalization
mother
liked - like
little
dog
doc1和doc2都会搜索出来
10.4 分词器 analyzer
10.4.1 什么是分词器 analyzer
作用切分词语normalization提升recall召回率
给你一段句子然后将这段句子拆分成一个一个的单个的单词同时对每个单词进行normalization时态转换单复数转换
recall召回率搜索的时候增加能够搜索到的结果的数量
analyzer 组成部分
1、character filter在一段文本进行分词之前先进行预处理比如说最常见的就是过滤html标签hello -- hello -- andIyou -- I and you
2、tokenizer分词hello you and me -- hello, you, and, me
3、token filterlowercasestop wordsynonymomdogs -- dogliked -- likeTom -- toma/the/an -- 干掉mother -- momsmall -- little
stop word 停用词 了 的 呢。
一个分词器很重要将一段文本进行各种处理最后处理好的结果才会拿去建立倒排索引。
10.4.2 内置分词器的介绍
例句Set the shape to semi-transparent by calling set_trans(5)
standard analyzer标准分词器set, the, shape, to, semi, transparent, by, calling, set_trans, 5默认的是standard
simple analyzer简单分词器set, the, shape, to, semi, transparent, by, calling, set, trans
whitespace analyzerSet, the, shape, to, semi-transparent, by, calling, set_trans(5)
language analyzer特定的语言的分词器比如说english英语分词器set, shape, semi, transpar, call, set_tran, 5
官方文档
https://www.elastic.co/guide/en/elasticsearch/reference/7.4/analysis-analyzers.html
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3YzSYWgr-1693035792655)(E:/2023最新Java学习路线图/学习资料/第4阶段—中间键服务框架/10、ELK搜索技术Elasticsearch/资料-ELK高级搜索/资料/ELK高级搜索/img/1568978200919.png)]
10.5 query string根据字段分词
10.5.1 query string分词
query string必须以和index建立时相同的analyzer进行分词
query string对exact value和full text的区别对待
如 dateexact value 精确匹配
text: full text 全文检索
10.5.2 测试分词器
GET /_analyze
{analyzer: standard,text: Text to analyze 80
}返回值
{tokens : [{token : text,start_offset : 0,end_offset : 4,type : ALPHANUM,position : 0},{token : to,start_offset : 5,end_offset : 7,type : ALPHANUM,position : 1},{token : analyze,start_offset : 8,end_offset : 15,type : ALPHANUM,position : 2},{token : 80,start_offset : 16,end_offset : 18,type : NUM,position : 3}]
}
token 实际存储的term 关键字
position 在此词条在原文本中的位置
start_offset/end_offset字符在原始字符串中的位置
10.6 mapping回顾总结
1往es里面直接插入数据es会自动建立索引同时建立对应的mapping。(dynamic mapping)
2mapping中就自动定义了每个field的数据类型
3不同的数据类型比如说text和date可能有的是exact value有的是full text
4exact value在建立倒排索引的时候分词的时候是将整个值一起作为一个关键词建立到倒排索引中的full text会经历各种各样的处理分词normaliztion时态转换同义词转换大小写转换才会建立到倒排索引中
5同时呢exact value和full text类型的field就决定了在一个搜索过来的时候对exact value field或者是full text field进行搜索的行为也是不一样的会跟建立倒排索引的行为保持一致比如说exact value搜索的时候就是直接按照整个值进行匹配full text query string也会进行分词和normalization再去倒排索引中去搜索
6可以用es的dynamic mapping让其自动建立mapping包括自动设置数据类型也可以提前手动创建index和tmapping自己对各个field进行设置包括数据类型包括索引行为包括分词器等
10.7 mapping的核心数据类型以及dynamic mapping
10.7.1 核心的数据类型
stringtext and keyword
byteshortintegerlong,floatdouble
boolean
date
详见https://www.elastic.co/guide/en/elasticsearch/reference/7.3/mapping-types.html
下图是ES7.3核心的字段类型如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NLfk6Mzf-1693035792656)(E:/2023最新Java学习路线图/学习资料/第4阶段—中间键服务框架/10、ELK搜索技术Elasticsearch/资料-ELK高级搜索/资料/ELK高级搜索/img/1568989192034.png)]
10.7.2 dynamic mapping 推测规则
true or false -- boolean
123 -- long
123.45 -- double
2019-01-01 -- date
“hello world” -- text/keywod
10.7.3 查看mapping
GET /index/_mapping/
10.8 手动管理mapping
10.8.1 查询所有索引的映射
GET /_mapping
10.8.2 创建映射
创建索引后应该立即手动创建映射
PUT book/_mapping
{properties: {name: {type: text},description: {type: text,analyzer:english,search_analyzer:english},pic:{type:text,index:false},studymodel:{type:text}}
}Text 文本类型
1analyzer
通过analyzer属性指定分词器
上边指定了analyzer是指在索引和搜索都使用english如果单独想定义搜索时使用的分词器则可以通过search_analyzer属性
2index
index属性指定是否索引
默认为indextrue即要进行索引只有进行索引才可以从索引库搜索到
但是也有一些内容不需要索引比如商品图片地址只被用来展示图片不进行搜索图片此时可以将index设置为false
删除索引重新创建映射将pic的index设置为false尝试根据pic去搜索结果搜索不到数据
3store
是否在source之外存储每个文档索引后会在 ES中保存一份原始文档存放在_source中一般情况下不需要设置store为true因为在_source中已经有一份原始文档了
测试
PUT book/_mapping
{properties: {name: {type: text},description: {type: text,analyzer:english,search_analyzer:english},pic:{type:text,index:false},studymodel:{type:text}}
}插入文档
PUT /book/_doc/1
{name:Bootstrap开发框架,description:Bootstrap是由Twitter推出的一个前台页面开发框架在行业之中使用较为广泛。此开发框架包含了大量的CSS、JS程序代码可以帮助开发者尤其是不擅长页面开发的程序人员轻松的实现一个不受浏览器限制的精美界面效果。,pic:group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg,studymodel:201002
}Get /book/_search?qname:开发
Get /book/_search?qdescription:开发
Get /book/_search?qpic:group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg
Get /book/_search?qstudymodel:201002
通过测试发现name和description都支持全文检索pic不可作为查询条件
keyword关键字字段
目前已经取代了index: false。上边介绍的text文本字段在映射时要设置分词器keyword字段为关键字字段通常搜索keyword是按照整体搜索所以创建keyword字段的索引时是不进行分词的比如邮政编码、手机号码、身份证等。keyword字段通常用于过虑、排序、聚合等。
date日期类型
日期类型不用设置分词器。
通常日期类型的字段用于排序。
format
通过format设置日期格式
例子
下边的设置允许date字段存储年月日时分秒、年月日及毫秒三种格式。
{
“properties”: {
“timestamp”: {
“type”: “date”,
“format”: “yyyy-MM-dd HH:mm:ss||yyyy-MM-dd”
}
}
}
插入文档
Post book/doc/3
{
“name”: “spring开发基础”,
“description”: “spring 在java领域非常流行java程序员都在用。”,
“studymodel”: “201001”,
“pic”:“group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg”,
“timestamp”:“2018-07-04 18:28:58”
}
数值类型
下边是ES支持的数值类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6CLOsAx-1693035792657)(E:/2023最新Java学习路线图/学习资料/第4阶段—中间键服务框架/10、ELK搜索技术Elasticsearch/资料-ELK高级搜索/资料/ELK高级搜索/img/1568990520717.png)]
1、尽量选择范围小的类型提高搜索效率
2、对于浮点数尽量用比例因子比如一个价格字段单位为元我们将比例因子设置为100这在ES中会按 分 存储映射如下
price: {type: scaled_float,scaling_factor: 100},由于比例因子为100如果我们输入的价格是23.45则ES中会将23.45乘以100存储在ES中。
如果输入的价格是23.456ES会将23.456乘以100再取一个接近原始值的数得出2346。
使用比例因子的好处是整型比浮点型更易压缩节省磁盘空间。
如果比例因子不适合则从下表选择范围小的去用
更新已有映射并插入文档
PUT book/doc/3
{
name: spring开发基础,
description: spring 在java领域非常流行java程序员都在用。,
studymodel: 201001,pic:group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg,timestamp:2018-07-04 18:28:58,price:38.6
}10.8.3 修改映射
只能创建index时手动建立mapping或者新增field mapping但是不能update field mapping。
因为已有数据按照映射早已分词存储好。如果修改那这些存量数据怎么办。
新增一个字段mapping
PUT /book/_mapping/
{properties : {new_field : {type : text,index: false}}
}如果修改mapping,会报错
PUT /book/_mapping/
{properties : {studymodel : {type : keyword}}
}返回
{error: {root_cause: [{type: illegal_argument_exception,reason: mapper [studymodel] of different type, current_type [text], merged_type [keyword]}],type: illegal_argument_exception,reason: mapper [studymodel] of different type, current_type [text], merged_type [keyword]},status: 400
}10.8.4 删除映射
通过删除索引来删除映射
delete book10.9 复杂数据类型
10.9.1 multivalue field
{ “tags”: [ “tag1”, “tag2” ]}
建立索引时与string是一样的数据类型不能混
10.9.2 empty field
null[][null]
10.9.3 object field
PUT /company/_doc/1
{address: {country: china,province: guangdong,city: guangzhou},name: jack,age: 27,join_date: 2019-01-01
}addressobject类型
查询映射
GET /company/_mapping
{company : {mappings : {properties : {address : {properties : {city : {type : text,fields : {keyword : {type : keyword,ignore_above : 256}}},country : {type : text,fields : {keyword : {type : keyword,ignore_above : 256}}},province : {type : text,fields : {keyword : {type : keyword,ignore_above : 256}}}}},age : {type : long},join_date : {type : date},name : {type : text,fields : {keyword : {type : keyword,ignore_above : 256}}}}}}
}object
{address: {country: china,province: guangdong,city: guangzhou},name: jack,age: 27,join_date: 2017-01-01
}底层存储格式
{name: [jack],age: [27],join_date: [2017-01-01],address.country: [china],address.province: [guangdong],address.city: [guangzhou]
}对象数组
{authors: [{ age: 26, name: Jack White},{ age: 55, name: Tom Jones},{ age: 39, name: Kitty Smith}]
}存储格式
{authors.age: [26, 55, 39],authors.name: [jack, white, tom, jones, kitty, smith]
}