当使用于 过滤情况 时,查询被设置成一个“不评分”或者“过滤”查询。即,这个查询只是简单的问一个问题:“这篇文档是否匹配?”。回答也是非常的简单,yes 或者 no ,二者必居其一。
当使用于 查询情况 时,查询就变成了一个“评分”的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 多好(匹配程度如何)。 此查询的典型用法是用于查找以下文档:
一个评分查询计算每一个文档与此查询的 相关程度,同时将这个相关程度分配给表示相关性的字段 _score,并且按照相关性对匹配到的文档进行排序。这种相关性的概念是非常适合全文搜索的情况,因为全文搜索几乎没有完全 “正确” 的答案。
查询语句和过滤语句可以放在各自的上下文中,但是查询语句可以包含过滤子句,反之亦然。
过滤查询包含filtered关键字,里面又包含普通的查询query逻辑和filter 过滤逻辑。运行时先执行过滤语句,后执行普通查询.
{
"query": {
"filtered":{
"query":{
"range":{
"date":{
"lte":"2016-10-01"
}
}
},
"filter":{
"term":{
"contents":"软件工程"
}
}
}
}
}
[1] 上述查询主要查询10月之前contents字段包含“软件工程”的文档。运行时先执行过滤语句(过滤出contents字段内容为软件工程的文档),后执行普通查询。
[2] search API中只能包含 query 语句,因此我们在需要在外层再加入 query 的上下文关系。
注意:在使用(filter)过滤语句时注意match关键字与term关键字的区别,由于在filter中不计算得分,因此match可能将查询条件进行分词(多次term)然后进行过滤。
Match 查询,查询索引中contend字段和"软件工程"这个查询语句匹配的文档。
{
"query": {
"match": {
"content" : {
"query" : "软件工程"
}
}
}
}
上面的查询匹配就会进行分词,包含这“软件、工程”这词的文档就会被搜索出来,并且根据lucene的评分机制(TF/IDF)来进行评分。
注意:查询时分词和存储时分词并不是统一的。比如上述样例中contend 字段的类型可以设置为keyword(存储时不分词),使用match查询时可能无法查询文档
比如上面一个例子,一个文档content字段为"office是一款不错的软件"也会被搜索出来,那么想要精确匹配所有同时包含"软件 工程"的文档怎么做?就要使用 match_phrase 了
{
"query": {
"match_phrase": {
"content" : {
"query" : "软件工程"
}
}
}
}
如果我们希望两个字段进行匹配,其中一个字段有这个文档就满足的话,使用multi_match
{
"query": {
"multi_match": {
"query" : "软件工程",
"fields" : ["title", "content"]
}
}
}
我们希望完全匹配的文档占的评分比较高,则需要使用best_fields
{
"query": {
"multi_match": {
"query": "软件工程",
"type": "best_fields",
"fields": [
"tag",
"content"
],
"tie_breaker": 0.3
}
}
}
我们希望越多字段匹配的文档评分越高,就要使用most_fields
{
"query": {
"multi_match": {
"query": "软件工程",
"type": "most_fields",
"fields": [
"tag",
"content"
]
}
}
}
我们会希望这个词条的分词词汇是分配到不同字段中的,那么就使用cross_fields
{
"query": {
"multi_match": {
"query": "软件工程",
"type": "cross_fields",
"fields": [
"tag",
"content"
]
}
}
}
term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇
{
"query": {
"term": {
"content": "汽车保养"
}
}
}
查出的所有文档都包含"汽车保养"这个词组的词汇。
使用term要确定的是这个字段是否“被分析”(analyzed),默认的字符串是被分析的。
这三个可以这么理解
must: 文档必须完全匹配条件
should: should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
must_not: 文档必须不匹配条件
如果我们想要请求"content中带宝马,但是tag中不带宝马"这样类似的需求,就需要用到bool联合查询。
{
"query": {
"bool": {
"must": {
"term": {
"content": "宝马"
}
},
"must_not": {
"term": {
"tags": "宝马"
}
}
}
}
}
由于嵌套对象 被索引在独立隐藏的文档中,我们无法直接查询它们。 相应地,我们必须使用 nested 查询 去获取它们。
GET /my_index/blogpost/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "eggs"
}
},
{
"nested": {
"path": "comments",
"query": {
"bool": {
"must": [
{
"match": {
"comments.name": "john"
}
},
{
"match": {
"comments.age": 28
}
}
]
}
}
}
}
]
}}}
nested 查询肯定可以匹配到多个嵌套的文档。每一个匹配的嵌套文档都有自己的相关度得分,但是这众多的分数最终需要汇聚为可供根文档使用的一个分数。