为什么使用ES

传统的数据库查询,假如现在有一个商品表
image.png
需求1:从 title 获取包含“手机”的数据
select * from goods where title like ‘%手机%’
这个sql存在的问题:

  • 使用like时,以‘%’开头,会导致索引失效,这时候全表扫描,效率低
    而且,如果表中数据太多,比如:1亿条,假设1秒钟查询十万,也需要1000秒,速度慢

需求2:从 title 获取包含“华为手机”的数据
select * from goods where title like ‘%华为手机%’,这个sql根本就查不出来
总结,使用数据库查询

  • 效率低
  • 功能弱

ES能解决这些的问题

两种索引

假设有一本古诗集,包含

  1. 《静夜思》
  2. 窗前明月光,疑是地上霜。
  3. 举头望明月,低头思故乡。
  4. 《水调歌头》
  5. 明月几时有?把酒问青天。
  6. 不知天上宫阙,今夕是何年?
  7. .....
  8. 《月下独酌四首》
  9. 花间一壶酒,独酌无相亲。
  10. 举杯邀明月,对影成三人。
  11. .....

需求:找出这本书中包含“明月”的古诗

正向索引

搜索逻辑:先看《静夜思》里有没有“明月”,有就记录,再看《水调歌头》里有没有“明月”,有就记录。。。。
就这样一首一首的判断下去,很明显效率很慢

反向索引

又称:倒排索引,按照规则,对文本内容进行分词,拆分出不同的词条(term)
比如:床前明月光,就可能分成:床前、明月、光、月光 等词
所以它最终的索引结构:
image.png
这样就能根据“明月”快速的查询到对应古诗
总结:倒排索引,对文档内容进行分词,最终得出词条和文档唯一标示(文档id)的对应关系

ES的存储和搜索原理

image.png
ES中存在文档、索引库着两个概念

  • 文档经过分词后存到索引库
    • ES中的文档是json
  • 索引库存储着词条跟文档的对应关系,并向用户提供搜索服务

倒排索引建立的过程:

id title
1 华为 电信3G手机
2 三星 移动4G手机
  • id=1 的数据第一个存进来,分词后
    • image.png
  • 然后 id=2 的数据进来,分词后:三星、移动、4G、手机
    • 三星、移动、4G是新增的词条,手机是已存在的词条
    • image.png

就这样,文档以倒排索引的方式存放到索引库
同时也会对词条进行处理,形成树形结构,有点儿类似数据库中跟某个字段建立索引,目的是提高查询速度

查询时,如果用户输入“华为手机”

  • 先分词为:华为、手机
  • 根据这两个词条分别查询
  • 最后汇总结果,反馈用户

    ES和Mysql区别

  • mysql有事务,ES没有

  • ES没有外键,如果数据一致性要求高,还是要用Mysql

总结:mysql存储数据,ES搜索数据

Elasticvue-Index

打开 extension://geifniocjfnfilcbeloeidajlfmhdlgo/index.html#/cluster/0/rest

创建索引

创建Index = create table

  1. PUT /gb
  1. {
  2. "mappings": {
  3. "properties": {
  4. "tweet": {
  5. "type": "text"
  6. },
  7. "date": {
  8. "type": "date"
  9. },
  10. "name": {
  11. "type": "text"
  12. },
  13. "user_id": {
  14. "type": "long"
  15. }
  16. }
  17. }
  18. }

1664785105107.png

更新Index

更新Index-PUT = alert table

  1. PUT /gb/_mapping
  1. {
  2. "properties" : {
  3. "tag" : {
  4. "type" : "text"
  5. }
  6. }
  7. }

1664785374492.png

获取index

  1. GET /gb

1664785582728.png

删除index

  1. DELETE /test

1664785655002.png

Elasticvue-Doc

新增doc(自动生成文档id)

通过 POST index_name/_doc 系统会自动生成document id

  1. POST /longfc/_doc
  1. {
  2. "username": "xiaoming_new"
  3. }

返回

  1. {
  2. "_index": "longfc",
  3. "_id": "Uw4QnYMBUnW7A9JlFtkY",
  4. "_version": 1,
  5. "result": "created",
  6. "_shards": {
  7. "total": 3,
  8. "successful": 1,
  9. "failed": 0
  10. },
  11. "_seq_no": 0,
  12. "_primary_term": 1
  13. }

1664787498670.png

新增doc(指定文档id)

通过 PUT index_name/_create/doc_id ,例如doc_id为1,则可以指定id创建。如果该id对应的文档已经存在,则操作失败

  1. PUT /longfc/_create/1
  1. {
  2. "username": "xiaoming"
  3. }

返回

  1. {
  2. "_index": "longfc",
  3. "_id": "1",
  4. "_version": 1,
  5. "result": "created",
  6. "_shards": {
  7. "total": 3,
  8. "successful": 1,
  9. "failed": 0
  10. },
  11. "_seq_no": 0,
  12. "_primary_term": 1
  13. }

1664787127364.png

获取文档

  1. GET /longfc/_doc/1

返回

  1. {
  2. "_index": "longfc",
  3. "_id": "1",
  4. "_version": 1,
  5. "_seq_no": 0,
  6. "_primary_term": 1,
  7. "found": true,
  8. "_source": {
  9. "username": "xiaoming"
  10. }
  11. }

1664787602300.png
如里文档不存在,如以下查询

  1. GET /longfc/_doc/1333

则返回

  1. {
  2. "_index": "longfc",
  3. "_id": "1333",
  4. "found": false
  5. }

1664787669191.png

更新文档

  • Update方法不会删除原来的文档,是真正的更新数据
  • POST方法 / Payload需要包含在 doc
  • 可以用来新增字段
    1. POST /longfc/_update/1
    1. {
    2. "doc": {
    3. "fullname": "xiaoming_new_v3"
    4. }
    5. }
    返回
    1. {
    2. "_index": "longfc",
    3. "_id": "1",
    4. "_version": 2,
    5. "result": "updated",
    6. "_shards": {
    7. "total": 3,
    8. "successful": 1,
    9. "failed": 0
    10. },
    11. "_seq_no": 1,
    12. "_primary_term": 1
    13. }
    “_version”字段又增加了1
    1664787858811.png
    文档为1的其他内容如username还存在
    1664788071261.png