ElasticSearch学习随笔之高级检索

这篇具有很好参考价值的文章主要介绍了ElasticSearch学习随笔之高级检索。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

ElasticSearch

1、ElasticSearch学习随笔之基础介绍
2、ElasticSearch学习随笔之简单操作
3、ElasticSearch学习随笔之java api 操作
4、ElasticSearch学习随笔之SpringBoot Starter 操作
5、ElasticSearch学习随笔之嵌套操作
6、ElasticSearch学习随笔之分词算法
7、ElasticSearch学习随笔之高级检索
8、ELK技术栈介绍
9、Logstash部署与使用
10、ElasticSearch 7.x 版本使用 BulkProcessor 实现批量添加数据
11、ElasticSearch 8.x 弃用了 High Level REST Client,移除了 Java Transport Client,推荐使用 Elasticsearch Java API
12、ElasticSearch 8.x 使用 snapshot(快照)进行数据迁移
13、ElasticSearch 8.x 版本如何使用 SearchRequestBuilder 检索

ElasticSearch,创始人 Shay Banon(谢巴农)
本文主要讲解ElasticSearch 高级搜索实战,来满足复杂的业务场景,还是用 Kibana 来操作。



前言

本文主要介绍 ES 的一下高级检索功能,80% 的业务场景,简单搜索就可以实现了,但是在一些复杂的业务场景中,我们必须使用一些高级的功能来满足,比如在一些与舆情监测项目或者智能推荐、猜你想搜这种复杂的功能,有时候需要搜索中需要提高相关度,有时候搜索需要减低相关度等。
Don’t bebe so much, show the codes…

让我们来准备一些数据来进行高级搜索测试,但是问题来了,这些数据真的是头疼,不好生成一些示例数据出来,这时候,chatGTP这是无敌了,简直太方便了。
ElasticSearch学习随笔之高级检索

一、Boosting(控制相关度)

Boosting 是控制相关度的一种手段,此操作最好是需要 boost 参数来控制评分权重,如下:

  • boost > 1时,打分的权重相对性提升
  • 0 < boost < 1时,打分权重相对性降低
  • boot < 0 时,负分

“positive” 查询用于匹配你感兴趣的文档,而 “negative” 查询匹配的文档会被降级,这就可以在不排除某些文档的情况下对文档进行检索,只是结果中存在相似度较低的文档,排在后面。
negative_boost 对 negative 部分 query 生效,在计算评分时,negative 部分 query 评分乘以 negative_boost 值。

GET electronics/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "desc": "手机"
        }
      },
      "negative": {
        "match": {
          "desc": "相机"
        }
      },
      "negative_boost": 0.2
    }
  },
  "from": 1,
  "size": 10
}

应用场景:希望检索的关键词的结果不是不出现,而是排在最后面。

二、Bool 布尔查询

2.1 复合查询

Bool 查询是一个或者多个子查询的组合体,包括 4 中子句,其中 2 种是影响评分的,两种不影响评分,具体如下:

  • must:相当于JAVA中的 && 操作符,必须匹配,支持评分。
  • should:相当于 JAVA 中的 || 操作符,选择性匹配,支持评分。
  • must_not:相当于JAVA中的 !,必须不匹配,不支持评分。
  • filter:简单的过滤,不支持评分。

注意面试中可能会被问到:

操作 描述
Query 会进行相关性算分,检索性能不高
Filter 不会进行相关性算分,检索性能会更好

注意: 把多个子查询合并为一个复合查询时,比如 bool 查询,每个子查询计算的评分会被合并到相关性总评分中。

布尔查询语法也是相当灵活:
1、子查询的顺序随意;
2、也可以嵌套多个子查询;
3、没有 must 条件的情况下,should 条件至少满足一项。

比如下面这一条示例,检索了 electronics 索引中,产品名称(title)带 “苹果” 的,描述(desc)中带有 “手机” 或者 “笔记本” 的,品牌(brand)是 “Apple” 的,颜色过滤掉 “black” 的结果。

brand.keyword 这里, 因为我并没有定义 schema,但是我用了 term 来精确匹配的,所以需要用 (.keyword) 来把 brand 字段设置成关键词匹配。

POST electronics/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "苹果"
          }
        }
      ],
      "should": [
        {
          "match": {
            "desc": "手机"
          }
        },
        {
          "match": {
            "desc": "笔记本"
          }
        }
      ],
      "filter": {
        "term": {
          "brand.keyword": "Apple"
        }
      },
      "must_not": [
        {
          "term": {
            "color": "black"
          }
        }
      ]
    }
  }
}

