本文总共4875个字,阅读需17分钟,全文加载时间:2.225s,本站综合其他专栏收录该内容! 字体大小:

文章导读:倒排索引 全文搜索引擎目前主流的索引技术就是倒排索引的方式。传统的保存数据的方式都是:记录→单词。而倒排索引的保存数据的方式是:单词→记录, 基于分词技术构建倒排索引,每个记录保存数据时,都不会直接存入数……各位看官请向下阅读:

倒排索引

全文搜索引擎目前主流的索引技术就是倒排索引的方式。传统的保存数据的方式都是:记录→单词。而倒排索引的保存数据的方式是:单词→记录, 基于分词技术构建倒排索引,每个记录保存数据时,都不会直接存入数据库。系统先会对数据进行分词,然后以倒排索引结构保存。

倒排索引结构

可以看到 Lucene 为倒排索引(Term Dictionary)部分又增加一层 Term Index 结构,用于快速定位,而这 Term Index 是缓存在内存中的,但 MySQL 的 B+tree 不在内存中,所以整体来看 ES 速度更快,但同时也更消耗资源(内存、磁盘)

集群操作集群健康状态

GET /_cat/health?v

绿 – 一切正常(集群功能齐全)

黄 – 所有数据可用,但有些副本尚未分配(集群功能完全)

红 – 有些数据不可用(集群部分功能)

集群健康状态

查看节点的情况

GET /_cat/nodes?v

集群节点

查询各个索引状态

GET /_cat/indices?v

集群索引

索引创建索引

PUT /film

查看某一个索引的分片情况

GET /_cat/shards/film?v

删除索引

DELETE /film

文档操作创建文档

PUT /film/_doc/1 幂等性

{ "id":100, "name":"operation red sea", "doubanScore":8.5, "actorList":[ {"id":1,"name":"zhang yi"}, {"id":2,"name":"hai qing"}, {"id":3,"name":"zhang han yu"} ]}

POST /film/_doc/ 非幂等性

{ "id":300, "name":"incident red sea", "doubanScore":5.0, "actorList":[ {"id":4,"name":"zhang cuishan111"}]}

根据主键保证幂等性

查询某一个索引中的全部文档

GET /film/_search

根据id查询某一个文档

保持良好的心态,开心每一天

GET /film/_doc/3

根据文档id,删除某一个文档

DELETE /film/_doc/3

修改文档

PUT /film/_doc/3 对已经存在的文档进行替换(幂等性)

{ "id":300, "name":"incident red sea", "doubanScore":5.0, "actorList":[ {"id":4,"name":"zhang cuishan"}]}

POST /film/_doc/3/_update 更新文档中的某一个字段内容

{ "doc": { "yy": "字符串" } }

Elasticsearch实际上并没有在底层执行就地更新,而是先删除旧文档,再添加新文档

批量创建文档

POST /film/_doc/_bulk

{"index":{"_id":66}}{"id":300,"name":"incident red sea","doubanScore":5.0,"actorList":[{"id":4,"name":"zhang cuishan"}]}{"index":{"_id":88}}{"id":300,"name":"incident red sea","doubanScore":5.0,"actorList":[{"id":4,"name":"zhang cuishan"}]}

批量更新与删除文档

POST /film/_doc/_bulk

{"update":{"_id":"66"}}{"doc": { "name": "wudangshanshang" } }{"delete":{"_id":"88"}}

查询

GET /索引名/_search?q=* &pretty这种方式不太适合复杂查询场景

查询指定字段

GET /film/_search{ "_source": ["name", "doubanScore"]}

按分词查询(必须使用分词 text 类型)

GET /film/_search{ "query": { "match": { "actorList.name": "zhang han yu" } }}

按短语查询 相当于like

GET /film/_search{ "query": { "match_phrase": { "actorList.name": "zhang han yu" } }}

不分词 通过精准匹配进行查询

GET /film/_search{ "query": { "term": { "actorList.name.keyword":"zhang han yu" } }}

容错匹配

GET /film/_search{ "query": { "fuzzy": { "name": "radd" } }}

匹配和过滤同时

GET /film/_search{ "query": { "bool": { "must": [ { "match": { "name": "red" } }], "filter": { "term": { "actorList.id": "3" } } }}}

范围过滤 ,将豆瓣评分在6到9的文档查询出来

GET /film/_search{ "query": { "range": { "doubanScore": { "gte": 6, "lte": 9 }} }}

按照豆瓣评分降序排序

GET /film/_search{ "query": { "match": { "name": "red" }}, "sort": [ { "doubanScore": { "order": "asc" } } ]}

分页查询

GET /film/_search{"from": 0, "size": 2}

搜索结果高亮

