全文检索|初步检索及进阶检索

1.基本概念 1.Index(索引)相当于数据库 动词,相当于 MySQL 中的 insert;
名词,相当于 MySQL 中的 Database
2.Type(类型) 相当于表(7版本已经不建议使用) 在 Index(索引)中,可以定义一个或多个类型。
类似于 MySQL 中的 Table;每一种类型的数据放在一起;
3.Document(文档) 相当于表中的数据 保存在某个索引(Index)下,某种类型(Type)的一个数据(Document),文档是 JSON 格 式的,Document 就像是 MySQL 中的某个 Table 里面的内容;
全文检索|初步检索及进阶检索
文章图片

4.倒排索引 全文检索|初步检索及进阶检索
文章图片

es在保存记录时,会同事创建一张表维护倒排索引。把存入的记录进行分词。
如图,在保存红海行动这条记录时,会生成红海和行动两个词,表中红海和行动的记录这一列就有1号记录,添加第二条探索红海行动这条记录时,红海和行动的记录这一列也有了2号记录,探索这条数据的记录这一列也有了2号记录。
检索时,比如输入红海特工行动,查找红海 特工 行动 这三条数据的记录这一列都有那条记录,因为红海这个词在1-5号记录都有,所以数据都会被查出来,看哪个最多得出相关性得分进行排序,此时 1号和2号记录都有 红海和行动,5号记录有红海和特工,所以他们相关性得分会比较高,1号记录时两个词占了两个词,2号记录是三个词占了两个词,5号记录是4歌词占了两个词,所以1号记录的相关性得分最高,排在最前面。
2.初步检索 1._cat GET /_cat/nodes:查看所有节点
GET /_cat/health:查看 es 健康状况 GET _cluster/health(详细信息 )GET _cluster/health?level=indices(索引级别的详细信息)
GET /_cat/master:查看主节点
GET /_cat/indices:查看所有索引 show databases;
单节点查询health会显示yellow 提示unassigned_shards:1 需要将备份数据改为0

PUT /customer/_settingscustomer是索引 { "number_of_replicas":0 }

2.索引一个文档(保存) PUT customer/external/1;在 customer 索引下的 external 类型下保存 1 号数据为
PUT customer/external/1 { "name": "John Doe" }

PUT 和 POST 都可以, POST 新增。如果不指定 id,会自动生成 id。指定 id 就会修改这个数据,并新增版本号 PUT 可以新增可以修改。PUT 必须指定 id;由于 PUT 需要指定 id,我们一般都用来做修改 操作,不指定 id 会报错。
3.查询指定文档 GET customer/external/1
结果
全文检索|初步检索及进阶检索
文章图片

1.查询索引信息
GET customer
2.查询对应索引下所有数据
GET customer/external/_search GET(customer/_search)
返回结果
全文检索|初步检索及进阶检索
文章图片

4.更新文档
POST customer/external/1/_update { "doc":{ "name": "John Doew" } }

5.删除文档和索引 DELETE customer/external/1 //删除文档
DELETE customer //删除索引
返回数据:
全文检索|初步检索及进阶检索
文章图片

6.bulk 批量 API
POST customer/external/_bulk {"index":{"_id":"1"}} {"name": "John Doe" } {"index":{"_id":"2"}} {"name": "Jane Doe" }

返回数据
全文检索|初步检索及进阶检索
文章图片