2.2 包含不相等查询

在具体业务中,有的业务数据并不是一个简单的字符串或者是数值,而是一个多值的情况,这种情况下我们在检索时希望精确匹配到多值中的一项,可以用 match 来查询,语句如下:

POST electronics/_search
{
  "query": {
    "match": {
      "product_agency": "打电话"
    }
  },
  "from": 0,
  "size": 20
}

我们也可以换成 term 来精确匹配,需要加上 .keyword,语句如下:

POST electronics/_search
{
  "query": {
    "term": {
      "product_agency.keyword": "打电话"
    }
  },
  "from": 0,
  "size": 20
}

以上两种方式,match 和 term 都可以查询出 product_agency 是 “打电话” 的手机信息,不过 “谷歌” 的手机确实没用过,那打电话的功能应该是有的,我要查询出只能打电话的,这时候可以增加 count 字段来解决这个问题,语句如下:

当然,如果 must 改为 filter, 则效率更佳!

POST electronics/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "product_agency.keyword": {
              "value": "打电话"
            }
          }
        },
        {
          "term": {
            "product_agency_count": {
              "value": 1
            }
          }
        }
      ]
    }
  },
  "from": 0,
  "size": 20
}

说实话,写完之后自我觉得这个例子没啥特别之处。

2.3 实现 should_not 查询

有没有发现 bool 查询里面 should_not 是没有的,我们可以通过 bool 嵌套多个子查询来实现,在 should 中嵌套 bool,再嵌套 must_not 来实现,语句如下:

POST electronics/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "product_agency.keyword": {
              "value": "打电话"
            }
          }
        }
      ],
      "should": [
        {
          "bool": {
            "must_not": [
              {
                "term": {
                  "price": {
                    "value": 699.99
                  }
                }
              }
            ]
          }
        }
      ],
      "minimum_should_match": 1
    }
  },
  "from": 0,
  "size": 20
}

注意: 这里需要加上 minimum_should_match 这个参数,最少匹配到一个 should 查询,这样才会生效。
说实话,这种只有在鸡肋业务中才会用到吧。

2.4 控制查询相关性算分

三、多字段查询

当值多字段查询操作在工作中很常见,大多数情况下就是用户数据一个关键词(通常是一个字符串),然后匹配到相关性最高的文档。

有三种这样的场景:

  • 最佳字段(Best Fields):字段直接相互竞争又相互关联,比如 title 和 content 字段,评分来自最匹配字段。
  • 多数字段(Most Fields):处理英文内容常见手段,在主字段(English Analyzer)抽取词干,加入同义词以匹配更多的文档;相同的文本,加入子字段(Standard Analyzer)以更加精准的匹配。
  • 混合字段(Cross Field):对于某些信息,比如 名称、地址、图书的信息等等,需要多个字段才能确定,单个字段只能作为整体的一部分,希望在这些字段中尽可能找到多的词。

3.1 最佳字段匹配(Best Fields)

在多个字段匹配时,用 bool 的 should 就可以实现,比如下面这条查询:

POST electronics/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "苹果"
          }
        },
        {
          "match": {
            "desc": "苹果"
          }
        }
      ]
    }
  }
}

但是这个查询并不会匹配到最好的结果,为什么?
should 的评分过程是这样的,匹配 should 语句中的多个子查询,加和多个子查询的评分,乘以匹配语句的总评分,除以语句的总数,显然这样的评分不够完美。
title 和 desc 两个字段属于竞争关系,所以不应该是评分简单加和,而是单个最佳字段的评分。

3.1.1 Dis Max Query

且看下面这条查询,可以通过 tie_breaker 来进行调整。
tie_breaker 介于 0 ~ 1 之间的浮点数,0 代表使用最佳匹配,1 代表所有语句同等重要。
1、取得最佳匹配的评分 _score。
2、将其他语句的评分与 tie_breaker(决胜局的意思) 进行相乘。
3、对所有评分求和并进行规范化。

看官网解释!!

POST electronics/_search
{
  "query": {
    "dis_max": {
      "tie_breaker": 0.7,
      "boost": 1.2,
      "queries": [
        {
          "match": {
            "title": "苹果"
          }
        },
        {
          "match": {
            "desc": "苹果"
          }
        }
      ]
    }
  }
}

3.1.2 Multi Match Query