GET /film/_search{ "query": { "match": { "name": "red" } }, "highlight": { "fields": {"name":{} }, "pre_tags": "<a>", "post_tags": "</a>" }}

聚合

聚合提供了对数据进行分组、统计的能力,类似于 SQL 中 Group By 和 SQL 聚合函数。在 ElasticSearch 中,可以同时返回搜索结果及其聚合计算结果,这是非常强大和高效的。

GET /film/_search{ "aggs": { "groupByName": { "terms": { "field": "actorList.name.keyword", "size": 10, "order": { "avg_score": "desc" } }, "aggs": { "avg_score": { "avg": { "field": "doubanScore" } } }} }}

.keyword 是某个字符串字段,专门储存不分词格式的副本,在某些场景中只允许只用不分词的格式,比如过滤 filter 比如聚合 aggs, 所以字段要加上.keyword 的后缀

中文分词中文分词器对比

分词器对比

GET _analyze{"analyzer": "ik_smart", "text": "我是中国人" }

{ "tokens" : [ { "token" : "我", "start_offset" : 0, "end_offset" : 1, "type" : "CN_CHAR", "position" : 0 }, { "token" : "是", "start_offset" : 1, "end_offset" : 2, "type" : "CN_CHAR", "position" : 1 }, { "token" : "中国人", "start_offset" : 2, "end_offset" : 5, "type" : "CN_WORD", "position" : 2 } ]}

自定义分词词库

<comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">./myword.txt</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords"></entry>

Mapping自定义mapping

实际上每个 Type 中的字段是什么数据类型,由 mapping 定义,如果我们在创建 Index的时候,没有设定 mapping,系统会自动根据一条数据的格式来推断出该数据对应的字段类型,具体推断类型如下:true/false → boolean 1020 → long 20.1 → float “2018-02-01” → date “hello world” → text +keyword默认只有 text 会进行分词,keyword 是不会分词的字符串。mapping 除了自动定义还可以手动定义,但是只能对新加的、没有数据的字段进行定义,一旦有了数据就无法再做修改了。

PUT film01{ "mappings": { "movie":{ "properties": { "id":{ "type": "long" }, "name":{ "type": "keyword" }, "doubanScore":{ "type": "double" }, "actorList":{ "properties": { "id":{ "type":"long" }, "name":{ "type":"keyword" } } } } } }}

copy索引数据

ElasticSearch 虽然强大,但是却不能动态修改 mapping 到时候我们有时候需要修改结构的时候不得不重新创建索引;ElasticSearch 为我们提供了一个 reindex 的命令,就是会将一个索引的快照数据 copy到另一个索引,默认情况下存在相同的_id 会进行覆盖(一般不会发生,除非是将两个索引的数据 copy 到一个索引中)

POST _reindex

{ "source": { "index": "my_index_name" }, "dest": { "index": "my_index_name_new" }}

索引别名应用场景给多个索引分组,把多个索引归并到一组给索引的一个子集创建视图相当于给 Index 加了一些过滤条件,缩小查询范围创建索引 并指定别名

PUT flim01{ "aliases": { "film_chn_3_aliase": {} },

查看所有别名

GET /_cat/aliases

索引增加、删除索引

POST /_aliases{ "actions": [ { "remove": { "index": "movie_chn_1", "alias": "movie_chn_query" }}, { "remove": { "index": "movie_chn_2", "alias": "movie_chn_query" }}, { "add": { "index": "movie_chn_3", "alias": "movie_chn_query" }} ]}

索引模板应用场景分割索引

分割索引就是根据时间间隔把一个业务索引切分成多个索引。比如 把 order_info 变成 order_info_20200101,order_info_20200102 这样做的好处有两个:

结构变化的灵活性

因为 ES 不允许对数据结构进行修改。但是实际使用中索引的结构和配置难免变化,那么只要对下一个间隔的索引进行修改,原来的索引维持原状。这样就有了一定的灵活性。要想实现这个效果,我们只需要在需要变化的索引那天将模板重新建立即可。

查询范围优化

因为一般情况并不会查询全部时间周期的数据,那么通过切分索引,物理上减少了扫描数据的范围,也是对性能的优化。

创建模板

PUT _template/template_film{"index_patterns": ["film_test*"], "settings": { "number_of_shards": 1 }, "aliases" : { "{index}-query": {}, "film_test-query":{} }, "mappings": { "_doc": { "properties": { "id": { "type": "keyword" }, "movie_name": { "type": "text", "analyzer": "ik_smart" }} }}}

查询所有模板

GET _cat/templates

查询模板详情

GET _template/template_film*

以上内容由优质教程资源合作伙伴 “鲸鱼办公” 整理编辑,如果对您有帮助欢迎转发分享!

你可能对这些文章感兴趣:

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注