在之前的博客中,我们介绍了如何将同义词合并到由 Elasticsearch 驱动的应用程序中。 在这里,我以该博客为基础,展示了如何结合词干分析器(stemmer)和多词同义词(multi-word synonyms),将搜索结果的质量提升到一个新的水平。

动机

想象一下,你正在使用 Elasticsearch 为搜索应用程序提供搜索引擎以查找书籍,并且在此应用程序中你希望将以下单词视为同义词:

  • brainstorm
  • brainstorming
  • brainstormed
  • brain storm
  • brain storming
  • brain stormed
  • envisage
  • envisaging
  • envisaged
  • 等等

明确地使用同义词来定义一个词或复合词的所有可能的变形、变格和屈折变化是乏味和容易出错的。

但是,可以通过在应用同义词之前使用词干分析器提取每个单词的词干来减少同义词列表的大小。 这将允许我们通过仅指定以下同义词来获得与上述同义词列表相同的结果:

  • brainstorm
  • brain storm
  • envisage

定制分词器

在本节中,我将展示定义可用于匹配同义词的定制分词器的代码片段。 稍后在本博客中,我将展示如何将分析器提交给 Elasticsearch。

我们之前的博客详细介绍了索引时(index-time)和搜索时(search-time)同义词之间的区别。 在此处提供的解决方案中,我使用了搜索时同义词。

我们将创建一个同义词图标记过滤器,使用 “brainstorm” 及 “envisage” 匹配多词同义词 “brain storm”。 这也会将 “mind” 和 “brain” 视为同义词。 我们将把这个标记过滤器称为 my_graph_synonyms,它看起来如下:

"filter": { "my_graph_synonyms": { "type": "synonym_graph", "synonyms": [ "mind, brain", "brain storm, brainstorm, envisage" ] }
}

接下来我们需要定义两个单独的定制分词器,一个将在索引时应用于文本,另一个将在搜索时应用于文本。

我们定义了一个名为 my_index_time_analyzer 的分词器,它使用标准分词器、小写分词过滤器和词干分词过滤器,如下所示:

"my_index_time_analyzer": { "tokenizer": "standard", "filter": [ "lowercase", "stemmer" ]
}

我们定义了一个名为 my_search_time_analyzer 的分词器,它也使用了标准分词器、小写分词过滤器和词干分词过滤器(如上)。 但是,这也包括我们称为 my_graph_synonyms 的自定义标记过滤器,可确保在搜索时匹配同义词:

"my_search_time_analyzer": { "tokenizer": "standard", "filter": [ "lowercase", "stemmer", "my_graph_synonyms" ]
}

Mapping

Mapping 是定义文档及其包含的字段如何存储和索引的过程。 每个文档都是字段的集合,每个字段都有自己的数据类型。 在此示例中,我们使用名为 my_new_text_field 的单个字段定义文档的mapping,我们将其定义为文本。 当文档被索引时,这个字段将使用 my_index_time_analyzer,当文档被搜索时将使用 my_search_time_analyzer。 映射如下所示:

"mappings": { "properties": { "my_new_text_field": { "type": "text", "analyzer": "my_index_time_analyzer", "search_analyzer": "my_search_time_analyzer" } }
}

把它放在一起

下面我们结合我们的自定义分析器和映射并将其应用到名为 test_index 的索引,如下所示:

PUT /test_index
{ "settings": { "index": { "analysis": { "filter": { "my_graph_synonyms": { "type": "synonym_graph", "synonyms": [ "mind, brain", "brain storm, brainstorm, envisage" ] } }, "analyzer": { "my_index_time_analyzer": { "tokenizer": "standard", "filter": [ "lowercase", "stemmer" ] }, "my_search_time_analyzer": { "tokenizer": "standard", "filter": [ "lowercase", "stemmer", "my_graph_synonyms" ] } } } } }, "mappings": { "properties": { "my_new_text_field": { "type": "text", "analyzer": "my_index_time_analyzer", "search_analyzer": "my_search_time_analyzer" } } }
}