另一种方式就是使用 multi_match 来检索,这种方式默认就是 best_fields 检索,所以可以不用指定 type 参数,tie_breaker 按照结果可调节。

POST electronics/_search
{
  "query": {
    "multi_match": {
      "query": "苹果",
      "fields": ["title", "desc"],
      "type": "best_fields",
      "tie_breaker": 0.2
    }
  }
}

3.2 多数字段匹配(Most Fields)

准备一些测试数据,首先来创建一个 index 并且定义 schema,加两条测试数据。

PUT /blogs
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "english",
        "fields": {
          "std": {
            "type": "text",
            "analyzer": "standard"
          }
        }
      }
    }
  }
}
POST blogs/_bulk
{ "index": { "_id": 1 }}
{ "title": "My dog barks" }
{ "index": { "_id": 2 }}
{ "title": "I see a lot of barking dogs on the road " }
{ "index": { "_id": 3 }}
{ "title": "I have a dog named bark" }
{ "index": { "_id": 4 }}
{ "title": "I see barking dogs on the street, they are running and playing " }

用下面的检索语句来查询,发现查询出了所有的数据,结果与我们的预期不匹配

GET blogs/_search
{
  "query": {
    "match": {
      "title": "braking dogs"
    }
  }
}

下面的查询语句来查询,发现结果好了很多,用 title 字段来尽可能的匹配更多的文档,提升召回率,同时又用 title.std 将相关度更高的文档置顶

GET blogs/_search
{
  "query": {
    "multi_match": {
      "query": "braking dogs",
      "fields": ["title", "title.std"],
      "type": "most_fields"
    }
  }
}

我们可以更精确一点,每个字段对于最终评分可以通过自定义评分 boost 来控制。
比如 title 字段更重要,我们可以用 boost 来控制,同时也降低了其他信号字段的作用。

GET blogs/_search
{
  "query": {
    "multi_match": {
      "query": "braking dogs",
      "fields": ["title^10", "title.std"],
      "type": "most_fields"
    }
  }
}

3.3 跨字段匹配(Cross Fields)

创建一个 address 的 index,字段是 provice 和 city,利用 ik 分词器分词。

PUT /address
{
    "settings" : {
        "index" : {
            "analysis.analyzer.default.type": "ik_max_word"
        }
    }
}
PUT /address/_bulk
{ "index": { "_id": "1"} }
{"province": "甘肃","city": "酒泉"}
{ "index": { "_id": "2"} }
{"province": "湖南","city": "常德"}
{ "index": { "_id": "3"} }
{"province": "陕西","city": "西安"}
{ "index": { "_id": "4"} }
{"province": "湖南","city": "邵阳"}
{ "index": { "_id": "5"} }
{"province": "甘肃","city": "武威"}
{ "index": { "_id": "6"} }
{"province": "甘肃","city": "玉门"}

先用 most_fields 的方式来查询 “甘肃酒泉”,但是结果不符合预期,甘肃玉门 和 甘肃武威 也出来了,查询不支持 operator 。

GET address/_search
{
  "query": {
    "multi_match": {
      "query": "甘肃酒泉",
      "fields": ["province", "city"],
      "type": "most_fields"
    }
  }
}

使用 cross_fields 来查询,支持 operator 操作。
查询结果符合我们的预期,只返回了 甘肃酒泉 的文档。

GET address/_search
{
  "query": {
    "multi_match": {
      "query": "甘肃酒泉",
      "fields": ["province","city"],
      "type": "cross_fields",
      "operator": "and"
    }
  }
}

还有另一种方式来解决,就是增加一个字段,用于检索完整的地址,比如:full_address 字段。

PUT /address
{
  "mappings" : {
      "properties" : {
        "province" : {
          "type" : "keyword",
          "copy_to": "full_address"
        },
        "city" : {
          "type" : "text",
          "copy_to": "full_address"
        }
      }
    },
    "settings" : {
        "index" : {
            "analysis.analyzer.default.type": "ik_max_word"
        }
    }
}

这样我们就可以用 full_address 字段来检索 “甘肃酒泉” 这个关键词了,利用 match 匹配就可以了,语句如下:

GET /address/_search
{
  "query": {
    "match": {
      "full_address": {
        "query": "湖南常德",
        "operator": "and"
      }
    }
  }
}

3.4 Terms Set 检索

今天看到一个新的检索方式,官方公众号介绍,这里做一下补充。
注意 :ElasticSearch 6.1 版中引入的新功能。
在检索多值字段时,利用 terms 进行精确匹配,利用minimum_should_match_field 参数指定一个包含匹配数量的字段(product_count)。

