倒排索引(了解)

查看所有的表(es中没有库的概念)

GET _cat/indices
image.png

查看某个表的详细信息(如字段信息)

GET account

删除表

DELETE account

新增数据

1.通过put+id新建数据

该方法如果id不存在的话就会新建, 存在的话就会更新数据

  1. // acount是表名, _doc意思是文档, 目前这个写法是固定的, 1id
  2. PUT /account/_doc/1
  3. {
  4. "name": "Felix",
  5. "age": 18,
  6. "company": [
  7. {
  8. "name": "tencent",
  9. "address": "深圳"
  10. },
  11. {
  12. "name": "alibaba",
  13. "address": "杭州"
  14. }
  15. ]
  16. }

image.png

2.通过post新建数据

  1. POST /user/_doc
  2. {
  3. "name": "Felix",
  4. "age": 18,
  5. "company": [
  6. {
  7. "name": "tencent",
  8. "address": "深圳"
  9. },
  10. {
  11. "name": "alibaba",
  12. "address": "杭州"
  13. }
  14. ]
  15. }

3.通过post+id新建数据

效果同put+id一样

4.通过post+_create新建数据

没有就新建, 有就报错
POST /account/_create/1
image.png

查询数据

1.查询某一条数据的详细信息(包括版本号等)

GET /account/_doc/1

2.查询某一条数据的内容

GET /account/_source/1

3.通过url查询数据(不推荐)

GET _search?q=Felix // 查询所有表
GET user/_search?q=Felix // 查询user表

4.通过request body查询数据

  1. // 查询所有数据
  2. GET account/_search
  3. {
  4. "query": {
  5. "match_all": {}
  6. }
  7. }


更新数据

  1. POST account/_update/1
  2. {
  3. "doc": {
  4. "company" : [
  5. {
  6. "name" : "zhongkeyuan",
  7. "address" : "北京"
  8. }
  9. ]
  10. }
  11. }
  12. // company里面所有的内容都会被替换(如果数组里面有2条数据, 那么会替换成"北京"这一条)
  13. // 此方法会检查数据库里面的数据和需要更新的数据是否一样, 如果一样, 则不会做任何操作(_version_seq_no的数字不会变)

删除数据

DELETE account/_doc/2
image.png

批量操作

批量操作数据

  1. POST _bulk
  2. // 索引(查询)
  3. { "index": { "_index": "test", "_id": "1" } }
  4. { "field1": "value1" }
  5. // 删除
  6. { "delete": { "_index": "test", "_id": "2" } }
  7. // 新增
  8. { "create": { "_index": "test", "_id": "3" } }
  9. { "field3": "value3" }
  10. // 更新
  11. { "update": { "_index": "test", "_id": "1" } }
  12. { "doc": { "field3": "value3" } }

聚合查询mget

  1. // 分别从useraccount中查询数据
  2. GET _mget
  3. {
  4. "doc": [
  5. {
  6. "_index": "user",
  7. "_id": 1,
  8. },
  9. {
  10. "_index": "account",
  11. "_id": 2,
  12. }
  13. ]
  14. }

1.全文查询

1.全文查询(match)[匹配查询]

  1. // 对于es来说 fromsize分页在数据量比较小的情况下可行, 数据量大的时候会影响性能, 使用scroll
  2. GET account/_search
  3. {
  4. "query": {
  5. "match_all": {}
  6. },
  7. "from": 4,
  8. "size": 4
  9. }
  10. GET /_search
  11. {
  12. "query": {
  13. "match": {
  14. "address": "广场"
  15. }
  16. }
  17. }

image.png

1.短语查询(match_phrase)

  1. // Madison street会作为一个整体, 如果分开就不会查出来
  2. GET user/_search
  3. {
  4. "query": {
  5. "match_phrase": {
  6. "address": "Madison street"
  7. }
  8. }
  9. }