测试我们的自定义搜索时间分词器

如果我们希望查看分析器如何标记和规范化给定字符串,我们可以直接调用 _analyze API,如下所示:

POST test_index/_analyze
{ "text" : "Brainstorm", "analyzer": "my_search_time_analyzer"
}

上面的命令返回的结果是:

{"tokens" : [{"token" : "brain","start_offset" : 0,"end_offset" : 10,"type" : "SYNONYM","position" : 0},{"token" : "envisag","start_offset" : 0,"end_offset" : 10,"type" : "SYNONYM","position" : 0,"positionLength" : 2},{"token" : "brainstorm","start_offset" : 0,"end_offset" : 10,"type" : "<ALPHANUM>","position" : 0,"positionLength" : 2},{"token" : "storm","start_offset" : 0,"end_offset" : 10,"type" : "SYNONYM","position" : 1}]
}

在真实文档上测试

我们可以使用 _bulk API 将多个文档驱动到 Elasticsearch 中,如下所示:

POST test_index/_bulk
{ "index" : { "_id" : "1" } }
{"my_new_text_field": "This is a brainstorm" }
{ "index" : { "_id" : "2" } }
{"my_new_text_field": "A different brain storm" }
{ "index" : { "_id" : "3" } }
{"my_new_text_field": "About brainstorming" }
{ "index" : { "_id" : "4" } }
{"my_new_text_field": "I had a storm in my brain" }
{ "index" : { "_id" : "5" } }
{"my_new_text_field": "I envisaged something like that" }

将上述示例文档写入到 test_index 后,我们可以执行搜索,正确响应文档 #1、#2、#3 和 #5,如下所示:

GET test_index/_search
{ "query": { "match": { "my_new_text_field": "brain storm" } }
}

我们可以执行以下搜索,它仅正确返回文档 #2 和 #4,如下所示:

GET test_index/_search
{ "query": { "match": { "my_new_text_field": "brain" } }
}

我们可以执行以下搜索,它将正确响应文档 #1、#2、#3 和 #5,如下所示:

GET test_index/_search
{ "query": { "match": { "my_new_text_field": "brainstorming" } }
}

我们可以执行以下搜索,正确返回文档 #2 和 #4,如下所示:

GET test_index/_search
{ "query": { "match": { "my_new_text_field": "mind storm" } }
}

最后,我们可以执行以下搜索,它仅正确返回文档 #2 和 #4,如下所示:

GET test_index/_search
{ "query": { "match": { "my_new_text_field": { "query": "storm brain" } } }
}

结论

在这篇博客中,我展示了如何在 Elasticsearch 中结合词干分析器和多词同义词来提高搜索结果的质量。

如果你还没有自己的 Elasticsearch 集群,您可以在几分钟内启动 Elastic Cloud 的免费试用版,或者下载 Elastic Stack 并在本地运行。 如果你更喜欢带有拖放增强和控件的预调整搜索体验,请查看 Elastic App Search。 借助 App Search,你可以轻松实现高度相关的搜索体验,并且它具有用于调整、管理和分析的直观界面。