GET electronics/_search
{
  "query": {
    "terms_set": {
      "product_agency.keyword":{
        "terms":["打电话","王者","看电影"],
        "minimum_should_match_field":"product_count"
      }
    }
  }
}

ElasticSearch学习随笔之高级检索

利用 minimum_should_match_script 检索,指定一个包含匹配数量的字段(product_count)的 70% 数量动态计算匹配。

GET electronics2/_search
{
  "query": {
    "terms_set": {
      "product_agency":{
        "terms":["打电话","办公","看大片"],
        "minimum_should_match_script":{
          "source":"doc['product_count'].value * 0.7"
        }
      }
    }
  }
}

ElasticSearch学习随笔之高级检索

总结

ES 是目前全文检索排行榜 首位,而且不断升级,现在一到 8.x 版本了,基本上 solr 搜索引擎用的公司已经不多了,虽然搜索速度很快,但做不到实时,这就很尴尬了,再加上定制写一写什么关联查询,简直鸡肋了。
ES 提供了很多高级检索,能很好的满足一些复杂的业务场景,可以嵌套,这样就不用总是加字段这种很 low 的方式来解决一些业务问题了。
ElasticSearch学习随笔之高级检索文章来源地址https://www.toymoban.com/news/detail-438740.html

到了这里,关于ElasticSearch学习随笔之高级检索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 商城-学习整理-高级-全文检索-ES(九)

    https://www.elastic.co/cn/what-is/elasticsearch Elastic 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。 REST API:天然的跨平台。 官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/cur

    2024年02月12日
    浏览(46)
  • 全文检索学习之ElasticSearch学习笔记

    在非关系型数据库中,数据是非结构化的,如果直接去查找效率极低,全文检索将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。索引就是从非结构化数据中提取出的然后重新组

    2023年04月11日
    浏览(52)
  • 软件测试/测试开发/全日制|学习使用Elasticsearch进行全文检索

    霍格沃兹测试开发学社推出了《Python全栈开发与自动化测试班》。本课程面向开发人员、测试人员与运维人员,课程内容涵盖Python编程语言、人工智能应用、数据分析、自动化办公、平台开发、UI自动化测试、接口测试、性能测试等方向。 为大家提供更全面、更深入、更系统

    2024年01月21日
    浏览(47)
  • 【随笔】Git -- 高级命令(中篇)(七)

    💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 您的点赞、关注、收藏、评论,是对我最大

    2024年04月17日
    浏览(36)
  • 【随笔】Git 高级篇 -- 快速定位分支 ^|~(二十三)

    💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 您的点赞、关注、收藏、评论,是对我最大

    2024年04月12日
    浏览(35)
  • 谷歌学术高级检索笔记-检索逻辑和技巧

    前言 谷歌学术在理工科的科研工作中重要性不言而喻,通过检索快速定位研究目标是必要的,但其检索方法或检索逻辑却少有资料,太多重复或错误的资料不便于实际检索。本笔记通过基本检索逻辑和不断检索实验来总结分析了一些常用规律。 Tips:谷歌学术其他相关

    2024年02月08日
    浏览(61)
  • 随笔:信息系统项目管理师(软考高级2023)考试指南

    1、全国计算机软件资格考试设三个级别层次,五个专业,共有27种岗位资格考试 2、除了初级信息处理技术员为上机考试,其他均为笔试 3、信息系统项目管理师、系统规划与管理师、系统集成项目管理工程师考试形式相对考验记忆、可以短期进行知识积累考试 1、一年考两次

    2024年02月17日
    浏览(37)
  • 【高级RAG技巧】使用二阶段检索器平衡检索的效率和精度

    之前的文章已经介绍过向量数据库在RAG(Retrieval Augmented Generative)中的应用,本文将会讨论另一个重要的工具-Embedding模型。 一般来说,构建生产环境下的RAG系统是直接使用Embedding模型对用户输入的Query进行向量化表示,并且从已经构建好的向量数据库中检索出相关的段落用户

    2024年04月26日
    浏览(37)
  • 【随笔】Git 高级篇 -- 提交的技巧(上) rebase & commit --amend(十八)

    💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 您的点赞、关注、收藏、评论,是对我最大

    2024年04月22日
    浏览(42)
  • 【随笔】Git 高级篇 -- 整理提交记录(上)cherry-pick(十五)

    💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘   大家好,又见面了,我是夜阑的狗🐶,

    2024年04月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包