设置Elasticsearch N-Gram字分析器的过程

说n-gram是一个大话题,这是轻描淡写的。 进行快速搜索,您会发现自己盯着语言学和语言模型,数据挖掘或特定蛋白质的分解对首次亮相文化的衰落所隐含的信息量。

好吧,我在跟那最后一个开玩笑。 但是,如果您是开发人员,希望使用Elasticsearch在应用程序中进行搜索,那么您很有可能需要以实用的方式使用n-gram分析器来进行某些搜索,并且可能需要一些针对性的信息才能获得您的搜索以期望的方式表现。 在Elasticsearch中使用n-gram搜索可以做的事情有很多可能性。 该博客将使您开始思考如何在搜索中使用它们。

一个例子

首先,让我们在这里缩小一下范围。 在很多情况下,使用n-gram可能是指搜索句子,而您的gram则是指句子中的单词。 但是对于今天,我想集中讨论单个单词的细分。 n元语法世界中的单个单词称为带状疱疹。

让我们进一步缩小自己的范围,假设我们想使用此搜索进行近似匹配。 在应用程序中,要搜索单词(名称,用户名)或类似于单词的数据(电话号码),然后以与搜索单词紧密匹配的形式向搜索者提供更多信息,这并不少见。 在这里,我们还希望部分匹配该单词,而不是总是在前面,也不总是在结尾。

为了便于参考,请假装我们有一个可以按名称查找动物的站点。 也许这是兽医办公室的前线,而该办公室希望首先以宠物的名字进行所有查找。 当然,您可能会发现自己Swift扩大了搜索范围,以包括其他条件,但举个例子,假设该办公室的所有爱狗人士都疯了,必须使用狗的名字。

分析仪

现在让我们考虑一下分析仪的需求。 首先,我们已经知道我们想要某种n-gram。 我们想要部分匹配。 其次,上面我们已经决定要搜索单词内的部分匹配项。 在这种情况下,这将仅在一定程度上,正如我们稍后将看到的那样,但是现在我们可以确定我们需要NGram令牌生成器,而不是仅保留从令牌开头开始保留n-gram的Edge NGram令牌生成器。

ElasticSearch Ngrams允许最小和最大克数。 从最小值开始,我们要匹配多少个名字? 好的,默认值为1,但是由于我们已经在处理单个单词的数据,所以如果我们使用一个字母(一个字母组合),我们肯定会得到太多的结果。 实际上,同样的事情也将适用于二元组。 但是,足够多的人养着三个字母的宠物,我们最好不要走,否则我们可能永远不会在搜索结果中返回名为“ Ace”和“ Rex”的幼犬。 现在我们知道我们的最小克数将是3。 最大克呢? 默认值为2,我们已经超过了最小值。 我们的目标是尽可能多地包含潜在的准确匹配项,但在索引大小存储方面仍然不会发疯。

考虑选择一个过大的数字(例如52),并为3个字符至52个字符之间的所有可能可能性分解名称,您会发现随着数据的增长,这很快就会加起来。 这里有些妥协,因为在某些情况下,您最终可能会排除超出最大语法的数据。

解决此排除问题的方法有两种,一种是包含您的字段的第二个映射并使用其他分析器(例如标准分析器),或者使用第二种映射并受益于精确匹配的速度和准确性字词查询。

在我们的案例中,我们将利用将单独的分析器用于搜索和索引的功能。 我们假设最大值之后的数据与我们的搜索无关,在这种情况下,它极有可能与搜索无关。

因此,这里我们创建索引,然后设置自定义分析器。 关于整体内容,这里的示例将有些简单,但是我希望它们有助于理解。

注意:稍微偏离主题,但是在现实生活中,您将需要以一种更可重用的方式进行操作,例如模板,以便您可以轻松使用别名和版本并更新索引,但是为此例如,我只是展示了卷曲索引创建的最简单设置。

这是我们的第一个分析器,创建一个自定义分析器,并使用ngram_tokenizer和我们的设置。 如果您在这里,则可能知道这一点,但是令牌生成器用于将字符串分解为术语或令牌流。 您可以根据需要在此处添加空格和许多其他选项:

curl -XPUT 'localhost:9200/searchpets' -d '{"settings" : {"analysis" : {"analyzer" : {"ngram_analyzer" : {"tokenizer" : "ngram_tokenizer"}},"tokenizer" : {"ngram_tokenizer" : {"type" : "nGram","min_gram" : "3","max_gram" : "8"}}}}}'

我们对此索引创建的响应为{“ acknowledged”:true}。 优秀的。

