ES入门之查询

当使用于 过滤情况 时,查询被设置成一个“不评分”或者“过滤”查询。即,这个查询只是简单的问一个问题:“这篇文档是否匹配?”。回答也是非常的简单,yes 或者 no ,二者必居其一。

  • created 时间是否在 2013 与 2014 这个区间?
  • status 字段是否包含 published 这个单词?
  • lat_lon 字段表示的位置是否在指定点的 10km 范围内?

当使用于 查询情况 时,查询就变成了一个“评分”的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 多好(匹配程度如何)。 此查询的典型用法是用于查找以下文档:

  • 查找与 full text search 这个词语最佳匹配的文档
  • 包含 run 这个词,也能匹配 runs 、 running 、 jog 或者 sprint
  • 包含 quick 、 brown 和 fox 这几个词 — 词之间离的越近,文档相关性越高
  • 标有 lucene 、 search 或者 java 标签 — 标签越多,相关性越高

一个评分查询计算每一个文档与此查询的 相关程度,同时将这个相关程度分配给表示相关性的字段 _score,并且按照相关性对匹配到的文档进行排序。这种相关性的概念是非常适合全文搜索的情况,因为全文搜索几乎没有完全 “正确” 的答案。

查询语句和过滤语句可以放在各自的上下文中,但是查询语句可以包含过滤子句,反之亦然。

filter context(过滤场景)

过滤查询包含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)然后进行过滤。

查询场景(query context)
match

Match 查询,查询索引中contend字段和"软件工程"这个查询语句匹配的文档。

{
  "query": {
    "match": {
        "content" : {
            "query" : "软件工程"
        }
    }
  }
}

上面的查询匹配就会进行分词,包含这“软件、工程”这词的文档就会被搜索出来,并且根据lucene的评分机制(TF/IDF)来进行评分。


注意:查询时分词和存储时分词并不是统一的。比如上述样例中contend 字段的类型可以设置为keyword(存储时不分词),使用match查询时可能无法查询文档

match_phrase

比如上面一个例子,一个文档content字段为"office是一款不错的软件"也会被搜索出来,那么想要精确匹配所有同时包含"软件 工程"的文档怎么做?就要使用 match_phrase 了

{
  "query": {
    "match_phrase": {
        "content" : {
            "query" : "软件工程"
        }
    }
  }
}
multi_match

如果我们希望两个字段进行匹配,其中一个字段有这个文档就满足的话,使用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

term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇

{
  "query": {
    "term": {
      "content": "汽车保养"
    }
  }
}

查出的所有文档都包含"汽车保养"这个词组的词汇。

使用term要确定的是这个字段是否“被分析”(analyzed),默认的字符串是被分析的。

bool 组合查询 (must,should,must_not)

这三个可以这么理解

must: 文档必须完全匹配条件
should: should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
must_not: 文档必须不匹配条件
如果我们想要请求"content中带宝马,但是tag中不带宝马"这样类似的需求,就需要用到bool联合查询。

{
  "query": {
    "bool": {
      "must": {
        "term": {
          "content": "宝马"
        }
      },
      "must_not": {
        "term": {
          "tags": "宝马"
        }
      }
    }
  }
}
nested 嵌套查询

由于嵌套对象 被索引在独立隐藏的文档中,我们无法直接查询它们。 相应地,我们必须使用 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 查询肯定可以匹配到多个嵌套的文档。每一个匹配的嵌套文档都有自己的相关度得分,但是这众多的分数最终需要汇聚为可供根文档使用的一个分数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值