ES(elasticsearch)查询或搜索总结

     很多写说明文档,没有总结写开头。因为文档内容又很多,你看到后面就忘记前面,没有形成结构化知识。这样知识在大脑里是离散的,不完整,不准确的。

    所以我的文章都是把结论写最开始,或者要说的全部内容用一句话写在最开始。你知道了可以不用看,不知道,可以一眼知道接下来学到什么。

    当你看到后面,不记得前面了,回到最开始一句话,大脑就会统领全局,形成最准确和系统性的知识。

     我们只能按大脑习惯的学习知识,不可违背大脑的习惯学习,不然只会事倍功半,甚至于学过就忘。

 

     本文说是es的查询,分为:Query查询Filter查询、复合查询、聚合查询。

Query context 查询上下文 这种语句在执行时既要计算文档是否匹配,还要计算文档相对于其他文档的匹配度有多高,匹配度越高,_score 分数就越高

Filter context 过滤上下文 过滤上下文中的语句在执行时只关心文档是否和查询匹配,不会计算匹配度,也就是得分

一、query查询

也就是你写dsl(es 查询语法语言)语句时,可以用的下一级字段例如 {"query":{"match":{}}}

1、match查询

match query: 知道分词器的存在,会对filed进行分词操作,然后再查询
match_all: 查询所有文档
multi_match: 可以指定多个字段
match_phrase: 短语匹配查询,ElasticSearch引擎首先分析(analyze)查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配短语中的所有分词。

#1、 查询年龄为3的(命中:ID = 1)
GET student/_search
{
"query":{
   "match":{"age": 3}
   }
}

#2、查询兴趣里包含'演戏'的 (命中 ID = 2,5,4)
GET student/_search
{
  "query":{
    "match":{"interests": "演戏"}
  }
}
#这里只要interests包含'演戏','演','戏'的都会命中

#3、查询索引所有文档 (命中 ID = 1,2,3,4,5)
GET student/_search
{
  "query":{
    "match_all": {}
  }
}

#4、查询name和address包含'德' (命中 ID = 2)
GET student/_search
{
  "query":{
    "multi_match": {
      "query": "德",
      "fields":["name","address"]
    }
  }
}
#说明 这里文档ID为4的address为'德州',应该也包含'德',但却没有被命中,原因是我们索引结构中,address属性是一个keyword类型,它是需要完全匹配,而不是包含的关系。
#如果这里query为'德州'就可以命中2条数据。

#5、查询兴趣里包含'演员'的 (命中 无)
GET student/_search
{
  "query":{
    "match_phrase":{"interests": "演员"}
  }
}
# 这里和match的区别是这里是真正包含'演员',而不是只要满足其中一个字就会被模糊命中

2、term查询和terms查询

term query: 会去倒排索引中寻找确切的term,它并不知道分词器的存在。这种查询适合keyword 、numeric、date

term:查询某个字段为该关键词的文档(它是相等关系而不是包含关系)

terms:查询某个字段里含有多个关键词的文档

#1、查询地址等于'香港'的文档 (命中:ID = 2,5)
GET student/_search
{
  "query":{
    "term":{ "address":"香港"}
  }
}
#如果仅检索'香'那是无法命中的,因为keyword需要完全匹配才能命中

#2、查询地址等于"香港"或"北京"的 (命中: ID =2,3,5)
GET student/_search
{
  "query":{
    "terms":{
      "address":["香港","北京"]
    }
  }
}

3、 范围查询

range: 实现范围查询

   include_lower: 是否包含范围的左边界,默认是true

   include_upper: 是否包含范围的右边界,默认是true

#2、查询年纪18到28 (命中 ID = 2,3)
GET student/_search
{
    "query": {
        "range": {
            "age": {
                "from": 18,
                "to": 28,
                "include_lower": true,
                "include_upper": true
            }
        }
    }
}

4、wildcard查询

允许使用通配符* 和 ?来进行查询
* 代表0个或多个字符
? 代表任意一个字符

#1、查询姓名'徐'开头的 (命中 ID = 1)
GET student/_search
{
    "query": {
        "wildcard": {
             "name": "徐*"
        }
    }
}

5、fuzzy实现模糊查询

模糊查询可以在Match和 Multi-Match查询中使用以便解决拼写的错误,模糊度是基于Levenshteindistance计算与原单词的距离。使用如下:

