ES总结四:检索
<p>[TOC]</p>
<h1>全文查询</h1>
<h2>match</h2>
<p>举一个例子,比如说存在某文档标题为:java编程思想。如果使用term query查询‘java编程思想’,查不到匹配性。因为term查询的是词项,java编程思想分词后会变成java、编程,思想、等词,所以Java编程思想查询不到,相反的是有match query 查询 java编程思想就可以查询的到。match会对查询语句进行分词,分词后查询语句中的任何一个词项被匹配,文档就会被搜索到。</p>
<h2>match_phrase</h2>
<p>match_phrase首先会把query内容分词,分词器可以自定义,同时文档还要满足以下两个条件才会被搜索到
1)分词后所有词项都要出现在该字段中。
(2)字段中的词项顺序要一致
<img src="https://www.showdoc.cc/server/api/common/visitfile/sign/21614596c425a4260bc58fdb2b569f2a?showdoc=.jpg" alt="" /></p>
<h2>match_phrase_prefix</h2>
<p>match_phrase_prefix和match_phrase类似,只不过match_phrase_prefix支持最后一个term前缀匹配:
<img src="https://www.showdoc.cc/server/api/common/visitfile/sign/44cab74a09b435129412a3e3209a50ca?showdoc=.jpg" alt="" /></p>
<h2>multi_match</h2>
<p>multi_match是match的升级,用于搜索多个字段.。</p>
<h2>query_string</h2>
<p>querystringquery是与Lucene查询语句的语法结合非常紧密的一种查询,允许在一个查询语句中使用多个特殊条件关键字(如:AND|OR|NOT)对多个字段进行查询,建议熟悉Lucene查询语法的用户去使用.</p>
<h2>simple_query_string</h2>
<p>simple_query_string是一种适合直接暴露给用户,并且具有非常完善的查询语法的查询语句,接受Lucene查询语法,解析过程中发生错误不会抛出异常</p>
<h1>词项查询</h1>
<p>全文搜索在执行查询之前会分析查询字符串,词项搜索时对倒排索引中存储的词项进行精确操作。词项级别的查询通常用于结构化数据,如数字、日期和枚举类型。</p>
<h2>term</h2>
<p>term查询用来查找指定字段中包含给定单词的文档,term查询不被解析,只有查询词和文档中的词精确匹配才会被搜索到,应用场景为查询人名、地名等需要精准配备的需求。</p>
<h2>terms</h2>
<p>字段中包含关键词“java”或“python”的文档,构造查询语句如下:
<code>GETbooks/search</code></p>
<pre><code class="language-json">{
"query": {
"terms": {
"title": ["java", "python"]
}
}
}</code></pre>
<h2>range</h2>
<p>range查询用于匹配在某一范围内的数值型、日期类型或者字符串型字段的文档,比如搜索哪些书籍的价格在50到100之间、哪些书籍的出版时间在2014年到2016年之间。使用range查询只能查询一个字段,不能作用在多个字段上。range查询支持的参数有以下几种:
•gt大于,查询范围的最小值,也就是下界,但是不包含临界值。
•gte大于等于,和gt的区别在于包含临界值。
•It小于,查询范围的最大值,也就是上界,但是不包含临界值。
•lte小于等于,和It的区别在于包含临界值
例如,想要查询价格大于50小于等于70的书籍,即50<price<=70, 构造查询语句如下:
<code>GETbooks/search</code></p>
<pre><code class="language-json">{
"query": {
"range": {
"price": {
"gt": 50,
"lte": 70
}
}
}
}</code></pre>
<p>查询出版日期在2016年1月1日和2016年12月31之间的书籍,对publish_time字段进行range查询:</p>
<pre><code class="language-json">{
"query": {
"range": {
"pub1ish_time": {
"gte": "2016-01-01",
"lte": "2016-12-31",
"format": "yyyy-MM-dd"
}
}
}
}</code></pre>
<h2>exists</h2>
<p>exists查询会返回字段中至少有一个非空值的文档</p>
<pre><code class="language-json">{
"query": {
"exists": {
"field": "user"
}
}
}</code></pre>
<p>user字段不为空的文档会被匹配出来</p>
<h2>prefix</h2>
<p>prefix查询用于查询某个字段中以给定前缀开始的文档,比如查询title中含有以java为前缀的关键词的文档,那么含有javajavascriptjavaee等所有以java开头关键词的文档都会被匹配</p>
<pre><code class="language-json">{
"query": {
"prefix": {
"description": "win"
}
}
}</code></pre>
<h2>wildcard</h2>
<p>假设需要找某一作者写的书,但是忘记了作者名字的全称,只记住了前两个字,那么就可以使用通配符查询:</p>
<pre><code class="language-json">{
"query": {
"wildcard": {
"author": "张三*"
}
}
}</code></pre>
<h2>regexp</h2>
<p>例如需要匹配以W开头紧跟着数字的邮政编码,使用正则表达式查询构造查询语句如下:</p>
<pre><code class="language-json">{
"query": {
"regexp": {
"postcode": "W[0-9].+"
}
}
}</code></pre>
<h2>fuzzy</h2>
<p>举例如下,用户在输入查询关键词时不小心把“javascript”拼成“javascritp”,在存在拼写错误的情况下使用模糊查询仍然可以搜索到含有“javascript”的文档,查询语句如下:</p>
<pre><code class="language-json">{
"query": {
"fuzzy": {
"title": "javascritp"
}
}
}</code></pre>
<h1>复合查询</h1>
<p>复合查询就是把一些简单查询组合在一起实现更复杂的查询需求,除此之外复合查询还可以控制另外一个查询的行为;</p>
<h2>constant—score</h2>
<p>constant——score query可以包装一个其他类型的查询,并返回匹配过滤器中的查询条件且具有相同评分的文档。下面的查询语句会返回title字段中含有关键词“java”的文档,所有文档的评分都是1.2</p>
<pre><code class="language-json">{
"query": {
"constantscore": {
"filter": {
"term": {
"title": "java"
}
},
"boost": 1.2
}
}
}</code></pre>
<h2>bool</h2>
<p>bool查询可以把任意多个简单查询组合在一起,使用must、should、must_not、filter选项来表示简单查询之间的逻辑,每个选项都可以出现0次到多次,它们的含义如下:</p>
<ul>
<li>must:文档必须匹配must选项下的查询条件,相当于逻辑运算的AND</li>
<li>should:文档可以匹配should选项下的查询条件也可以不匹配,相当于逻辑运算的OR</li>
<li>must_not:与must相反,匹配该选项下的查询条件的文档不会被返回。</li>
<li>filter: 和must—样,匹配filter选项下的查询条件的文档才会被返回,但是filter不评分,只起到过滤功能
假设要查询title中包含关键词java,并且price不能高于70,description可以包含也可以不包含虚拟机的书籍,构造bool查询语句如下:
<pre><code class="language-json">{
"query": {
"bool": {
"minimu_should_match": 1,
"must": {
"match": {
"title": "java"
}
},
"should": [{
"match": {
"description": "虚拟机"
}
}],
"must_not ": {
"range": {
"price": {
"gte": 70
}
}
}
}
}
}</code></pre>
<h2>indices</h2>
<p>indicesquery适用于需要在多个索引之间进行查询的场景,它允许指定一个索引名字列表和内部查询。indicesquery中有query和nomatchquery两部分,query中用于搜索指定索引列表中的文档,no_match_query中的查询条件用于搜索指定索引列表之外的文档。下面的查询语句实现了搜索索引booksbooks2中title字段包含关键字javascript,其他索引中title字段包含basketball的文档,查询语句如下:</p>
<pre><code class="language-json">{
"query": {
"indices": {
"indices": ["book","book1"],
"query":{"match":{"title":"javascript"}},
"no_match_query":{"term":{"title":"basketball"}
}
}
}</code></pre>
<h1>其他查询</h1>
<p>除了上面讲到的查询之外,ES还有一些其他不常用查询,如嵌套查询、位置查询,特殊查询等等。</p></li>
</ul>
<h1>搜索排序</h1>
<h2>单字段排序</h2>
<p>Elasticsearch是按照查询和文档的相关度进行排序的,默认按评分降序排序,搜索title字段中包含java关键词的文档:</p>
<pre><code class="language-json">{
"query": {
"term": {
"title": "java"
}
}
}</code></pre>
<p>等价于:</p>
<pre><code class="language-json">{
"query": {
"term": {
"title": "java"
}
},
"sort": [{
"_score": {
"order": "asc"
}
}]
}</code></pre>
<p>对于match_all y而言,由于只返回所有文档,不需要评分,<strong>文档的顺序为添加文档的顺序</strong>。如果需要改变match_all的文档返回顺序,可以对_doc进行排序。例如,返回最后添加的那条文档,可以对_doc降序排序,设置返回文档条数为1,命令如下:</p>
<pre><code class="language-json">{
"query": {
"match_all": {}
},
"sort": [{
"_doc": {
"order": "desc"
}
}]
}</code></pre>
<h2>多字段排序</h2>
<p>例如,先按价格降序排序,价格相等的按照出版年份升序排序:</p>
<pre><code class="language-json">{
"sort": [{
"price": {
"order": "asc"
}
}, {
"year": {
"order": "desc"
}
}]
}</code></pre>