Elasticsearch:通过结合 Elasticsearch 词干分析器和同义词来提高搜索相关性相关推荐

  1. 【Elasticsearch】改进布尔查询的搜索相关性

    1.概述 翻译:Improving search relevance with boolean queries 有人翻译:Elasticsearch:使用布尔查询提高搜索的相关性 当你在Elastic ...

  2. ElasticSearch 2 (25) - 语言处理系列之同义词

    ElasticSearch 2 (25) - 语言处理系列之同义词 摘要 词干提取有助于通过简化屈折词到它们词根的形式来扩展搜索的范围,而同义词是通过关联概念和想法来扩展搜索范围的.或许没有文档能与查 ...

  3. Elasticsearch:使用同义词 synonyms 来提高搜索效率

    在我们的很多情况下,我们希望在搜索时,有时能够使用一个词的同义词来进行搜索,这样我们能搜索出来更多相关的内容.我们可以通过 text analysis 来帮助我们形成同义词.如果大家对 Elastic ...

  4. Elasticsearch:在 Elasticsearch 中使用语言识别进行多语言搜索

    我们很高兴地宣布,随着机器学习推理摄入处理器 (inference ingest processor)的发布,我们还将在 Elasticsearch 7.6 中发布语言识别. 在此发行版中,我们希望借 ...

  5. 剖析Elasticsearch集群系列第三篇 近实时搜索、深层分页问题和搜索相关性权衡之道...

    http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part03?utm_source=infoq&utm ...

  6. ElasticSearch,docker 安装ElasticSearch,Springboot 使用 ElasticSearch JavaAPI

    什么是 ElasticSearch ? 数据库查询存在的问题: 性能低:使用模糊查询,左边有通配符,不会走索引,会全表扫描,性能低 关键字模糊查询比较麻烦 ElasticSearch概念 • Elas ...

  7. yum安装elasticsearch慢_ELK elasticsearch yum 安装(4th)

    比起tar包安装,以yum方式安装对于启动和关闭elasticsearch服务更为方便.而对于CentOS与Ubuntu而言,apt 安装比yum 更为方便.楼主工作前期中是以CentOS系统为主,后 ...

  8. 【Elasticsearch】使用Elasticsearch中的copy_to来提高搜索效率

    1.概述 转载:使用Elasticsearch中的copy_to来提高搜索效率 在今天的这个教程中,我们来着重讲解一下如何使用Elasticsearch中的copy来提高搜索的效率.比如在我们的搜索中 ...

  9. 【elasticsearch】总结—elasticsearch启动失败的几种情况及解决

    1.使用root用户启动失败 在有一次搭建elasticsearch的时候,使用systemctl启动elasticsearch失败,然后在bin目录下面去使用启动脚本启动,发现报错不能用root用户 ...

最新文章

  1. nurbs建模能用MATLAB么,NURBS(matlab生成nurbs曲线图像)
  2. c#获取DataTable某一列不重复的值,或者获取某一列的所有值
  3. What do you need at home?
  4. boost::multiprecision模块mpfr相关的测试程序
  5. java程序大笨钟怎么打,L1-018.大笨鍾(Java)PAT團體程序設計天梯賽-練習集
  6. 仅用1天,为湖北黄冈中学搭建直播课堂!
  7. ACM-Maximum Tape Utilization Ratio
  8. 对称加密和非对称加密大概介绍和区别
  9. 矩池云上如何修改cudnn版本
  10. python热度评价指标_编程语言流行指数四月榜单发布:Python 持续强势,Java 热度减退...
  11. MongoDB(二)CRUD 指令简单汇总
  12. python gui下载进度条_对python GUI实现完美进度条的示例详解
  13. jupyter 代码到 pycharm 的迁移
  14. 计算机组成原理(第3版)唐朔飞著 知识点总结 第七章 指令系统
  15. tomcat版本号进行隐藏或者删除
  16. 关于Pandownload一些功能的挖掘
  17. hdjs---1、hdjs爬坑杂记
  18. AndroidX迁移
  19. mysql rpl_MySQL半同步复制rpl_semi_sync_master_timeout测试
  20. R语言使用order函数降序排序向量数据、设置decreasing参数进行降序排序

热门文章

  1. lnmp运行php原理,lnmp安装管理运行
  2. Java小游戏——捕鱼达人
  3. 微信小程序-打卡激励小程序—随笔录-tabber无效
  4. 关于路由的一点理解,还有编址
  5. Realplayer将回归 能否重夺原来视频霸主地位
  6. java遍历ArrayList的三种方法
  7. Cocos2d-x 3.2 大富翁游戏项目开发-第二十五部分 大富翁股市
  8. 为什么网吧电脑配置不高却很流畅,自家电脑如何优化配置
  9. 太棒了!2018-2020前端经典面试题整理合集,还附带大厂面试题分享!
  10. 2022.09·最新PC端微信小程序抓包方式