经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Elasticsearch » 查看文章
ES 21 - Elasticsearch的高级检索语法 (包括term、prefix、wildcard、fuzzy、boost等)
来源:cnblogs  作者:瘦风  时间:2019/6/28 19:06:10  对本文有异议

1 term query - 索引词检索

1.1 term query - 不分词检索

term query: 把检索串当作一个整体来执行检索, 即不会对检索串分词.

term是完全匹配检索, 要用在不分词的字段上, 如果某个field在映射中被分词了, term检索将不起作用.
所以, 不分词的field, 要在mapping中设置为不分词.

—— ES 5.x之后, 为每个text类型的字段新增了名为keyword的子字段, 是不分词的, 默认保留256个字符.

—— 可以使用keyword字段进行term检索. 示例:

  1. GET shop/_search
  2. {
  3. "query": {
  4. "term": {
  5. "name.keyword": "Java编程思想"
  6. }
  7. }
  8. }

1.2 terms query - in检索

terms, 相当于多个term检索, 类似于SQL中in关键字的用法, 即在某些给定的数据中检索:

  1. GET shop/_search
  2. {
  3. "query": {
  4. "terms": {
  5. "name.keyword": [
  6. "Java编程思想", "Java并发编程的艺术"
  7. ]
  8. }
  9. }
  10. }

2 prefix query - 前缀检索

prefix query, 就是前缀检索. 比如商品name中有多个以"Java"开头的document, 检索前缀"Java"时就能检索到所有以"Java"开头的文档.

—— 扫描所有倒排索引, 性能较差.

  1. GET shop/_search
  2. {
  3. "query": {
  4. "prefix": { "name": "java" }
  5. }
  6. }

3 wildcard query - 通配符检索

扫描所有倒排索引, 性能较差.

  1. GET shop/_search
  2. {
  3. "query": {
  4. "wildcard": { "name": "ja*" }
  5. }
  6. }

4 regexp query - 正则检索

扫描所有倒排索引, 性能较差.

  1. GET shop/_search
  2. {
  3. "query": {
  4. "regexp": { "name": "jav[a-z]*" }
  5. }
  6. }

5 fuzzy query - 纠错检索

fuzziness的默认值是2 —— 表示最多可以纠错两次.

说明: fuzziness的值太大, 将削弱检索条件的作用, 也就是说纠错次数太多, 就会导致限定检索结果的检索条件被改变, 失去了限定作用.

示例: 检索name中包含"Java"的文档, Java中缺失了一个字母a:

  1. GET shop/_search
  2. {
  3. "query": {
  4. "match": {
  5. "name": {
  6. "query": "Jav",
  7. "fuzziness": 1,
  8. "operator": "and"
  9. }
  10. }
  11. }
  12. }

6 boost评分权重 - 控制文档的优先级别

通过boost参数, 令满足某个条件的文档的得分更高, 从而使得其排名更靠前.

  1. GET shop/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": [
  6. { "match": { "name": "编程思想"} }
  7. ],
  8. "should": [
  9. {
  10. "match": {
  11. "name": {
  12. "query": "艺术",
  13. "boost": 2 // 提升评分权重
  14. }
  15. }
  16. }
  17. ]
  18. }
  19. }
  20. }

7 dis_max的用法 - best fields策略

一般检索中, 检索条件会被分词, bool检索构建多个子检索 (must | must_not | should | filter), 这些子检索可能会包含多个field. 这时:

多个子检索的field各自匹配少量关键字的文档的分数 > 某个子检索的field匹配大量关键字的文档的分数.

7.1 dis_max的提出

如果我们希望检索结果中 (检索串被分词后的) 关键字匹配越多, 这样的文档就越靠前, 而不是多个子检索中匹配少量分词的文档靠前.

? 此时可以使用dis_max和tie_breaker.

tie_breaker的值介于0~1之间, Elasticsearch将 bool检索的分数 * tie_breaker的结果与dis_max的最高分进行比较, 除了取dis_max的最高分以外, 还会考虑其他的检索结果的分数.

7.2 使用示例

