2019独角兽企业重金招聘Python工程师标准>>>

es种有两种查询模式,一种是像传递URL参数一样去传递查询语句,被称为简单搜索或查询字符串(query string)搜索,比如

GET /megacorp/employee/_search //查询全部员工

GET /megacorp/employee/_search?q=last_name:Smith //查询last_name为Smith的员工

另外一种是通过DSL语句来进行查询,被称为DSL查询(Query DSL),DSL是Elasticsearch提供的一种丰富且灵活的查询语言,该语言以json请求体的形式出现,通过restful请求与Elasticsearch进行交互,本文主要讲DSL查询的一些常用规则,在介绍之前,我们先简单插入一个测试用的小例子。

 $curl -XPOST http://localhost:9200/index/doc/1 -d'{"content":"美国留给伊拉克的是个烂摊子吗","title":"标题","tags":["美国","伊拉克","烂摊子"]}'$curl -XPOST http://localhost:9200/index/doc/2 -d'{"content":"中国是世界上人口最多的国家","title":"中国","tags":["中国","人口"]}'$curl -XPOST http://localhost:9200/index/doc/3 -d'{"content":"同一个世界同一个梦想","title":"北京奥运","tags":["和平"]}'$curl -XPOST http://localhost:9200/index/doc/4 -d'{"content":"杭州是一个美丽的城市,欢迎来到杭州","title":"宣传","tags":["旅游","城市"]}'

检查一下我们的数据是否导入成功

$curl -XGET http://localhost:9200/index/doc/_search

{"took":1,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":4,"max_score":1.0,"hits":[{"_index":"index","_type":"doc","_id":"2","_score":1.0,"_source":{"content":"中国是世界上人口最多的国家","title":"中国","tags":["中国","人口"]}},{"_index":"index","_type":"doc","_id":"4","_score":1.0,"_source":{"content":"杭州是一个美丽的城市,欢迎来到杭州","title":"宣传","tags":["旅游","城市"]}},{"_index":"index","_type":"doc","_id":"1","_score":1.0,"_source":{"content":"美国留给伊拉克的是个烂摊子吗","title":"标题","tags":["美国","伊拉克","烂摊子"]}},{"_index":"index","_type":"doc","_id":"3","_score":1.0,"_source":{"content":"同一个世界同一个梦想","title":"北京奥运","tags":["和平"]}}]}}

ok,导入成功,接下来利用这些数据逐步介绍各种常用查询

term查询

term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词,所以我们的搜索词必须是文档分词集合中的一个。比如说我们要找标题为北京奥运的所有文档

$curl -XGET http://localhost:9200/index/doc/_search?pretty -d
'{"query":{"term":{"title":"北京奥运"}}
}'

将会得到如下结果


{"took": 1,"timed_out": false,"_shards": {"total": 5,"successful": 5,"failed": 0},"hits": {"total": 1,"max_score": 0.92055845,"hits": [{"_index": "index","_type": "doc","_id": "3","_score": 0.92055845,"_source": {"content": "同一个世界同一个梦想","title": "北京奥运","tags": ["和平"]}}]}
}

搜索title包含北京或者奥运的,结果也一样,但是如果你搜索词为京奥,或者北京奥这样的,那么搜索结果将为空

{"took" : 1,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 0,"max_score" : null,"hits" : [ ]}
}

这是因为在对文档建立索引时,会将北京奥运分词为北京,奥运,北京奥运,只要搜索词为这三个之一,都可以将这篇文章搜索出来,而京奥和北京奥并不在分词集合里,所以无法搜索到该文档。 如果对于某个字段,你想精确匹配,即搜索什么词匹配什么词,类似sql中的=操作,比如只能通过北京奥运搜索到文档3而不想让北京和奥运也搜索到,那么,你可以在建立索引阶段指定该字段为"index": "not_analyzed",此时,elasticsearch将不会对该字段的值进行分词操作,只保留全文字索引。比如本例子中的tags字段,我在建立索引时设置了"index": "not_analyzed", 搜索时,不管是指定tags为美,还是国,都无法将第一条结果搜索出来

$curl -XGET http://localhost:9200/index/doc/_search?pretty -d

'{"query":{"term":{"tags":"美"}}
}'

搜索结果:


{"took" : 1,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 0,"max_score" : null,"hits" : [ ]}
}

而全词美国却可以


$curl -XGET http://localhost:9200/index/doc/_search?pretty -d
'{"query":{"term":{"tags":"美国"}}
}'

搜索结果:


{"took" : 2,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 1,"max_score" : 0.30685282,"hits" : [ {"_index" : "index","_type" : "doc","_id" : "1","_score" : 0.30685282,"_source" : {"content" : "美国留给伊拉克的是个烂摊子吗","title" : "标题","tags" : [ "美国", "伊拉克", "烂摊子" ]}} ]}
}

match类查询

match查询会先对搜索词进行分词,分词完毕后再逐个对分词结果进行匹配,因此相比于term的精确搜索,match是分词匹配搜索,match搜索还有两个相似功能的变种,一个是match_phrase,一个是multi_match,接下来详细介绍一下 match

前面提到match搜索会先对搜索词进行分词,对于最基本的match搜索来说,只要搜索词的分词集合中的一个或多个存在于文档中即可,例如,当我们搜索中国杭州,搜索词会先分词为中国和杭州,只要文档中包含搜索和杭州任意一个词,都会被搜索到

$curl -XGET http://localhost:9200/index/doc/_search?pretty -d

'{"query": {"match": {"content": "中国杭州"}}
}'

文档3正文中有杭州,文档2中有中国,因此搜索结果有两个,文档3中杭州出现两次,所以排在前面,结果如下:

{"took" : 1,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 2,"max_score" : 0.99999994,"hits" : [ {"_index" : "index","_type" : "doc","_id" : "4","_score" : 0.99999994,"_source" : {"content" : "杭州是一个美丽的城市,欢迎来到杭州","title" : "宣传","tags" : [ "旅游", "城市" ]}}, {"_index" : "index","_type" : "doc","_id" : "2","_score" : 0.8838835,"_source" : {"content" : "中国是世界上人口最多的国家","title" : "中国","tags" : [ "中国", "人口" ]}} ]}
}

同样的,我们用match的方式搜索中国世界,那么,文档2(含有中国和世界)和文档3(含有世界都会被搜索出来)。如果我们仅仅想搜索中国和世界都包含的文档该怎么办呢? 其实,对于match搜索,可以按照分词后的分词集合的or或者and进行匹配,默认为or,这也是为什么我们看到前面的搜索都是只要有一个分词出现在文档中就会被搜索出来,同样的,如果我们希望是所有分词都要出现,那只要把匹配模式改成and就行了

curl -XGET http://localhost:9200/index/doc/_search?pretty -d
'{"query": {"match": {"content": {"query": "中国世界","operator": "and"}}}
}'

如上所示,查询时将operator设置为and,此时,就只会搜索到既包含中国,也包含世界的文档了(因返回的字段较多,后面搜索结果只展示_source中的内容)


"_source" : {"content" : "中国是世界上人口最多的国家","title" : "中国","tags" : [ "中国", "人口" ]
}

match_phrase

match_phrase为按短语搜索,这个可能先用英文来解释会直观一点(中文分词后其实已经是一个一个有具体意思的词语)。英文中以空格分词,因此分词后是一个个的单词,当想搜索类似hope so这样的短语时,你或许并不想将一些只含有hope的文档搜索出来,也不想将一些类似I hope ×××. So ××这样的搜索出来,此时,就可以用match_phrase。 match_phrase的搜索方式和match类似,先对搜索词建立索引,并要求所有分词必须在文档中出现(像不像operator为and的match查询),除此之外,还必须满足分词在文档中出现的顺序和搜索词中一致且各搜索词之间必须紧邻,因此match_phrase也可以叫做紧邻搜索。 所以,当我们搜美国留给时

curl -XGET http://localhost:9200/index/doc/_search?pretty -d

'{"query": {"match_phrase": {"content": "美国留给"}}
}'

能搜出文档美国留给伊拉克的是个烂摊子吗

"_source" : {"content" : "美国留给伊拉克的是个烂摊子吗","title" : "标题","tags" : [ "美国", "伊拉克", "烂摊子" ]}

但是我们搜索留给美国或美国伊拉克时,却没有搜索结果,因为一个顺序不对,一个不是紧邻(隔着留给)。 紧邻对于匹配度要求较高,为了减小精度增加可操作性,引入了slop参数。该参数可以指定相隔多少个词仍被算作匹配成功。如下,

curl -XGET http://localhost:9200/index/doc/_search?pretty -d

'{"query": {"match_phrase": {"content": {"query": "美国伊拉克","slop": "1"}}}
}'

当我们将slop设置为1时,文档1已能被搜索到。

  "_source" : {"content" : "美国留给伊拉克的是个烂摊子吗","title" : "标题","tags" : [ "美国", "伊拉克", "烂摊子" ]}

需要注意的是,当slop的值过大时(超出文档总分词数),那么分词数据将可以是随意的,即跟operator为and的match查询效果一样。比如我们查询