好了,既然有了索引,使用新的分析仪时数据将是什么样?

curl -XGET'localhost:9200/searchpets/_analyze?analyzer=ngram_analyzer' -d 'Raven'

响应是:

{"tokens":[{"token":"Rav","start_offset":0,"end_offset":3,"type":"word","position":1},{"token":"Rave","start_offset":0,"end_offset":4,"type":"word","position":2},{"token":"Raven","start_offset":0,"end_offset":5,"type":"word","position":3},{"token":"ave","start_offset":1,"end_offset":4,"type":"word","position":4},{"token":"aven","start_offset":1,"end_offset":5,"type":"word","position":5},{"token":"ven","start_offset":2,"end_offset":5,"type":"word","position":6}]}

这是合理的。 所有令牌都在3到5个字符之间生成(因为单词少于8个,所以很明显)。

好的,太好了,现在将其应用于字段。 而且,是的,您绝对可以一步一步完成所有操作,我只是将其分解。

$ curl -XPUT 'http://localhost:9200/searchpets/_mapping/pet' -d '
{"pet": {"properties": {"name": {"type": "string","analyzer": "ngram_analyzer"}}}
}
'

我们在现场测试分析:

curl -XGET 'http://localhost:9200/searchpets/_analyze?field=pet.name' -d 'Raven';

再一次,我们得到了我们期望的结果:

{"tokens":[{"token":"Rav","start_offset":0,"end_offset":3,"type":"word","position":1},{"token":"Rave","start_offset":0,"end_offset":4,"type":"word","position":2},{"token":"Raven","start_offset":0,"end_offset":5,"type":"word","position":3},{"token":"ave","start_offset":1,"end_offset":4,"type":"word","position":4},{"token":"aven","start_offset":1,"end_offset":5,"type":"word","position":5},{"token":"ven","start_offset":2,"end_offset":5,"type":"word","position":6}]}

现在,假设我已经继续并在此处添加了一些记录,并针对以下内容运行简单的匹配查询:{“ query”:{“ match”:{“ name”:“ Pegasus”}}}。

利用我的数据,我们可以得到以下信息:

"hits": {"total": 2,"max_score": 0.29710895,"hits": [{"_index": "searchpets","_type": "pet","_id": "3","_score": 0.29710895,"_source": {"name": "Pegasus"}},{"_index": "searchpets","_type": "pet","_id": "2","_score": 0.0060450486,"_source": {"name": "Degas"}}]
}
}

我们获得最接近的匹配以及可能实际上是用户正在寻找的关闭选项。

定制分析仪

好的,但是现在我们正在使用一个非常基本的分析器案例。 如果我们需要一个自定义分析器,以便能够处理在搜索和索引上需要不同的分词器的情况,该怎么办? 如果我们想用关键字标记器来限制搜索怎么办?

让我们对其进行更改,以使用针对n元语法的过滤器来设置自定义分析器。 由于我们在下一次搜索中使用了tokenizer关键字和match查询,因此在显示的这些测试用例中,此处的结果实际上与之前的结果相同,但是您会注意到它们的评分方式有所不同。

$ curl -XPUT 'localhost:9200/searchpets' -d '{"settings": {"analysis": {"analyzer": {"namegrams": {"type": "custom","tokenizer": "keyword","filter": ["ngrams_filter"]}},"filter": {"ngrams_filter": {"type": "ngram","min_gram": 3,"max_gram": 8}}}}
}'

现在,我们像以前一样添加映射和数据:

curl -XPUT 'http://localhost:9200/searchpets/_mapping/pet' -d '
{"pet": {"properties": {"name": {"type": "string","analyzer": "namegrams"}}}
}
'

我运行另一个匹配查询:{“ query”:{“ match”:{“ name”:“ Pegasus”}}},响应为:

hits": {
"total": 2,
"max_score": 1.1884358,
"hits": [{"_index": "searchpets","_type": "pet","_id": "2","_score": 1.1884358,"_source": {"name": "Pegasus"}},{"_index": "searchpets","_type": "pet","_id": "3","_score": 0.08060065,"_source": {"name": "Degas"}}
]
}

因此,我们进行了设置,并基于关键字标记器和n-grams过滤器获得了期望的结果和评分。 假设我们正在做一些更复杂的查询。 我们可能还添加了其他一些过滤器或标记器。 情况看起来不错,对吗? 好吧,差不多。

我前面提到的所有这些要记住的一个小因素。 我们有一个最大的8克。 那么,当我们拥有一个超过该大小的名称作为搜索条件时,会发生什么呢? 好吧,根据您的搜索,您可能不会获得任何数据。

