Elasticsearch 自动补全搜索 - autocomplete

news/2025/2/21 7:09:40

作者:来自 Elastic Amit Khandelwal

探索处理自动完成的不同方法,从基础到高级,包括输入时搜索、查询时间、完成建议器和索引时间。

在本文中,我们将介绍如何避免严重的性能错误、Elasticsearch 默认解决方案为何不适用以及重要的实施注意事项。

所有现代网站都在其搜索栏上提供自动补全(autocomplete)功能(输入时搜索),以改善用户体验(没有人愿意输入整个搜索词……)。自动补全必须比标准搜索更快,因为自动完成的全部目的是在用户输入时开始显示结果。如果延迟较高,则会导致用户体验不佳。

以下是著名问答网站 Quora 上的自动完成搜索示例。这是一个很好的自动完成示例:搜索 “elasticsearch auto” 时,以下帖子开始显示在搜索栏中:

注意搜索结果中,有与 Elasticsearch 的自动扩展、自动标记和自动完成功能相关的问题。用户可以进一步输入一些字符来细化搜索结果。

Elasticsearch 中自动完成的各种方法/输入时搜索

有多种方法可以实现自动完成功能,大致分为四大类:

  • Search-as-you-type
  • Query time
  • Completion suggester
  • Index time

1. Search as you type

这是一种数据类型,旨在方便自动完成查询,而无需事先了解自定义分析器设置。Elasticsearch 内部存储同一文本的各种标记(edge n-gram, shingles),因此可用于前缀和中缀补全。

如果你不熟悉 Elasticsearch 的高级功能(其他三种方法都需要这些功能),那么这种方法会很方便。在 “Search as you type - 边输入边搜索” 中,不需要进行太多配置,即可使其适用于简单的用例和代码示例。更多详细信息请参阅我们的文档。

2. 查询时 - query time

可以通过将匹配查询(match queries)更改为前缀查询(prefix queries)来实现自动完成。在对 token(索引)到 token(搜索查询 token)匹配的匹配查询时,前缀查询(如其名称所建议)从搜索 token 开始的所有 token 匹配,因此匹配的文档数量(结果)很高。

正如所解释的那样,前缀查询不是一个准确的 token 匹配,而是基于字符串中的字符匹配,这是非常昂贵的,并获取了很多文档。 Elasticsearch 内部使用 B+树(B+ tree)类型的数据结构来存储其 token。了解倒排索引(indices)使用的数据结构的内部以及不同类型的查询如何影响性能和结果是有用的。

Elasticsearch 在 7.2 版本中引入了 Match Boolean Prefix 查询(Match boolean prefix query)。这是一种结合了 Match 查询和 Prefix 查询的方式,兼具两者的优势。它在处理多个搜索词时特别有用。例如,如果搜索词为 "foo bar baz",那么与其对所有搜索词执行前缀搜索(这种方式开销大且结果较少),该查询仅对最后一个词执行前缀搜索,而对前面的词进行匹配,且顺序不限。这样可以提高搜索结果的速度和相关性。

3. 完成建议 - Completion suggester

如果你为诸如电子商务和酒店搜索网站等搜索词提供建议,这将很有用。搜索栏提供了查询建议,而不是在实际搜索结果中出现的建议,并且选择了完善建议者提供的建议之一后,它提供了搜索结果。

为了使 completion suggester 工作,必须将 suggestions 索引为任何其他字段。你还可以选择添加权重字段来对建议进行排名。

如果你具有 autocomplete suggestions 的外部来源,例如搜索分析,则这种方法是理想的选择。

代码样本

索引定义

PUT movies
{
  "mappings": {
    "properties": {
      "movie_name": {
        "type": "completion"
      }
    }
  }
}

响应:

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "movies"
}

索引 suggstions

PUT movies/_doc/1?refresh
{
  "movie_name" : {
    "input": [ "Avengers", "Infinity War" ],
    "weight" : 34
  }
}

响应:

{
  "_index": "movies",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "forced_refresh": true,
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

搜素

POST movies/_search?pretty
{
  "suggest": {
    "song-suggest": {
      "prefix": "inf",        
      "completion": {         
          "field": "movie_name"  
      }
    }
  }
}

响应:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  },
  "suggest": {
    "song-suggest": [
      {
        "text": "inf",
        "offset": 0,
        "length": 3,
        "options": [
          {
            "text": "Infinity War",
            "_index": "movies",
            "_id": "1",
            "_score": 1,
            "_source": {
              "movie_name": {
                "input": [
                  "Avengers",
                  "Infinity War"
                ]
              }
            }
          }
        ]
      }
    ]
  }
}

4. 索引时 - index time

有时,要求只是 prefix completion 或 autocomplete 中的 infix 完成。使用 Custom-Analyzers 看到自动完成的实现并不少见,这涉及以与用户的搜索词相匹配的方式索引令牌。

如果我们继续进行示例,我们将查看由 “elasticsearch Autocopterete”,“ elasticsearch Auto-Tag”,“ elasticsearch auto Scaling” 和 “Elasticsearch automatically” 组成的文档。默认的 analyzer 不会为 “autocomplete”,“autoscaling” 和 “automatically” 产生任何部分 token,并且搜索 “auto” 不会产生任何结果。

