查看“ElasticSearch查询:全文搜索”的源代码
←
ElasticSearch查询:全文搜索
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:ElasticSearch教程]] == 关于 == <pre> 全文搜索是 ES 的关键特性之一,平时我们使用 SQL 的 like 语句,搜索一些文本、字符串是否包含指定的关键词。 但是如果两篇文章,都包含我们的关键词,具体那篇文章内容的相关度更高? 这是 SQL 的 like 语句是做不到的,更别说 like 语句的性能问题了。 </pre> ES 通过'''分词处理'''、'''相关度计算'''可以解决这个问题。 ES 内置了一些相关度算法,例如:'''TF/IDF 算法''',大体上思想就是:如果一个关键词在一篇文章出现的频率高,并且在其他文章中出现的少,那说明这个关键词与这篇文章的相关度很高。 === 与 SQL 的差异 === SQL 中也有全文索引(通过倒排索引),也有 like 进行模糊查询。 但是: # 如上所述,对于同一个关键词,两个 text 记录的相关度是 SQL 不能判断的; # SQL 的性能问题:仅使用服务器认为代价最低的那个索引。所以不能保证全部条件都能够用到索引来优化。 === 分词的目的 === 主要就是为了'''提取搜索关键词''',理解搜索的意图。 在进行搜索内容的时候,输入的内容可能很长,但不是每个字都对搜索有帮助,所以通过分词算法,输入的关键词会进一步分解成多个关键词。 : 例如:搜索输入“上海陆家嘴在哪里?”,分词算法可能分解出:“上海、陆家嘴、哪里”,'''具体会分解出什么关键词,跟具体的分词算法有关'''。 == 默认全文搜索 == 默认情况下,使用全文搜索很简单,只要将字段类型定义为 '''text''' 类型,然后用 '''match''' 语句匹配即可。 * ES 对于 text 类型的字段,在插入数据的时候,会进行分词处理,然后根据分词的结果索引文档。当我们搜索 text 类型字段的时候,也会先对搜索关键词进行分词处理、然后根据分词的结果去搜索。 * ES 默认的分词器是 '''standard'''。 ** 对英文比较友好,例如:“hello world”会被分解成“hello”和“world”; ** 但如果是中文会全部分解成单字,例如:“上海大学”会分解成: “上”、“海”、“大”、“学”。 语法: <syntaxhighlight lang="JSON" highlight=""> GET /_analyze { "text": "需要分词的内容", "analyzer": "分词器" } </syntaxhighlight> 示例 1: <syntaxhighlight lang="JSON" highlight=""> GET /_analyze { "text": "hello wolrd", "analyzer": "standard" } </syntaxhighlight> 输出: <syntaxhighlight lang="JSON" highlight=""> { "tokens" : [ { "token" : "hello", "start_offset" : 0, "end_offset" : 5, "type" : "<ALPHANUM>", "position" : 0 }, { "token" : "wolrd", "start_offset" : 6, "end_offset" : 11, "type" : "<ALPHANUM>", "position" : 1 } ] } </syntaxhighlight> * '''token''' 就是分解出来的关键词。 示例 2: <syntaxhighlight lang="JSON" highlight=""> GET /_analyze { "text": "上海大学", "analyzer": "standard" } </syntaxhighlight> 输出: <syntaxhighlight lang="JSON" highlight=""> { "tokens" : [ { "token" : "上", "start_offset" : 0, "end_offset" : 1, "type" : "<IDEOGRAPHIC>", "position" : 0 }, { "token" : "海", "start_offset" : 1, "end_offset" : 2, "type" : "<IDEOGRAPHIC>", "position" : 1 }, { "token" : "大", "start_offset" : 2, "end_offset" : 3, "type" : "<IDEOGRAPHIC>", "position" : 2 }, { "token" : "学", "start_offset" : 3, "end_offset" : 4, "type" : "<IDEOGRAPHIC>", "position" : 3 } ] } </syntaxhighlight> == 中文分词器 == 不过 ES 支持安装'''分词插件''',增加新的分词器。 目前中文分词器比较常用的有:'''smartcn''' 和 '''ik''' 两种。 === 指定 analyzer === 默认的分词器不满足需要,可以在'''定义索引映射的时候,指定 text 字段的分词器'''(analyzer)。 示例: <syntaxhighlight lang="JSON" highlight=""> PUT /article { "mappings": { "properties": { "title": { "type": "text", "analyzer": "smartcn" } } } } </syntaxhighlight> === smartcn 分词器 === smartcn 是目前 ES 官方推荐的中文分词插件,不过'''目前不支持自定义词库'''。 * smartcn 的分词器名字就叫做:'''smartcn''' 插件安装: <syntaxhighlight lang="bash" highlight=""> {ES安装目录}/bin/elasticsearch-plugin install analysis-smartcn </syntaxhighlight> * 安装完成后,重启 ES 即可。 示例: <syntaxhighlight lang="JSON" highlight=""> GET /_analyze { "text": "红烧牛肉面", "analyzer": "smartcn" } </syntaxhighlight> 输出: <syntaxhighlight lang="JSON" highlight=""> { "tokens" : [ { "token" : "红烧", "start_offset" : 0, "end_offset" : 2, "type" : "word", "position" : 0 }, { "token" : "牛肉面", "start_offset" : 2, "end_offset" : 5, "type" : "word", "position" : 1 } ] } </syntaxhighlight> === ik 分词器 === ik 支持'''自定义扩展词库''':有时候分词的结果不满足我们业务需要,需要根据业务设置专门的词库,词库的作用就是自定义一批关键词,分词的时候优先根据词库设置的关键词分割内容。 : 例如:词库中包含 “上海大学” 关键词,如果对“上海大学在哪里?”进行分词,“上海大学” 会做为一个整体被切割出来。 ik 分词插件支持两种分词器: # '''ik_smart''':粗粒度的分词; # '''ik_max_word''':尽可能的枚举可能的关键词; 插件安装: # 找到自己 ES 版本一致的插件:[https://github.com/medcl/elasticsearch-analysis-ik/releases https://github.com/medcl/elasticsearch-analysis-ik/releases] #: 如,ES 7.5.1 的 ik 插件版本地址是:[https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.1/elasticsearch-analysis-ik-7.5.1.zip https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.1/elasticsearch-analysis-ik-7.5.1.zip] # 安装命令: #: <syntaxhighlight lang="bash" highlight=""> {ES安装目录}/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.1/elasticsearch-analysis-ik-7.5.1.zip </syntaxhighlight> * 安装完成后,重启 ES 即可。 示例 1: <syntaxhighlight lang="JSON" highlight=""> GET /_analyze { "text": "上海人民广场麻辣烫", "analyzer": "ik_smart" } </syntaxhighlight> 输出: <syntaxhighlight lang="JSON" highlight=""> { "tokens" : [ { "token" : "上海", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 0 }, { "token" : "人民", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 1 }, { "token" : "广场", "start_offset" : 4, "end_offset" : 6, "type" : "CN_WORD", "position" : 2 }, { "token" : "麻辣烫", "start_offset" : 6, "end_offset" : 9, "type" : "CN_WORD", "position" : 3 } ] } </syntaxhighlight> 示例 2: <syntaxhighlight lang="JSON" highlight=""> GET /_analyze { "text": "上海人民广场麻辣烫", "analyzer": "ik_max_word" } </syntaxhighlight> 输出: <syntaxhighlight lang="JSON" highlight=""> { "tokens" : [ { "token" : "上海人", "start_offset" : 0, "end_offset" : 3, "type" : "CN_WORD", "position" : 0 }, { "token" : "上海", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 1 }, { "token" : "人民", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 2 }, { "token" : "广场", "start_offset" : 4, "end_offset" : 6, "type" : "CN_WORD", "position" : 3 }, { "token" : "麻辣烫", "start_offset" : 6, "end_offset" : 9, "type" : "CN_WORD", "position" : 4 }, { "token" : "麻辣", "start_offset" : 6, "end_offset" : 8, "type" : "CN_WORD", "position" : 5 }, { "token" : "烫", "start_offset" : 8, "end_offset" : 9, "type" : "CN_CHAR", "position" : 6 } ] } </syntaxhighlight> === ik 自定义词库 === 自定义扩展词库步骤如下: # '''创建词库文件''',以 '''dic''' 作为扩展名: #* '''一行一个词条'''。 #: 如,词库文件:<code>{ES安装目录}/analysis-ik/config/demo.dic</code> #: <syntaxhighlight lang="xml" highlight=""> 上海大学 复旦大学 人民广场 </syntaxhighlight> # '''创建或者修改配置文件''': #* 路径:<code>{ES安装目录}/analysis-ik/config/IKAnalyzer.cfg.xml</code> #* 内容: #*: <syntaxhighlight lang="xml" highlight=""> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 扩展配置</comment> <!--用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">{ES安装目录}/analysis-ik/config/demo.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典,没有可用删掉配置--> <entry key="ext_stopwords">custom/ext_stopword.dic</entry> <!--用户可以在这里配置远程扩展字典,这个配置需要结合下面配置一起使用,没有可用删掉配置 --> <entry key="remote_ext_dict">location</entry> <!--用户可以在这里配置远程扩展停止词字典,没有可用删掉--> <entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry> </properties> </syntaxhighlight> # 重启 ES。 * Ik 新增扩展词库,支持'''热更新''',不用重启 ES,使用 '''remote_ext_dict''' 和 '''remote_ext_stopwords''' 配置远程词库地址即可。 ** 词库地址需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,ES 靠这两个头识别是否需要更新词库,不了解这两个 HTTP 头,可以搜一下。【???】
返回至“
ElasticSearch查询:全文搜索
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息