curl -XGET http://localhost:9200/index/doc/_search?pretty -d

'{"query": {"match_phrase": {"content": {"query": "伊拉克美国","slop": "12"}}}
}'

将会得到与上面一样的结果

multi_match

文/木鸟飞鱼(简书作者) 原文链接:http://www.jianshu.com/p/eb30eee13923# 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

转载于:https://my.oschina.net/wsyblog/blog/710245

Elasticsearch查询之term/match解析相关推荐

  1. 【ES笔记02】ElasticSearch数据库之查询操作(match、must、must_not、should、_source、filter、range、exists、ids、term、terms)

    这篇文章,主要介绍ElasticSearch数据库之查询操作(match.must.must_not.should._source.filter.range.exists.ids.term.terms ...

  2. elasticsearch 查询(match和term)

    elasticsearch 查询(match和term) es中的查询请求有两种方式,一种是简易版的查询,另外一种是使用JSON完整的请求体,叫做结构化查询(DSL). 由于DSL查询更为直观也更为简 ...

  3. elasticsearch7常见查询(term、match、bool、filter)

    一.精准查询term term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇 1.term单值 字段只有一个值时候,用term关键词查询 查询biz_id值为190919002390 ...

  4. Elasticsearch中的Term查询和全文查询

    Elasticsearch中的Term查询和全文查询 前言 Term 查询 exists 查询 fuzzy 查询 ids 查询 prefix 查询 range 查询 regexp 查询 term 查询 ...

  5. ElasticSearch查询 第四篇:匹配查询(Match)

    <ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...

  6. elasticsearch查询

    1.查询方式 有两种查询方式,一种是通过在url中指定查询条件 ,另外一种是通过DSL查询.都是使用GET方法 1.1 分页查询 from 指定从文档的什么位置开始,默认值0 size 指定一次查询返 ...

  7. ElasticSearch查询 基础篇

    1. 查询表达式 查询表达式(Query DSL)是一种非常灵活又富有表现力的 查询语言. Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分.在你的应 ...

  8. ElasticSearch ---- 查询

    模拟数据创建 首先利用head差检查创建book索引 然后修改mappings配置 http方法:  post 链接地址:  http://192.168.253.129:9200/ book/nov ...

  9. Go Elasticsearch 查询快速入门

    文章目录 0.前言 1.根据 ID 查询 2.精确匹配单个字段 3.精确匹配单个字段的多个值 4.全文查询 5.范围查询 6.判断某个字段是否存在 7.bool 组合查询 must filter sh ...

最新文章

  1. 判断数据是否服从某一分布(二)——简单易用fitdistrplus包
  2. Java事务处理总结【JDBC事务|JTA事务|容器事务】
  3. 某些您可以编辑的区域交叠在一起 可能不能同时显示_DX200操作要领—修改与编辑程序(三十九)...
  4. js获取页面URL地址并判断URL是否包含具体值
  5. ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
  6. jQuery 常用效果
  7. abb机器人伺服电机报闸是什么_ABB机器人伺服电机维修更换马达步骤
  8. Debian下安装搜狗拼音输入法
  9. 计算机组成原理与系统结构裘雪红课后答案,计算机组成原理与系统结构课后作业答案(包健_冯建文章复嘉版).doc...
  10. STM32F1下载程序方法
  11. 计算机基础知识及键盘熟悉实验报告,微型计算机组成和键盘操作 实验报告
  12. css3实现缺角四边形_利用CSS3实现折角效果实例源码
  13. Bootstrap学习笔记——缩略图、警示框、进度条、媒体对象、列表组、画板
  14. #ASM 翻译系列第二十五弹:ASM 高级知识 When will my rebalance complete
  15. 熬了一夜!我用Python做了一个网站,帮小姐姐生成漫画头像
  16. java list里数据用逗号结合
  17. USB OTG的检测原理及使用
  18. 软件学报投稿论文格式模板
  19. BIND的安装与配置
  20. python计算量比指标

热门文章

  1. 信息服务器 iis 7.0,iis7.0的技术参数汇总
  2. php mysql orm_PHP ORM框架与简单代码实现(转)
  3. 装了python3但在cmd里不识别,Pip无法识别安装命令(Windows 7,Python 3.3)
  4. 通过连接池无法连接mysql_连接池无法链接数据库
  5. php基类控制器,控制器基类
  6. java 泛型 泛型类(Generic Classes)类型形参(Type Parameters)
  7. SQLAlchemy orm.query.Query
  8. 图解TCPIP-以太网(物理层)
  9. C语言 Condition variables
  10. java hashSet