为了克服上述问题, edge ngram 或 n-gram tokenizer 用于在 Elasticsearch 中索引 token,如文档中所述,并搜索时分析器(search time analyzer )以获得自动完成结果。

上述方法使用了 Match 查询,这种查询速度较快,因为它基于字符串比较(使用哈希码)。此外,索引中精确匹配的 token 相对较少,从而进一步提高了查询效率。

性能考虑

上述几乎所有方法在较小的搜索负载的较小数据集上都可以正常工作,但是当你有大量索引获得大量自动索引建议查询时,上述查询的 SLA 和性能是必不可少的。以下要点应帮助你选择最适合你需求的方法:

  • Ngram 或 Edge Ngram token 会显著增加索引大小,因此需要根据应用需求和系统容量合理设定 min_grammax_gram 的限制。合理规划可以在生产环境中避免许多问题。
  • 允许空前缀或仅包含少量字符的前缀查询可能会匹配索引中的所有文档,从而导致整个集群崩溃。因此,最佳实践是仅在少数字段上执行前缀查询,并限制前缀查询的最小字符数。上述的 Match Boolean Prefix 查询可以很好地解决这一问题。
  • Elasticsearch 提供的 "search_as_you_type" 数据类型会以多种格式对输入文本进行分词。由于它是 Elasticsearch 提供的标准解决方案,无法满足所有业务需求,因此在使用时应仔细检查业务场景下的所有边界情况。此外,由于该方法会以多种格式对字段进行分词,可能会增加 Elasticsearch 索引存储的大小。
  • Completion Suggest 采用独立索引的方式存储建议词,但无法用于获取搜索结果,因此适用于自动补全场景,而不适用于一般的搜索需求。
  • 索引时优化(Index-time approach)速度快,因为查询时的计算开销较小,但它需要更多的前期工作,例如 重新索引(reindexing)、容量规划(capacity planning)和额外的磁盘存储成本。相比之下,查询时优化(Query-time approach)更容易实现,但搜索查询成本更高。理解这一权衡(trade-off)非常重要,因为在大多数情况下,用户需要在两者之间做出选择,并清楚其影响,以便解决各种性能问题。

想获得 Elastic 认证吗?找出何时进行下一个 Elasticsearch工程师培训!

Elasticsearch 包含新功能,可帮助你为用例构建最佳的搜索解决方案。潜入我们的示例笔记本上,以了解更多信息,开始免费的云试验,或者现在在本地机器上尝试 Elastic。

原文:Elasticsearch autocomplete search - Elasticsearch Labs


http://www.niftyadmin.cn/n/5860429.html

相关文章

uniapp多端适配

UniApp是一个基于Vue.js开发多端应用的框架,它可以让开发者编写一次代码,同时适配iOS、Android、Web等多个平台。 环境搭建: UniApp基于Vue.js开发,所以需要先安装Vue CLI npm install -g vue/cli 创建一个新的UniApp项目&…

MapReduce 第二部:深入分析与实践

在第一部分中,我们了解了MapReduce的基本概念和如何使用Python2编写MapReduce程序进行简单的单词计数。今天,我们将深入探讨如何使用MapReduce处理更复杂的数据源,比如HDFS中的CSV文件,并将结果输出到HDFS。通过更复杂的实践案例&…

zero自动化框架搭建---Git安装详解

一、Git下载 下载安装包 官网下载 下载的地址就是官网即可:Git - Downloads 进来直接选择windows的安装包下载 选择安装位置 双击安装包安装,选择安装地址后点击next 选择安装的组件,默认即可 也可按照需要自行选择 Windows Explorer i…

MySQL 三层 B+ 树能存多少数据?

1. B树的基本结构 节点大小:在InnoDB中,B树的每个节点(页)大小通常是16KB。索引项大小:每个索引项的大小取决于主键和指针的大小。假设主键为8字节,指针为6字节,则每个索引项的大小约为14字节。…

leetcode_位运算 190.颠倒二进制位

190. 颠倒二进制位 颠倒给定的 32 位无符号整数的二进制位。 1. 字符串 class Solution:# param n, an integer# return an integerdef reverseBits(self, n):res "" # 创建一个保存结果的空字符串for b in str(bin(n))[2:]:# 遍历n的二进制数res b res # 把每…

线程与线程:从入门到放弃

引言 在计算机科学中,**线程**是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程可以拥有多个线程,这些线程共享进程的内存空间和资源,但每个线程拥有独立的执行栈和程序计数器。 本…

JUC并发—8.并发安全集合二

大纲 1.JDK 1.7的HashMap的死循环与数据丢失 2.ConcurrentHashMap的并发安全 3.ConcurrentHashMap的设计介绍 4.ConcurrentHashMap的put操作流程 5.ConcurrentHashMap的Node数组初始化 6.ConcurrentHashMap对Hash冲突的处理 7.ConcurrentHashMap的并发扩容机制 8.Concu…

第1章大型互联网公司的基础架构——1.11 消息中间件技术

消息队列(Message Queue)是分布式系统中最重要的中间件之一,在服务架构设计中被广泛使用。 1.11.1 通信模式与用途 消息中间件构建了这样的通信模式: 一条消息由生产者创建,并被投递到存放消息的队列中;…