为了增加精准度, 常用的是配合boost、minimum_should_match等参数控制检索结果.

  1. GET shop/_search
  2. {
  3. "query": {
  4. "dis_max": {
  5. "queries": [
  6. { "match": { "name": "虚拟机" } },
  7. { "match": { "desc": "经典" } }
  8. ],
  9. "tie_breaker": 0.2 // 对同时满足的文档的分值进行提升
  10. }
  11. }
  12. }
  13. GET shop/_search
  14. {
  15. "query": {
  16. "dis_max": {
  17. "queries": [
  18. {
  19. "match": {
  20. "name": {
  21. "query": "虚拟机",
  22. "minimum_should_match": "50%",
  23. "boost": 2
  24. }
  25. }
  26. },
  27. {
  28. "match": {
  29. "desc": {
  30. "query": "经典",
  31. "minimum_should_match": "50%",
  32. "boost": 3
  33. }
  34. }
  35. }
  36. ],
  37. "tie_breaker": 0.3
  38. }
  39. }
  40. }

8 exist query - 存在检索, 已过期

这是Elasticsearch 2.x中的API, 后续版本不再支持.

9 复杂检索的使用范例

9.1 多条件过滤 - 包含

检索出版时间在2012-07之后, 且至少满足下述条件中一个的文档:

a. 名称(name)中包含"并发";

b. 描述(desc)中包含"java";

c. 出版社(publisher)名称中不包含"电子".

  1. GET shop/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": { // 按时间过滤
  6. "range": {
  7. "date": {"gte": "2012-07"}
  8. }
  9. },
  10. "should": [ // 可匹配, 可不匹配
  11. {
  12. "match": { "name": "并发" }
  13. },
  14. {
  15. "bool": {
  16. "must": { // 必须匹配
  17. "match": { "desc": "java" }
  18. },
  19. "must_not": { // 不能匹配
  20. "match": { "publisher": "电子" }
  21. }
  22. }
  23. }
  24. ],
  25. "minimum_should_match": 1 // 至少满足should中的一个条件
  26. }
  27. },
  28. // 自定义排序
  29. "sort": [
  30. { "price": { "order": "desc" } }
  31. ]
  32. }

注意: 排序的字段最好是数字, 或日期, 因为字符串字段会被分词, ES会通过分词后的某个词去排序, 结果难以预测.

9.2 多条件拼接 - 包含+范围+排序

匹配检索: name中包含"java"却不包含"虚拟机";
范围检索: 价格大于50、小于80;
结果排序: 按照价格升序排序.

  1. GET shop/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "must": { // 必须匹配
  6. "match": { "name": "java" }
  7. },
  8. "must_not": { // 必须不匹配
  9. "match": { "name": "虚拟机" }
  10. },
  11. "filter": {
  12. "range": {
  13. "price": {
  14. "gte": 40,
  15. "lte": 80,
  16. "boost": 2.0 // 设置得分的权重值(提升值), 默认是1.0
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }

关于范围检索的使用, 请参考下篇文章: ES 22 - Elasticsearch对数值或日期类型进行范围检索

9.3 定制检索结果的排序规则

(1) 默认排序规则:

ES默认是按检索结果的分值(_score)降序排列的.

某些情况下, 可能存在无实际意义的_score, 比如filter时所有_score的值都相同:

  1. GET website/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "filter": {
  6. "term": {
  7. "author_id": 5520 // 此时所有符合条件的_score都为0
  8. }
  9. }
  10. }
  11. }
  12. }
  13. // 或通过constant_score过滤:
  14. GET website/_search
  15. {
  16. "query": {
  17. "constant_score": {
  18. "filter": {
  19. "term": {
  20. "author_id": 5520 // 此时所有符合条件的_score都为1
  21. }
  22. }
  23. }
  24. }
  25. }

(2) 定制排序规则:

  1. GET website/_search
  2. {
  3. "query": {
  4. "constant_score": {
  5. "filter": {
  6. "term": {
  7. "author_id": 5520
  8. }
  9. }
  10. }
  11. },
  12. "sort": [
  13. {
  14. "post_date": { "order": "asc" }
  15. }
  16. ]
  17. }

版权声明

作者: 马瘦风(https://healchow.com)

出处: 博客园 马瘦风的博客(https://www.cnblogs.com/shoufeng)

感谢阅读, 如果文章有帮助或启发到你, 点个[好文要顶??] 或 [推荐??] 吧??

本文版权归博主所有, 欢迎转载, 但 [必须在文章页面明显位置标明原文链接], 否则博主保留追究相关人员法律责任的权利.

原文链接:http://www.cnblogs.com/shoufeng/p/11103913.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号