您可能没有想到这里会发生什么! 您如何避免这种情况? 一种方法是使用不同的index_analyzer和search_analyzer。 拆分这些内容可以使您更好地控制搜索。

因此,假设我们对原始搜索所说的一切都是真实的,那么您的最终设置将是这样。 我不会深入探讨查询本身的详细信息,但是我们将假定它将使用指定的search_analyzer(我建议阅读ES文档中有关如何选择分析器进行搜索的层次结构)。

注意:这里的search_ngram分析器上的小写标记器会标准化标记文本,因此所有数字都将被剥离。 此示例适用于此示例,但是使用不同的数据可能会导致意外的结果。

$ curl -XPUT 'localhost/searchpets' -d '{"settings": {"analysis": {"analyzer": {"namegrams": {"type": "custom","tokenizer": "keyword","filter": ["ngrams_filter"]},"search_ngram": {"type": "custom","tokenizer": "lowercase","filter": ["truncate_filter"]}},"filter": {"ngrams_filter": {"type": "ngram","min_gram": 3,"max_gram": 8},"truncate_filter": {"type": "truncate","length": 8}}}}
}
’

然后,最后,我们再次设置映射:

curl -XPUT 'http://localhost:9200/searchpets/_mapping/pet' -d '
{"pet": {"properties": {"name": {"type": "string","index_analyzer": "namegrams","search_analyzer": "search_trigram"}}}
}'

最后的想法

那里有。 但是,这使得假设超过8个字符的数据不太重要。 如果您要拥有比最大克数更大的数据,并且类似的数据,您可能会发现自己需要进一步调整。

在Elastisearch中使用n-gram搜索可以做的事情有很多可能性。 我希望这可以让您开始思考如何在搜索中使用它们。

翻译自: https://www.javacodegeeks.com/2015/11/anatomy-of-setting-up-an-elasticsearch-n-gram-word-analyzer.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336859.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java字节码反编译_javap 反编译 java 字节码文件

概述:javap是 Java class文件分解器,可以反编译,也可以查看java编译器生成的字节码,从而对代码内部的执行逻辑进行分析。语法:把java文件编译为class文件:javac Test.java (Test.java为java文件名) 生成对…

javaone_JavaOne演讲者选择了您不容错过的10个会话

javaone确保会议安排中包含这些JavaOne会话 JavaOne 2015从这个星期日开始,数百个会话同时进行,因此很难筛选所有会话并选择要参加的会话。 这就是为什么我们邀请5位最喜欢的JavaOne发言人让我们了解他们的会议,并选择他们最期待的会议。 好…

java servlet文件下载_Java之Servlet文件下载20190228

jsp页面:pageEncoding"utf-8"%>Insert title here下载index.jsp下载1.jpg下载test.jspServlet:packageorg.jimmy.testwebproject2019012602.servlet.download;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;importjavax.se…

activiti 多租户_Activiti中具有独立数据库架构的多租户

activiti 多租户我们过去听到的一项功能请求是以多租户方式运行Activiti引擎,使租户的数据与其他数据隔离。 当然,在某些云/ SaaS环境中,这是必须的。 几个月前,波恩大学的学生拉斐尔吉伦(Raphael Gielen)…

jigsaw kaggle_使用Project Jigsaw的JDK 9 Early Access上的Eclipse IDE