2.通过multi_match指定查询字段权重

  1. POST resume/_doc/12
  2. {
  3. "title": "后端工程师",
  4. "desc": "多年go语言经验, 熟悉go的基本语法, 熟悉常用go语言库",
  5. "want_learn": "python语言"
  6. }
  7. POST resume/_doc/13
  8. {
  9. "title": "go工程师",
  10. "desc": "多年开发经验, 熟悉go的基本语法, 熟悉常用go语言库",
  11. "want_learn": "java语言"
  12. }
  13. POST resume/_doc/14
  14. {
  15. "title": "后端工程师",
  16. "desc": "多年go语言经验, 熟悉go的基本语法, 熟悉常用go语言库",
  17. "want_learn": "python语言"
  18. }
  19. POST resume/_doc/15
  20. {
  21. "title": "后端工程师",
  22. "desc": "多年开发经验",
  23. "want_learn": "rust语言"
  24. }
  25. GET resume/_search
  26. {
  27. "query": {
  28. "multi_match": {
  29. "query": "go",
  30. "fields": ["title", "desc"]
  31. // "fields": ["title^3", "desc"] 设置权重(权重分会x2)
  32. }
  33. }
  34. }

image.png

4.query_string

  1. GET account/_search
  2. {
  3. "query": {
  4. "query_string": {
  5. "default_field": "address", // 加上这行会只在address字段进行查询
  6. "query": "广场" // 可以使用ANDOR连接符
  7. }
  8. }
  9. }


2.term查询

  1. GET user/_search
  2. {
  3. "query": {
  4. "term": {
  5. "address": "madison street"
  6. }
  7. }
  8. }

range查询

  1. GET user/_search
  2. {
  3. "query": {
  4. "range": {
  5. "age": {
  6. "gte": 10,
  7. "lte": 20,
  8. "boost": 2.0
  9. }
  10. }
  11. }
  12. }

exist查询

  1. // 查询包含age字段的数据
  2. GET user/_search
  3. {
  4. "query": {
  5. "exist": {
  6. "field": "age"
  7. }
  8. }
  9. }

fuzzy模糊查询

  1. GET /_search
  2. {
  3. "query": {
  4. "fuzzy": {
  5. "user.id": {
  6. "value": "ki"
  7. }
  8. }
  9. }
  10. }

3.bool复合查询(must, should, must_not, filter)

  1. {
  2. "quey": {
  3. "bool": {
  4. "must": [], // 条件必须满足
  5. "should": [], // 可满足可不满足, 满足会加分
  6. "must_not": [], // 条件必须不满足
  7. "filter": [] // 将结果进行过滤
  8. }
  9. }
  10. }
  11. // must: 必须匹配, 查询上下文, 加分
  12. // should: 应该匹配, 查询上下文, 加分
  13. // must_not: 必须不匹配, 过滤上下文, 过滤
  14. // filter: 必须匹配, 过滤上下文, 过滤
  15. // 示例
  16. GET user/_search
  17. {
  18. "query": {
  19. "bool": {
  20. "must": [
  21. {
  22. "term": {
  23. "country": {
  24. "value": "china"
  25. }
  26. // 这里也可以直接简写成 "country": "china" 注意term查询如果录入数据的时候没有做term那就要写成小写, 因为倒排索引会把所有字母转成小写
  27. },
  28. },
  29. {
  30. "range": {
  31. "age": {
  32. "gte": 20,
  33. "lte": 30
  34. }
  35. }
  36. }
  37. ],
  38. "must_not": [
  39. {
  40. "term": {
  41. "gender": "m" // 过滤掉genderM的人
  42. }
  43. }
  44. ],
  45. "should": [
  46. {
  47. "match": {
  48. "firstname": "Felix" // 不会影响结果条数, 但是满足firstnamefelix的结果分数会高一些
  49. }
  50. }
  51. ],
  52. // 在原来的结果上过滤, 但是不影响评分(相当于所有的数据还是原来的, 只是把复合条件的结果拿出来而已)
  53. "filter": [
  54. {
  55. "range": {
  56. "age": {
  57. "gte": 20,
  58. "lte": 30
  59. }
  60. }
  61. }
  62. ]
  63. }
  64. }
  65. }

mapping

  1. PUT usertest
  2. {
  3. "mappings": {
  4. "properties": {
  5. "age": {
  6. "type": "integer"
  7. },
  8. "name": {
  9. "type": "keyword" // 不会分词
  10. },
  11. "desc": {
  12. "type": "text" // 会分词
  13. }
  14. }
  15. }
  16. }

