1. keyword

用于索引结构化内容(如电子邮件地址、主机名、状态码、邮政编码或标记)的字段。
通常用于筛选(查找发布状态为已发布的所有博客文章)、排序和聚合。keyword字段只能按其精确值进行搜索。(为整个字段值建立索引,而不会对其进行分词)

2. text

使用text类型定义的字段,es在建立索引的时候,会对该字段值进行分词(使用默认的分词器,或用户指定的分词器)。

3. 实例理解keyword和text的区别

3.1 建立一个索引,构造测试数据

索引名称my-test,索引类型为shops。
其中,shop_name字段类型为keyword类型(不分词),business_desc字段类型为text类型,采用ik_max_word分词器进行分词。

  1. PUT /my-test
  2. {
  3. "mappings":{
  4. "shops":{
  5. "properties":{
  6. "shop_id":{"type":"long"},
  7. "shop_name":{"type":"keyword"},
  8. "business_desc":{
  9. "type":"text",
  10. "analyzer":"ik_max_word"
  11. },
  12. "members":{
  13. "type":"nested",
  14. "dynamic":false,
  15. "properties":{
  16. "member_id":{"type":"long"},
  17. "member_name":{"type":"keyword"}
  18. }
  19. }
  20. }
  21. }
  22. }
  23. }

构造两个测试数据:

  1. PUT /my-test/shops/1
  2. {
  3. "ship_id" : 10000001,
  4. "shop_name": "王尼玛的电器小店",
  5. "business_desc": "主营:家用电器、电脑设备、办公设备、安防设备、手机、耳机等",
  6. "members" : [
  7. {
  8. "member_id" :1,
  9. "member_name" : "王大大"
  10. },
  11. {
  12. "member_id" : 2,
  13. "member_name" : "王二二"
  14. }
  15. ]
  16. }
  1. PUT /my-test/shops/2
  2. {
  3. "ship_id" : 10000002,
  4. "shop_name": "王大锤的创意小店",
  5. "business_desc": "主营:创意品,饰品,房间挂件,汽车挂件",
  6. "members" : [
  7. {
  8. "member_id" :1,
  9. "member_name" : "张三"
  10. },
  11. {
  12. "member_id" : 2,
  13. "member_name" : "李四"
  14. }
  15. ]
  16. }

3.2 keyword字段查询(不分词)

3.2.1 测试实例1

以“王尼玛”为搜索内容,搜索shop_name为“王尼玛”的数据:

  1. GET /my-test/shops/_search
  2. {
  3. "query":{
  4. "bool":{
  5. "filter":{"term":{"shop_name":"王尼玛"}}
  6. }
  7. }
  8. }

查询结果:匹配到 0 个文档,因为 shop_name 只有一个 “王尼玛的电器小店” 倒排索引

  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 5,
  6. "successful" : 5,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : 0,
  12. "max_score" : null,
  13. "hits" : [ ]
  14. }
  15. }

3.2.2 测试实例2

搜索shop_name为“王尼玛的电器小店”的文档:

  1. GET /my-test/shops/_search
  2. {
  3. "query":{
  4. "bool":{
  5. "filter":{"term":{"shop_name":"王尼玛的电器小店"}}
  6. }
  7. }
  8. }

查询结果:匹配到 1 个文档,因为 shop_name 有一个 “王尼玛的电器小店” 倒排索引

  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 5,
  6. "successful" : 5,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : 1,
  12. "max_score" : 0.0,
  13. "hits" : [
  14. {
  15. "_index" : "my-test",
  16. "_type" : "shops",
  17. "_id" : "1",
  18. "_score" : 0.0,
  19. "_source" : {
  20. "ship_id" : 10000001,
  21. "shop_name" : "王尼玛的电器小店",
  22. "business_desc" : "主营:家用电器、电脑设备、办公设备、安防设备、手机、耳机等",
  23. "members" : [
  24. {
  25. "member_id" : 1,
  26. "member_name" : "王大大"
  27. },
  28. {
  29. "member_id" : 2,
  30. "member_name" : "王二二"
  31. }
  32. ]
  33. }
  34. }
  35. ]
  36. }
  37. }

3.3 text字段查询(分词:ik_max_word)

3.3.1 测试实例1

搜索business_desc(主营描述信息)包含手机和汽车挂件的文档:采用match(会对检索条件分词)

  1. GET /my-test/shops/_search
  2. {
  3. "query":{
  4. "bool":{
  5. "filter":{"match":{"business_desc":"手机和汽车挂件"}}
  6. }
  7. }
  8. }

查询结果:匹配到 2 个文档,因为 business_desc字段定义类型为text类型,使用分词器为ik_max_word,es在保存文档的时候,business_desc的内容会被分词器ik_max_word按照分词规则拆分成:家用、电器、电脑、设备、办公、安防、手机、耳机等词后建立倒排索引。

  1. {
  2. "took" : 4,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 5,
  6. "successful" : 5,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : 2,
  12. "max_score" : 0.0,
  13. "hits" : [
  14. {
  15. "_index" : "my-test",
  16. "_type" : "shops",
  17. "_id" : "2",
  18. "_score" : 0.0,
  19. "_source" : {
  20. "ship_id" : 10000002,
  21. "shop_name" : "王大锤的创意小店",
  22. "business_desc" : "主营:创意品,饰品,房间挂件,汽车挂件",
  23. "members" : [
  24. {
  25. "member_id" : 1,
  26. "member_name" : "张三"
  27. },
  28. {
  29. "member_id" : 2,
  30. "member_name" : "李四"
  31. }
  32. ]
  33. }
  34. },
  35. {
  36. "_index" : "my-test",
  37. "_type" : "shops",
  38. "_id" : "1",
  39. "_score" : 0.0,
  40. "_source" : {
  41. "ship_id" : 10000001,
  42. "shop_name" : "王尼玛的电器小店",
  43. "business_desc" : "主营:家用电器、电脑设备、办公设备、安防设备、手机、耳机等",
  44. "members" : [
  45. {
  46. "member_id" : 1,
  47. "member_name" : "王大大"
  48. },
  49. {
  50. "member_id" : 2,
  51. "member_name" : "王二二"
  52. }
  53. ]
  54. }
  55. }
  56. ]
  57. }
  58. }

3.3.2 测试实例2

搜索business_desc(主营描述信息)包含手机和汽车挂件的文档:term(检索条件不分词)

  1. GET /my-test/shops/_search
  2. {
  3. "query":{
  4. "bool":{
  5. "filter":{"term":{"business_desc":"手机和汽车挂件"}}
  6. }
  7. }
  8. }

查询结果:匹配到 0 个文档,因为term查询不会对检索条件进行分词

  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 5,
  6. "successful" : 5,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : 0,
  12. "max_score" : null,
  13. "hits" : [ ]
  14. }
  15. }

3.4 小结

shop_name 字段的类型是 keyword,ES 在为该字段建立索引的时候,会为整个字段值建立索引,而不会对其进行分词,例如某个店铺名称是“王大锤的创意品小店”,ES 的倒排索引会建立针对“王大锤的创意品小店”的倒排索引。
business_desc 字段类型是 text,ES 在为该字段建立索引时,会首先对字段值进行分词(使用默认的分词器,或用户指定的分词器),例如某个店铺的经营描述是“创意品,饰品,房间挂件,汽车挂件”,ES 会为创意品、饰品、房间、挂件、汽车、挂件等都建立倒排索引

term 将被检索词作为一个名词在指定字段上进行检索(不对被检索词进行分词操作),match 则将被检索词进行分词后在指定字段上进行检索。