GET student/_search
{
    "query": {
        "fuzzy": {
            "interests": {
                "value": "演" 
            }
        }
    }
}

二、Filter查询

filter是不计算相关性的,同时可以cache。因此,filter速度要快于query

#1、获取年龄为3的 (命中 ID = 1)
GET student/_search
{ 
  "post_filter":{
    "term":{"age": 3}
  }
}

#2、查询年纪为3或者63的 (命中 ID = 1,4)
GET student/_search
{ 
  "post_filter":{
    "terms":{"age":[3,63]}
  }
}

三、复合查询

bool query(布尔查询)、boosting query(提高查询)、constant_score(固定分数查询)、dis_max(最佳匹配查询)、function_score(函数查询)

1.布尔查询 "query":"bool"

# must:    必须匹配。贡献算分
# must_not:过滤子句,必须不能匹配,但不贡献算分 
# should:  选择性匹配,至少满足一条。贡献算分
# filter:  过滤子句,必须匹配,但不贡献算分 在filter元素下指定的查询对评分没有影响 , 评分 返回为0。分数仅受已指定查询的影响。

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user" : "kimchy" }
      },
      "filter": {
        "term" : { "tag" : "tech" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tag" : "wow" } },
        { "term" : { "tag" : "elasticsearch" } }
      ],
      "minimum_should_match" : 1,
      "boost" : 1.0
    }
  }
}

 2、提高查询 boosting query

在上面的复合查询我们可以通过must_not+must 先剔除不想匹配的文档,再获取匹配的文档,但是有一种场景就是我并不需要完全剔除,而是把需要剔除的那部分文档的分数降低。

 

# 通过Boosting的方式,将3的记录也纳入结果集,只是排名会靠后。(结果 1->2->3)
POST news/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "content": "apple"
        }
      },
      "negative": {
        "match": {
          "content": "pie"
        }
      },
      "negative_boost": 0.5
    }
  }
}

"""
说明boosting需要搭配三个关键字 positive , negative , negative_boost

只有匹配了 positive查询 的文档才会被包含到结果集中,但是同时匹配了negative查询 的文档会被降低其相关度,通过将文档原本的_score和negative_boost参数进行

相乘来得到新的_score。因此,negative_boost参数一般小于1.0。在上面的例子中,任何包含了指定负面词条的文档的_score都会是其原本_score的一半。

"""

 

就是说就算文档包含了苹果,但因为包含了树或者水果那么我们也会过滤这条文档信息,因为我们要查的苹果公司相关信息,如果你是苹果树那对我来讲确实是不匹配,

所以直接过滤掉,看是没啥问题。

但是你想,这样做是不是太粗暴了,因为一个文档中包含'苹果'和'树'那不代表一定是苹果树,而可能是 '苹果公司组织员工一起去种树' 那么这条文档理应出现

而不是直接过滤掉,所以我们就可以用boosting query。就像上面这个例子一样。

3、最佳匹配

dis_max : 只是取分数最高的那个query的分数而已。

GET /_search
{
    "query": {
        "dis_max" : {
            "queries" : [
                { "term" : { "title" : "Quick pets" }},
                { "term" : { "body" : "Quick pets" }}
            ],
            "tie_breaker" : 0.7
        }
    }
}
"""
假设一条文档的'title'查询得分是 1,'body'查询得分是1.6。那么总得分为:1.6+1*0.7 = 2.3。

如果我们去掉"tie_breaker" : 0.7 ,那么tie_breaker默认为0,那么这条文档的得分就是 1.6 + 1*0 = 1.6
"""

四、function_score(函数查询)

向量搜索的计算余弦相似度,就可以用到

{
            "query": {
                "script_score": {
                    "query": {
                        "bool":{"must":[{"match": {"org_id": org_id}},
                                        {"match": {"type_": type_}},
                                        {"match": {"bot_id": bot_id}}],
                                "filter": {"exists": {"field": "sentence_vec"}}
                                }
                    },
                    "script": {
                        "source": "cosineSimilarity(params.queryVector, 'sentence_vec')+1.0",
                        "params": {
                            "queryVector": sentence_vector
                        }
                    }
                }
            }
        }

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ai君臣

学会的就要教给人

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值