jigsaw kaggle几周前,我写了关于在Java 9上运行Eclipse Neon的文章 (尽管,我在帖子标题中错误地且令人尴尬地留下了“火星”)。 值得注意的是,我列出的步骤也适用于带有Project Jigsaw (Java模块化&#xf…

win7 activemq_带有骆驼,ActiveMQ,Elasticsearch的关键HL7用例

win7 activemqML7上的HL7是可以说HL7协议格式的系统的一种非常常见的传输机制。 JBoss Fuse是一个非常强大的微服务样式集成平台,在为关键医疗保健提供者构建灵活,有弹性,高可用性的集成方案方面拥有良好的经验。 此外,在JCAPS上替…

jboss4 迁移_应用程序服务器迁移:从JBoss EE5到Wildfly EE7

jboss4 迁移几周前,我发布了一个有关从Java EE 5迁移到7的博客 。这主要是关于如何使用新的Java EE 7改进Java EE 5代码。 现在,在这篇文章中,我将对应用程序服务器端的迁移路径进行一些研究。 如果您使用的是Java EE 5,则很有可…

java xmlrpc2.0 实现_简单的java xmlrpc

简单的 XMLRPCjava---XmlRpcClientpackage com.company;import org.apache.xmlrpc.XmlRpcClient;import org.apache.xmlrpc.XmlRpcException;import java.net.MalformedURLException;import java.util.Hashtable;import java.util.Vector;public class…

操作方法:带有Thymeleaf和Spring Boot的Java 8日期和时间

如果您碰巧使用Spring Boot和Thymeleaf,并且需要在视图中格式化Java 8 Date&Time对象,则可以使用thymeleaf-extras-java8time –用于Java 8 Date&Time API的Thymeleaf模块。 向现有的基于Maven或Gradle的Spring Boot项目中添加th…

java boundary_上传文件multipart form-data boundary 说明

含义 ENCTYPE"multipart/form-data" 说明:通过 http 协议上传文件 rfc1867协议概述,客户端发送内容构造。概述在最初的 http 协议中,没有上传文件方面的功能。 rfc1867为 http 协议添加了这个功能。客户端的浏览器,如 M…

java 预处理语句_预处理语句PreparedStatement到底咋用啊

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼我自己试了一下直接查询id为1的语句,有一条结果出来,但是用了PreparedStatement后就没有结果了,有大佬知道为什么吗orzpackage test;import java.io.IOException;import java.io.PrintWriter;imp…

crud-table_我个人的CRUD故事-或我如何来到CUBA平台

crud-table在此博客文章中,我想介绍一下我如何使用CUBA平台以及该工具的好处。 在我年轻的“业务应用程序开发”历史上,我将深入探讨各个阶段,只是给您一些背景知识。 因此,让我们从如何进入典型的CRUD应用程序开始,以…

python api接口生成_Django 自动生成api接口文档教程

最近在写测试平台,需要实现一个节点服务器的api,正好在用django,准备使用djangorestframework插件实现。需求实现一个接口,在调用时,通过传递的参数,直接运行对应项目的自动化测试环境Python3.6 ,PyCharm,W7项目结构功…

eclipse clean_Clean Sheet – Windows 10的人体工程学Eclipse主题

eclipse cleanClean Sheet是适用于Windows 10的符合人体工程学的Eclipse主题。它基于干净,低眩光的外观和感觉,旨在减轻视觉疲劳和眼睛疲劳。 它融合了均衡的颜色选择,可以突出谐波语法并注重可读性。 除自定义滚动条外,它还努力满…

什么时候需要使用cqrs_在CQRS读取模型中使用Hibernate进行快速开发

什么时候需要使用cqrs在本文中,我将分享一些在CQRS读取模型中使用Hibernate工具进行快速开发的技巧。 为什么要Hibernate? Hibernate非常流行。 从外观上看,它也很容易,而从内部看,它却相当复杂。 它可以很容易地上手…

java面试题三_最全的java面试题目三

78、什么情况下调用doGet()和doPost()?答:Jsp页面中的form标签里的method属性为get时调用doGet(),为post时调用doPost()。79、servlet的生命周期答:web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行…

python的内存管理机制及调优手段_Python的内存管理机制及调优手段

内存管理机制:引用计数、垃圾回收、内存池引用计数:引用计数是一种非常高效的内存管理手段,当一个Python对象引用时其引用计数加一,当其不再被一个变量引用时则减一。当引用计数等于0时对象被删除。1.引用计数:引用计数…

tcga癌症亚型获取_亚型多态性应用于元组的危险

tcga癌症亚型获取Java 8具有lambda和stream&#xff0c;但是没有元组&#xff0c;这真是令人遗憾 。 这就是为什么我们在jOOλ中实现了元组-Java 8的缺失部分 。 元组确实是无聊的值类型容器。 本质上&#xff0c;它们只是这些类型的枚举&#xff1a; public class Tuple2<…

java 隐藏了什么_JAVA程序中封装与隐藏是什么意思

qq_遁去的一_1隐藏就是封装吧。。。。封装是把过程和数据包围起来&#xff0c;对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念&#xff0c;即现实世界可以被描绘成一系列完全自治、封装的对象&#xff0c;这些对象通过一个受保护的接口访问其他对象。封装是一…

esb 和 开源esb_如果今天完成,ESB会是什么样子?

esb 和 开源esbJavaOne 2015即将结束&#xff0c;这又是一次很棒的社区活动。 我和Rafael进行了两次会议和一次HOL 。 我最喜欢的会议之一实际上是&#xff1a;谈论ESB&#xff0c;如果今天完成的话。 我以为那是过去&#xff1f; 我通常也倾向于这样说。 但是&#xff0c;系统…