3.进阶检索 1.检索信息
GET bank/_search { //查询条件 "query": { "match_all": {} }, //检索条件 "sort": [ { "account_number": { "order": "desc" //按照auuount_number降序排列 } } ] }

结果:默认返回10条数据
全文检索|初步检索及进阶检索
文章图片

响应结果解释:
took - Elasticsearch 执行搜索的时间(毫秒)
time_out - 告诉我们搜索是否超时
_shards - 告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片
hits - 搜索结果 hits.total - 搜索结果
hits.hits - 实际的搜索结果数组(默认为前 10 的文档)
sort - 结果的排序 key(键)(没有则按 score 排序)
score 和 max_score –相关性得分和最高得分(全文检索用)
2.Query DSL 1.基本语法格式
GET bank/_search { "query": { "match_all": {} }, "from": 0, "size": 5, "sort": [ { "account_number": { "order": "desc" } } ] }

query 定义如何查询,
match_all 查询类型【代表查询所有的所有】,es 中可以在 query 中组合非常多的查 询类型完成复杂查询
除了 query 参数之外,我们也可以传递其它的参数以改变查询结果。如 sort,size
from+size 限定,完成分页功能
sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准
2.只返回部分字段
GET bank/_search { "query": { "match_all": {} }, "from": 0, "size": 5, "_source": [ "age", "balance" ] }

全文检索|初步检索及进阶检索
文章图片

3.match【匹配查询】 1.基本类型(非字符串),精确匹配
只返回account_number为20的数据
GET bank/_search { "query": { "match": { "account_number": "20" } } }

返回:
全文检索|初步检索及进阶检索
文章图片

2.字符串,全文检索
GET bank/_search { "query": { "match": { "address": "mill" } } }

返回
全文检索|初步检索及进阶检索
文章图片

最终查询出 address 中包含 mill 单词的所有记录 match 当搜索字符串类型的时候,会进行全文检索,并且每条记录有相关性得分。
3.字符串,多个单词(分词+全文检索)
GET bank/_search { "query": { "match": { "address": "mill road" } } }

全文检索|初步检索及进阶检索
文章图片

最终查询出 address 中包含 mill 或者 road 或者 mill road 的所有记录,并给出相关性得分。
4.match_phrase【短语匹配】
GET bank/_search { "query": { "match_phrase": { "address": "mill road" } } }

返回
全文检索|初步检索及进阶检索
文章图片

查出 address 中包含 mill road 的所有记录,并给出相关性得分
5.multi_match【多字段匹配】
GET bank/_search { "query": { "multi_match": { "query": "mill", "fields": [ "state", "address" ] } } }

全文检索|初步检索及进阶检索
文章图片

查出state 或者 address 包含 mill的数据
6.bool【复合查询】
GET bank/_search { "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "gender": "M" } } ], "should": [ { "match": { "address": "lane" } } ], "must_not": [ { "match": { "email": "baluba.com" } } ] } } }

全文检索|初步检索及进阶检索
文章图片

会查出address包含mill(必须),并且gender 是 M(必须),如果address(非必须) 里面有lane最好不过,但是email(必须没有) 必须不包含baluba.com的数据。
7.filter【结果过滤】
并不是所有的查询都需要产生分数,特别是那些仅用于 “filtering”(过滤)的文档。为了不计算分数 Elasticsearch 会自动检查场景并且优化查询的执行。
GET bank/_search { "query": { "bool": { "must": [ { "match": { "address": "mill" } } ], "filter": { "range": { "balance": { "gte": 1000, "lte": 50000 } } } } } }

8.term
和 match 一样。匹配某个属性的值。全文检索字段用 match,其他非 text 字段匹配用 term。
GET bank/_search { "query": { "bool": { "must": [ { "term": { "age": { "value": "28" } } }, { "match": { "address": "990 Mill Road" } } ] } } }

9.aggregations(执行聚合)
size:0 不显示搜索数据
aggs:执行聚合。聚合语法如下
“aggs”: {
“aggs_name 这次聚合的名字,方便展示在结果集中”:
{ “AGG_TYPE 聚合的类型(avg,term,terms)”: {} } },
GET bank/_search { "query": { "match": { "address": "mill" } }, "aggs": { "group_by_state": { //聚合的名字 "terms": {//聚合方式 "field": "age" //聚合的字段 } }, "avg_age": {//第二个聚合的名字 "avg": {//聚合方式 "field": "age"//聚合的字段 } } }, "size": 0 }

全文检索|初步检索及进阶检索
文章图片

搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情。
按照年龄聚合,并且请求这些年龄段的这些人的平均薪资(聚合嵌套)
GET bank/account/_search { "query": { "match_all": {} }, "aggs": { "age_avg": { //父聚合名字 "terms": { //父聚合方式 "field": "age", //父聚合的字段 "size": 1000 }, "aggs": {//子聚合 "banlances_avg": { //子聚合名字 "avg": {//子聚合方式 "field": "balance"//子聚合字段 } } } } }, "size": 1000 }

全文检索|初步检索及进阶检索
文章图片

查出所有年龄分布,并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄 段的总体平均薪资
GET bank/account/_search { "query": { "match_all": {} }, "aggs": { "age_agg": { //根据年龄聚合 求出各个年龄段的人数 "terms": { "field": "age", "size": 100 }, "aggs": { "gender_agg": { //每个年龄段再根据性别聚合 求出每个年龄段 男和女的人数 "terms": { "field": "gender.keyword", "size": 100 }, "aggs": { "balance_avg": {//每个年龄段的性别再根据工资聚合 "avg": { "field": "balance" } } } }, "balance_avg": {//年龄段根据工资聚合 "avg": { "field": "balance" } } } } }, "size": 1000 }

结果返回(其中的一条)
全文检索|初步检索及进阶检索
文章图片

4.Mapping 映射 Mapping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和 索引的。
哪些字符串属性应该被看做全文本属性(full text fields)。
哪些属性包含数字,日期或者地理位置。
文档中的所有属性是否都能被索引(_all 配置)。
日期的格式。
自定义映射规则来执行动态添加属性。
查看 mapping 信息:GET bank/_mapping
Es7 及以上移除了 type 的概念。 (也就是移除了表的概念,数据直接存在索引下 也就是数据库下)
关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用, 但 ES 中不是这样的。elasticsearch 是基于 Lucene 开发的搜索引擎,而 ES 中不同 type 下名称相同的 filed 最终在 Lucene 中的处理方式是一样的。
两个不同 type 下的两个 user_name,在 ES 同一个索引下其实被认为是同一个 filed, 你必须在两个不同的 type 中定义相同的 filed 映射。否则,不同 type 中的相同字段 名称就会在处理中出现冲突的情况,导致 Lucene 处理效率下降。
去掉 type 就是为了提高 ES 处理数据的效率。
Elasticsearch 7.x : URL 中的 type 参数为可选。比如,索引一个文档不再要求提供文档类型。 Elasticsearch 8.x :不再支持 URL 中的 type 参数。
解决:将已存在的索引下的类型数据,全部迁移到指定位置即可。详见数据迁移
1.创建索引并指定映射
PUT /my-index { "mappings": { "properties": { "age": { "type": "integer" }, "email": { "type": "keyword" }, "name": { "type": "text" } } } }

2.添加新的字段映射
PUT /my-index/_mapping { "properties": { "employee-id": { "type": "keyword", "index": false } } }

3.更新映射
对于已经存在的映射字段,我们不能更新。更新必须创建新的索引进行数据迁移
4.数据迁移
先创建出 new_twitter 的正确映射。然后使用如下方式进行数据迁移
POST _reindex { "source": { "index": "twitter" }, "dest": { "index": "new_twitter" } }

【全文检索|初步检索及进阶检索】将旧索引的 type 下的数据进行迁移
POST _reindex { "source": { "index": "twitter", "type": "tweet" //指定好原来的type (表) }, "dest": { "index": "tweets" } }

    推荐阅读