测试

  1. // 新建mappings
  2. PUT usertest
  3. {
  4. "mappings": {
  5. "properties": {
  6. "age": {
  7. "type": "integer"
  8. },
  9. "name": {
  10. "type": "keyword"
  11. },
  12. "desc": {
  13. "type": "text"
  14. }
  15. }
  16. }
  17. }
  18. // 查看mappings
  19. GET usertest
  20. // 插入数据
  21. POST usertest/_doc
  22. {
  23. "age": 18,
  24. "name": "Felix Chan",
  25. "desc": "He is a good guy!He is handsome!He is great!"
  26. }
  27. GET usertest/_search
  28. {
  29. "query": {
  30. "match": {
  31. "name": "Felix" // 获取不到, 因为设置了typekeyword不会分词
  32. // "name": "Felix" // 可以获取
  33. }
  34. }
  35. }
  36. GET usertest/_search
  37. {
  38. "query": {
  39. "match": {
  40. "desc": "he good" // 可以获取, 因为已经text会分词
  41. }
  42. }
  43. }

analyzer查询过程

  1. GET _analyze
  2. {
  3. "analyzer": "standard",
  4. "text": "The 2 QUIKC Red-Fox jumped over the bridge!"
  5. }
  6. // standard: 标准分词器, 按词切分, 小写处理
  7. // simple: 简单分词器, 按照非字母切分(符号被过滤), 小写处理
  8. // stop: 小写吹李, 停用词过滤(the, a, is...)
  9. // whitespace: 空格分词器, 不转小写
  10. // keyword: 不做分词
  11. // patter: 正则表达式, 默认\W+
  12. // 语言分词器: 提供了30多重常见语言的分词器
  13. //

新建mapping的时候指定analyzer

  1. PUT usertest
  2. {
  3. "mappings": {
  4. "properties": {
  5. "age": {
  6. "type": "integer",
  7. "analyzer": "whitespace", // 指定存储的时候用什么analyzer
  8. "search_analyzer": "simple" // 指定搜索的时候用什么analyzer
  9. }
  10. }
  11. }
  12. }
  13. // 使用顺序

搜索的时候指定analyzer

  1. GET user/_search
  2. {
  3. "query": {
  4. "match": {
  5. "desc": {
  6. "query": "Felix Chan",
  7. "analyzer": "keyword"
  8. }
  9. }
  10. }
  11. }

查看setting中的默认analyzer

GET user
查看setting字段

查询的时候使用analyzer的顺序

1.先使用search的时候指定的analyzer
2.如果1不存在, 使用存储的时候search_analyzer指定的analyzer
3.如果2不存在, 使用存储的时候analyzer指定的analyzer
4.如果3不存在, 使用的setting中指定的analyzer
如果以上都不存在, 则使用标准的analyzer

ik分词器的安装和配置

github下载地址: https://github.com/medcl/elasticsearch-analysis-ik
1.下载对应版本的ik
image.png
2.解压并且重命名为ik并放到docker-elasticsearch的plugins目录下
image.pngimage.pngimage.png
image.png
3.修改ik目录的权限chmod 777 -R ik
4.重启容器: docker-compose restart

试用

ik有两个分词器”ik_smark”、”ik_max_word”

  1. GET _analyze
  2. {
  3. "text": "中华牙膏",
  4. "analyzer": "ik_smart"
  5. }
  6. GET _analyze
  7. {
  8. "text": "中华牙膏",
  9. "analyzer": "ik_max_word"
  10. }
  11. GET _analyze
  12. {
  13. "text": "中国科学技术大学",
  14. "analyzer": "ik_max_word"
  15. }

image.png

自定义分词词库

1.cd到docker-elasticsearch/plugins/ik/config目录
2.mkdir custom
3.新建两个文件
vim mydic.dic // 用于存放用户词库
vim extra_stop_word.dic // 用于存放停用词(的, 是, 又…)
4.回到docker-elasticsearch/plugins/ik/config目录
打开配置文件vim IKAnalyzer.cfg.xml
image.png
image.png
配置路径
image.png
5.重启elasticsearchdocker-compose restart