当前位置: 首页 > news >正文

上海企业网站建设公司企业门户网站建设优势

上海企业网站建设公司,企业门户网站建设优势,房子在线设计平台,wordpress 注册邮件与其他需要精确匹配的数据不同#xff0c;文本数据在前期的索引构建和搜索环节都需要进行额外的处理#xff0c;并且在匹配环节还要进行相关性分数计算。本章将详细介绍文本搜索的相关知识。 本章首先从总体上介绍文本的索引建立过程和搜索过程#xff0c;然后介绍分析器的…与其他需要精确匹配的数据不同文本数据在前期的索引构建和搜索环节都需要进行额外的处理并且在匹配环节还要进行相关性分数计算。本章将详细介绍文本搜索的相关知识。 本章首先从总体上介绍文本的索引建立过程和搜索过程然后介绍分析器的构成和使用。ES内置的分析器对于中文的使用略显尴尬因此本章还会介绍当下使用较多的中文分析器然后再介绍使用中文分析器实现的拼音搜索功能。ES对于文本搜索结果提供了高亮显示功能本章的最后会结合实例对其进行详细介绍。 1 文本搜索简介 作为一款搜索引擎框架文本搜索是其核心功能。ES在文本索引的建立和搜索过程中依赖两大组件即Lucene和分析器。其中Lucene负责进行倒排索引的物理构建分析器负责在建立倒排索引前和搜索前对文本进行分词和语法处理。本节将文本的搜索功能拆分成索引建立过程和搜索过程分别进行介绍。 1 文本的索引建立过程 为了完成对文本的快速搜索ES使用了一种称为“倒排索引”的数据结构。倒排索引中的所有词语存储在词典中每个词语又指向包含它的文档信息列表。 假设需要对下面两个酒店的信息进行倒排索引的创建 文档ID为001酒店名称为“金都嘉怡假日酒店”文档ID为002酒店名称为“金都欣欣酒店”。 首先ES将文档交给分析器进行处理处理的过程包括字符过滤、分词和分词过滤最终的处理结果是文档内容被表示为一系列关键词信息的集合。这里的关键词信息指的是关键词本身以及它在文档中出现的位置信息和词性信息如图5.1所示为文档001的分析结果示意图。 其次ES根据分析结果建立文档-词语矩阵用以表示词语和文档的包含关系本例中的文档-词语矩阵如图5.2所示。 通过上面的文档-词语矩阵可知ES从文档001中提取出4个词语从文档002中提取出3个词语。 文档-词语矩阵建立完成之后接着需要建立基于词语的倒排索引。ES会遍历文档词语矩阵中的每一个词语然后将包含该词语的文档信息与该词语建立一种映射关系。映射关系中的词语集合叫作Term Dictionary即“词典”。映射中的文档集合信息不仅包含文档ID还包含词语在文档中的位置和词频信息包含这些文档信息的结构叫作Posting List。对于一个规模很大的文档集合来说可能包含几十万甚至上百万的词语集合能否快速定位某个词语直接影响搜索时的响应速度。因此需要一种高效的数据结构对映射关系中的词语集合进行索引这种结构叫作Term Index。上述3种结构结合在一起就构成了ES的倒排索引结构倒排索引与三者之间的逻辑关系如图5.3所示。 本例中的倒排索引结构如图5.4所示。 2 文本的搜索过程 在ES中一般使用match查询对文本字段进行搜索。match查询过程一般分为如下几步 1ES将查询的字符串传入对应的分析器中分析器的主要作用是对查询文本进行分词并把分词后的每个词语变换为对应的底层lucene term查询。 2ES用term查询在倒排索引中查找每个term然后获取一组包含该term的文档集合。3ES根据文本相关度对每个文档进行打分计算打分完毕后ES把文档按照相关性进行倒序排序。 4ES根据得分高低返回匹配的文档。 如图5.5所示为对酒店索引中搜索“金都嘉怡”的查询流程。 在图5.5中ES分析器先将查询词切分为“金都”和“嘉怡”然后分别到倒排索引里查找两个词对应的文档列表并获得了文档001和002然后根据相关性算法计算文档得分并进行排序最后将文档集合返回给客户端。 2 分析器简介 5.1节提到ES在文本字段的索引建立和搜索阶段都会用到分析器。那么分析器的主要作用是什么它是由哪几部分构成的各部分的作用又是什么呢本节将对这些疑问进行解答。 分析器一般用在下面两个场景中 创建或更新文档时合称索引时对相应的文本字段进行分词处理查询文本字段时对查询语句进行分词。 ES中的分析器有很多种但是所有分析器的结构都遵循三段式原则即字符过滤器、分词器和词语过滤器。其中字符过滤器可以有0个或多个分词器必须只有一个词语过滤器可以有0个或多个。从整体上来讲三个部分的数据流方向为字符过滤器→分词器→分词过滤器。如图5.6所示为一个分析器的构成示例。 在图5.6中文本先以字符流的形式流经字符过滤器在本例中由两个子字符过滤器组成一个字符过滤器组合。字符过滤器处理完字符后将结果传递给分词器分词器对文本进行分词处理后将结果又传递给分词过滤器。在本例中由两个子分词过滤器组成一个分词过滤器组合。最终分析器输出分词后每个词的信息至此一个分析器的处理流程结束。 对于不同的分析器上述三部分的工作内容是不同的为了正确匹配如果在数据写入时指定了某个分析器那么在匹配查询时也需要设定相同的分析器对查询语句进行分析。 1 字符过滤器 字符过滤器是分析器处理文本数据的第一道工序它接收原始的字符流对原始字符流中的字符进行添加、删除或者转换操作进而改变原始的字符流。例如原始数据中可能包含来自爬虫的结果字符过滤器可以去除文本中的HTML标签也可以将原始文本中的一些特殊字符进行转义如把“”转换为and。总而言之字符过滤器就是对原始文本做一些粗加工的工作为后续的分词做准备。 ES内置了一些字符过滤器其中常用的字符过滤器及其功能如表5.1所示。 2 分词器 分词器在分析器中负责非常重要的一环工作——按照规则来切分词语。对于英文来说简单的分词器通常是根据空格及标点符号进行切分。然而对于中文分词来说字符之间往往没有空格因此采用英文的切分规则是不可取的。中文分词有多种切分方案在后面的内容中将会介绍这些方案。不同的分词器采用的方案不同处理后的结果也可能不同。分词器对文本进行切分后需要保留词语与原始文本之间的对应关系因此分词器还负责记录每个Token的位置以及开始和结束的字符偏移量。 3 分词过滤器 分词过滤器接收分词器的处理结果并可以将切分好的词语进行加工和修改进而对分词结果进行规范化、统一化和优化处理。例如它可以将文本中的字母全部转换为小写形式还可以删除停用词如的、这、那等还可以为某个分词增加同义词。 3 分析器的使用 5.2节介绍了分析器的组成和其工作流程接下来将介绍分析器的使用。ES提供了分析器的调用API使用户可以方便地对比不同分析器的分析结果。另外ES提供了一些开箱即用的内置分析器这些分析器其实就是字符过滤器、分词器和分词过滤器的组合体可以在索引建立时和搜索时指定使用这些分析器。当然如果这些分析器不符合需求用户还可以自定义分析器。 1 测试分析API 为了更好地理解分析器的运行结果可以使用ES提供的分析API进行测试。在DSL中可以直接使用参数analyzer来指定分析器的名称进行测试分析API的请求形式如下 POST _analyze { analyzer: ${analyzer_name}, //指定分析器名称 text:${analyzer_text} //待分析文本 }以下示例使用standard分析器分析一段英文 POST _analyze { analyzer: standard, //指定分析器名称为standard text: The letter tokenizer is not configurable. //待分析文本 } 上述文本的分析结果如下 { tokens : [ //分析器将文本切分后的分析结果 { token : the, //将文本切分后的第一个词语 start_offset : 0, //该词在文本中的起始偏移位置 end_offset : 3, //该词在文本中的结束偏移位置 type : ALPHANUM, //词性 position : 0 //该词语在原文本中是第0个出现的词语 }, { token : letter, start_offset : 4, end_offset : 10, type : ALPHANUM, position : 1 }, { token : tokenizer, start_offset : 11, end_offset : 20, type : ALPHANUM, position : 2 }, … ] }据以上结果可以看到standard分析器对文本进行分析时按照空格把上面的句子进行了分词。分析API返回信息的参数说明如下 ·token文本被切分为词语后的某个词语 ·start_offset该词在文本中的起始偏移位置 ·end_offset该词在文本中的结束偏移位置 ·type词性各个分词器的值不一样 ·position分词位置指明该词语在原文本中是第几个出现的。 start_offset和end_offset组合起来就是该词在原文本中占据的起始位置和结束位置。 下面使用standard分析器分析一段中文文本。 POST _analyze { analyzer: standard, //使用standard分析器 text: 金都嘉怡假日酒店 }分析结果如下 { tokens : [ { token : 金, //将文本切分后的第一个词语 start_offset : 0, //该词在文本中的起始偏移位置 end_offset : 1, //该词在文本中的结束偏移位置 type : IDEOGRAPHIC, //词性 position : 0 //该词语在原文本中是第0个出现的词语 }, { token : 都, start_offset : 1, end_offset : 2, type : IDEOGRAPHIC, position : 1 }, … { token : 假, start_offset : 4, end_offset : 5, type : IDEOGRAPHIC, position : 4 }, … ] }如上述结果所示使用standard分析器对中文进行分析时由于中文没有空格无法根据空格进行切分因此只能按单字进行切分并给出了每个单字的词性。在中文里两个单字的词性和每个单字的词性是不同的因此使用standard分析器分析中文时给出的词性不具备参考价值。不仅如此ES内置的其他分析器也不适合分析中文在后面的章节中将介绍专门的中文分析器来解决这些问题。 除了指定分析器进行请求分析外用户还可以指定某个索引的字段使用这个字段对应的分析器对目标文本进行分析。下面使用酒店索引的title字段对应的分析器分析文本。 POST /hotel/_analyze { //使用酒店索引的title字段对应的分析器分析文本 field: title, text: 金都嘉怡假日酒店 }另外用户还可以在API中自定义分析器对文本进行分析。在下面的示例中自定义了一个分析器该分析器的分词器使用standard分词过滤器使用Lower Case其将分词后的结果转换为小写形式。 GET _analyze { tokenizer: standard, //使用standard分词器 filter:[lowercase], //使用Lower Case分词过滤器 text: JinDu JiaYi Holiday Hotel //待分析文本 }2 内置分析器 ES已经内置了一些分析器供用户使用在默认情况下一个索引的字段类型为text时该字段在索引建立时和查询时的分析器是standard。standard分析器是由standard分词器、Lower Case分词过滤器和Stop Token分词过滤器构成的。注意standard分析器没有字符过滤器。除了standard分析器之外ES还提供了simple分析器、language分析器、whitespace分析器及pattern分析器等这些分析器的功能如表5.4所示。 另外用户也可以自定义分析器并且可以在索引建立或搜索时指定自定义分析器。自定义分析器的使用方式将在后面介绍。 3 索引时使用分析器 文本字段在索引时需要使用分析器进行分析ES默认使用的是standard分析器。如果需要指定分析器一种方式是在索引的settings参数中设置当前索引的所有文本字段的分析器另一种方式是在索引的mappings参数中设置当前字段的分析器。 以下示例在settings参数中指定在酒店索引的所有文本字段中使用simple分析器进行索引构建。 PUT /hotel { settings: { analysis: { analyzer: { //指定所有text字段索引时使用simple分析器 default: { type: simple } } } }, mappings: { properties: { … } } } 以下示例在mappings参数中指定在酒店索引的title字段中使用whitespace分析器进行索引构建。 PUT /hotel { mappings: { properties: { title: { type: text, //指定索引中的title字段索引时使用whitespace分析器 analyzer: whitespace }, … } } } 4 搜索时使用分析器 为了搜索时更加协调在默认情况下ES对文本进行搜索时使用的分析器和索引时使用的分析器保持一致。当然用户也可以在mappings参数中指定字段在搜索时使用的分析器。如下示例展示了这种用法 PUT /hotel { mappings: { properties: { title: { type: text, analyzer: whitespace, //索引时使用whitespace分析器 search_analyzer: whitespace //搜索时使用whitespace分析器 }, … } } } 注意这里指定的搜索分析器和索引时的分析器是一致的但是在大多数情况下是没有必要指定的因为在默认情况下二者就是一致的。如果指定的搜索分析器和索引时的分析器不一致则ES在搜索时可能出现有不符合预期的匹配情况因此该设置在使用时需要慎重选择。 5 自定义分析器 当系统内置的分析器不满足需求时用户可以使用自定义分析器。在有些场景中某个文本字段不是自然语言而是在某种规则下的编码。例如在酒店索引中有个sup_env字段其值为“APP,H5,WX”表示当前酒店可以在App、Web端和微信小程序端上显示。假设当前搜索用户使用的是H5或App客户端则需要过滤掉不支持在这两个客户端上显示的酒店。 首先需要在索引创建的DSL中定义分析器comma_analyzer该分析器中只有一个分词组件该分词组件使用逗号进行词语切分然后在mappings中使用analyzer参数指定字段sup_env的分析器为定义好的comma_analyzer分析器。具体的DSL如下 PUT /hotel { settings: { analysis: { analyzer: { comma_analyzer: { //自定义分析器 tokenizer: comma_tokenizer //使用comma_tokenizer分词器 } }, tokenizer: { //定义分词器 comma_tokenizer: { type: pattern, pattern: , //指定切分时使用的分隔符 } } } }, mappings: { properties: { title: { type: text, analyzer: whitespace, //设定title字段索引时使用whitespace分析器 //设定title字段搜索时使用whitespace分析器 search_analyzer: whitespace }, sup_env: { type: text, //设置sup_env字段使用comma_analyzer分析器 analyzer: comma_analyzer }, … } } } 下面向酒店索引中插入几条数据 POST /_bulk {index:{_index:hotel,_id:001}} {title:金都嘉怡假日酒店,city:北京,price:337,sup_env:APP,H5} {index:{_index:hotel,_id:002}} {title:金都欣欣酒店,city:天津,price:200,sup_env:H5,WX} {index:{_index:hotel,_id:003}} {title:金都酒店,city:北京,price:500,sup_env:WX}当前用户的客户端为H5或App当搜索“金都”关键词时应该构建的DSL如下 GET /hotel/_search { query: { bool: { must: [ { //match查询使用whitespace分析器 match: { title: 金都 } }, { //match查询使用comma_analyzer分析器 match: { sup_env: H5,APP } } ] } } } 运行上面的DSL后ES返回的结果如下 { … hits : { … hits : [ //命中的文档集合 { _index : hotel, _type : _doc, _id : 001, _score : 1.5761212, _source : { title : 金都嘉怡假日酒店, … sup_env : App,H5 //切分成App和H5两部分都与查询词匹配 } }, { _index : hotel, _type : _doc, _id : 002, _score : 0.7015199, _source : { title : 金都欣欣酒店, … sup_env : H5,WX //切分成H5和WX其中H5与查询词匹配 } } ] } } 由上面的结果可以看到索引中有3个文档只有文档001和文档002对应的酒店标题中包含“金都”且可以在H5或App客户端显示。使用自定义的分词器可以将以逗号分隔的字段进行分词后建立索引从而在搜索时也使用逗号分隔符进行匹配搜索。 6 中文分析器 对于英文来说一个文档很容易被切分成关键词的集合因为除了标点符号外都是由空格把各个英文单词进行分隔的。例如I have a red car用空格进行切分的结果为I/have/a/red/car。对于中文来说一般由一个或多个字组合在一起形成一个词语并且句子中没有词的界限。根据不同的使用场景对于词语切分颗粒度的需求也是不一样的请看如下示例。 例句我来到北京清华大学。 分词结果1我/来到/北京/清华/华大/大学/清华大学 分词结果2我/来到/北京/清华大学 上面的两种分词方式都是正确的它们可以应用在不同的场景中。 中文分词根据实现原理和特点分词的切分算法主要有两种即基于词典的分词算法和基于统计的机器学习算法。 1 基于词典的分词算法 基于词典的分词算法是按照某种策略将提前准备好的词典和待匹配的字符串进行匹配当匹配到词典中的某个词时说明该词分词成功。该算法是匹配算法中最简单、速度最快的算法其分词算法分为3种即正向最大化匹配法、逆向最大化匹配法和双向最大化匹配法。 2 基于统计的机器学习算法 基于统计的机器学习算法的主要思想是事先构建一个语料库该语料库中是标记好的分词形式的语料然后统计每个词出现的频率或者词与词之间共现的频率等基于统计结果给出某种语境下应该切分出某个词的先验概率。后续进行分词时使用先验概率给出文本应该切分的结果。这类算法中代表的算法有HMM、CRF、深度学习等比如结巴分词基于HMM算法、HanLP分词工具基于CRF算法等。 当前中文分词的难点主要有以下三方面 分词标准不同的分词器使用的分词标准不同分词的结果也不同。例如在分词的颗粒度方面对“中华人民共和国”进行切分时粗粒度的分词就是“中华人民共和国”细粒度的分词可能是“中华”“人民”“共和国”。分词歧义使用分词器对文本进行切分切分后的结果和原来的字面意义不同。例如在“郑州天和服装厂”中“天和”是厂名是一个专有词“和服”也是一个词它们共用了“和”字。如果分词器不够精准则很容易切分成“郑州、和服、服装、服装厂”但是原文中并没有与“和服”有关的含义因此这里就产生了歧义。新词识别新词也称未登录词即该词没有在词典或者训练语料中出现过。在这种情况下分词器很难识别出该词。目前新词识别问题的解决依赖于人们对分词技术和中文结构的进一步认识。 ES通过安装插件的方式来支持第三方分析器。比较常用的第三方中文分析器是HanLP和IK分析器后面小节将对这两个分析器进行介绍。 3 IK分析器 IK分析器是一个开源的、基于Java语言开发的轻量级的中文分词工具包它提供了多种语言的调用库。在ES中IK分析器通过第三方插件的方式来使用其代码托管到了GitHub上项目地址为https://github.com/medcl/elasticsearch-analysis-ik。IK分析器实现了词典的冷更新和热更新用户可以选择适合自己的方式进行词典的更新。 安装https://blog.csdn.net/zs18753479279/article/details/128902665?spm1001.2014.3001.5501 下例使用ik_max_word分析器对待测试文本进行分析。 POST _analyze { analyzer: ik_max_word, //使用ik_max_word中文分析器分析文本 text: 金都嘉怡假日酒店 } 分析结果如下 { tokens : [ { token : 金都, //将文本进行切分“金都”被切分出来 start_offset : 0, end_offset : 2, type : CN_WORD, position : 0 //“金都”是第一个被切分出的词语索引位置为0 }, { token : 嘉, start_offset : 2, end_offset : 3, type : CN_CHAR, position : 1 }, { token : 怡, start_offset : 3, end_offset : 4, type : CN_CHAR, position : 2 }, { token : 假日酒店, start_offset : 4, end_offset : 8, type : CN_WORD, position : 3 }, { //ik_max_word分析器的词语切分颗粒度较细将“假日”单独切分了出来 token : 假日, start_offset : 4, end_offset : 6, type : CN_WORD, position : 4 }, { //ik_max_word分析器的词语切分颗粒度较细将“酒店”单独切分了出来 token : 酒店, start_offset : 6, end_offset : 8, type : CN_WORD, position : 5 } ] } 下例使用ik_smart分析器对待测试文本进行分析。 POST _analyze { analyzer: ik_smart , //使用ik_smart分析器 text: 金都嘉怡假日酒店 } 分析结果如下 { tokens : [ { token : 金都, //将文本进行切分切分出词语“金都” start_offset : 0, end_offset : 2, type : CN_WORD, position : 0 //“金都”是第一个被切分出的词语索引位置为0 }, { token : 嘉, start_offset : 2, end_offset : 3, type : CN_CHAR, position : 1 }, { token : 怡, start_offset : 3, end_offset : 4, type : CN_CHAR, position : 2 }, { token : 假日酒店, start_offset : 4, end_offset : 8, type : CN_WORD, position : 3 } ] } 从上述两个分析结果中可以看到ik_max_word和ik_smart分析器的主要区别在于切分词语的粒度上ik_smart的切分粒度比较粗而ik_max_word将文本进行了最细粒度的拆分甚至穷尽了各种可能的组合。 另外可以看到“嘉怡”这个词被切分成了“嘉”和“怡”这个词没有在IK分析器的词典里因此被切分成了两个单字这需要为IK分析器添加词典来解决该问题。在IK分析器的安装目录下的config子目录中创建文件my.dict在其中添加“嘉怡”即可。如果有更多的词语需要添加则每个词语单独一行添加示例如图5.9所示。 添加完成后修改IK分析器的配置文件路径为config/IKAnalyzer.cfg.xml将新建的字典文件加入ext_dict选项中如图5.10所示。 配置完成后重启ES然后使用分析器分析上面的文本此时“嘉怡”就可以被切分出来。下面是使用ik_smart分析器切分文本的过程。 { tokens : [ { token : 金都, start_offset : 0, end_offset : 2, type : CN_WORD, position : 0 }, { token : 嘉怡, // 添加自定义词典后ik_smart分析器将“嘉怡”切分了出来 start_offset : 2, end_offset : 4, type : CN_WORD, position : 1 }, { token : 假日酒店, start_offset : 4, end_offset : 8, type : CN_WORD, position : 2 } ] } 安装完毕后也可以将IK分析器应用到索引的字段中。下面将ik_max_word分析器设置为酒店索引中title字段的默认分析器。 PUT /hotel { mappings: { properties: { title: { type: text, analyzer: ik_max_word //指定title字段使用ik_max_word分析器 }, … } } } 7 使用同义词 在搜索场景中同义词用来处理不同的查询词有可能是表达相同搜索目标的场景。例如当用户的查询词为“带浴缸的酒店”和“带浴池的酒店”时其实是想搜索有单独泡澡设施的酒店。再例如在电商搜索中同义词更是应用广泛如品牌同义词Adidas和“阿迪达斯”产品同义词“投影仪”和“投影机”修饰同义词“大码”和“大号”等。用户在使用这些与同义词相关的关键词进行搜索时搜索引擎返回的搜索结果应该是一致的。如图5.13所示左右两幅图分别是在京东商城和天猫商城中搜索“番茄”后的返回结果。 从上面的结果中可以看到搜索“番茄”时两个电商平台都会匹配“番茄”和“西红柿”相关产品。 用户还可以通过ES中的分析器来使用同义词使用方式分为两种一种是在建立索引时指定同义词并构建同义词的倒排索引另一种是在搜索时指定字段的search_analyzer查询分析器使用同义词。 1 建立索引时使用同义词 在ES内置的分词过滤器中有一种分词过滤器叫作synonyms它是一种支持用户自定义同义词的分词过滤器。以下是使用IK分析器和synonyms分词过滤器一起定义索引的DSL PUT /hotel { settings: { analysis: { filter: { //定义分词过滤器 ik_synonyms_filter: { type: synonym, synonyms: [ //在分词过滤器中定义近义词 北京,首都, 天津,天津卫, 假日,度假 ] } }, analyzer: { //自定义分析器 ik_analyzer_synonyms: { tokenizer: ik_max_word, //指定分词器 filter: [ //指定分词过滤器 lowercase, ik_synonyms_filter ] } } } }, mappings: { properties: { title: { type: text, analyzer: ik_analyzer_synonyms //指定索引时使用自定义的分析器 }, … } } } 为方便测试下面向酒店索引中写入几条数据 POST /_bulk {index:{_index:hotel,_id:001}} {title: 文雅假日酒店} {index:{_index:hotel,_id:002}} {title: 北京金都嘉酒店} {index:{_index:hotel,_id:003}} {title: 天津金都欣欣酒店} {index:{_index:hotel,_id:004}} {title: 金都酒店} {index:{_index:hotel,_id:005}} {title: 文雅精选酒店} 搜索关键词“首都度假酒店”DSL如下 GET /hotel/_search { query: { //使用match搜索 match: { title: 首都度假 } } } 搜索后的返回结果如下 { … hits : { … max_score : 2.1445937, hits : [ { _index : hotel, _type : _doc, _id : 002, _score : 2.1445937, _source : { title : 北京金都嘉酒店 //字段中的“北京”与查询词中的“首都”匹配 } }, { _index : hotel, _type : _doc, _id : 001, _score : 1.7899693, _source : { title : 文雅假日酒店 //字段中的“度假”与查询词中的“假日”匹配 } } ] } } 由上面的结果可见酒店标题中的“北京”和“假日”分别可以匹配查询词中的“首都”和“度假”说明前面的同义词设置成功。 2 查询时使用同义词 在ES内置的分词过滤器中还有个分词过滤器叫作synonym_graph它是一种支持查询时用户自定义同义词的分词过滤器。 以下是使用IK分析器和synonym_graph分词过滤器一起定义索引的DSL PUT /hotel { settings: { analysis: { filter: { //定义分词过滤器 ik_synonyms_graph_filter: { type: synonym_graph, synonyms: [ //在分词过滤器中定义近义词 北京,首都, 天津,天津卫, 假日,度假 ] } }, analyzer: { //自定义分析器 ik_analyzer_synonyms_graph: { tokenizer: ik_max_word, //指定分词器 filter: [ //指定分词过滤器 lowercase, ik_synonyms_graph_filter ] } } } }, mappings: { properties: { title: { type: text, analyzer: ik_max_word, //指定查询时使用自定义的分析器 search_analyzer: ik_analyzer_synonyms_graph }, … } } } 使用与5.5.1节相同的数据搜索关键词“首都度假”DSL如下 GET /hotel/_search { query: { //使用match搜索 match: { title: 首都度假 } } } 搜索后的返回结果如下 { … hits : { … hits : [ //命中的文档集合 { _index : hotel, _type : _doc, _id : 001, _score : 1.2929529, _source : { title : 文雅假日酒店 } }, { _index : hotel, _type : _doc, _id : 002, _score : 1.2929529, _source : { title : 北京金都嘉酒店 } } ] } } 通过对比两种方式的结果可以看到命中的结果集和索引时使用的同义词一致但是结果的排序却不同。这是因为在索引时使用同义词会计算全部的同义词的TF/IDF值在搜索时进行的相关性计算是将同义词和其他词同等对待也就是将其TF/IDF值计算在内。而在搜索时使用同义词需要ES将同义词转换后再进行相关性计算。以下DSL是查看查询词“度假”和文档001匹配的情况 GET /hotel/_explain/001 { //查看查询词和文档的匹配情况 query: { match: { title: 度假 } } } ES的返回结果如下 { _index:hotel, _type:_doc, _id:001, matched:true, explanation:{ //ES将查询词改写成“title:假日”和“title:度假” value:1.2929529, description:weight(Synonym(title:假日 title:度假) in 0) [PerFieldSimilarity], result of:, details:[ //具体的匹配打分过程 { value:1.2929529, description:score(freq1.0), computed as boost * idf * tf from:, … } ] } } 根据explain的结果来看ES将查询改写为title字段匹配关键字“假日”或者“度假”。 如果有更新同义词的需求则只能使用查询时使用同义词的这种方式。首先需要先关闭当前索引 POST /hotel/_close 下面更改索引的settings信息新添加一组近义词“精选豪华” PUT /hotel/_settings { analysis: { filter: { ik_synonyms_graph_filter: { //定义分词过滤器 type: synonym_graph, synonyms: [ //在分词过滤器中定义近义词 北京,首都, 天津,天津卫, 假日,度假, 精选,豪华 ] } }, analyzer: { //自定义分析器 ik_analyzer_synonyms_graph: { tokenizer: ik_max_word, //指定分词器 filter: [ lowercase, ik_synonyms_graph_filter //指定分词过滤器 ] } } } } 打开索引 POST /hotel/_open搜索关键词“豪华”搜索结果如下 { … hits : { … hits : [ { _index : hotel, _type : _doc, _id : 005, _score : 1.456388, _source : { title : 文雅精选酒店 //字段中的“精选”与查询词“豪华”匹配 } } ] } } 根据上述结果可见通过更新同义词之前添加的“精选豪华”已经在搜索时生效。 如果同义词比较多在settings中进行配置时将非常烦琐。ES支持用户将同义词放在文件中文件的位置必须是在${ES_HOME}/config目录及其子目录下注意该文件必须存在于ES集群中的每一个节点上。在${ES_HOME}/config目录下建立一个子目录mydict然后在该目录下创建一个名称为synonyms.dict的文件文件内容如图5.14所示。然后在创建酒店索引时在settings中指定同义词文件及其路径DSL如下 PUT /hotel { settings: { analysis: { filter: { //定义分词过滤器 ik_synonyms_graph_filter: { type: synonym_graph, synonyms_path:mydict/synonyms.dict //指定同义词文件及其路径 } }, analyzer: { ik_analyzer_synonyms_graph: { tokenizer: ik_max_word, //指定分词器 filter: [ lowercase, ik_synonyms_graph_filter //指定分词过滤器 ] } } } }, mappings: { properties: { title: { type: text, analyzer: ik_max_word, //指定查询时使用自定义的分析器 search_analyzer: ik_analyzer_synonyms_graph }, … } } } 当同义词词典文件内容更新时例如在其中添加“酒店旅店”后则需要执行如下请求 POST /hotel/_reload_search_analyzers 执行上述请求后同义词得到更新后续就可以在查询中使用新添加的同义词了。 8 使用停用词 停用词也叫停止词是指文本在被分词之后的词语中包含的无搜索意义的词。什么叫作“无搜索意义”呢假设文本为“这里的世界丰富多彩”那么分词结果中的“这里”和“的”对于匹配这个文档来说意义不大因为这两个词的使用频率非常高并且没有太多独特的意义。在构建搜索引擎索引时常常忽略这样的词这样可以大大提升搜索效率。 经常使用的中文和英文停用词可以在网站www.ranks.nl上提取中文停用词地址为https://www.ranks.nl/stopwords/chinese-stopwords英文停用词地址为https://www.ranks.nl/stopwords。 如图5.15所示为该网站上的部分中文和英文停用词截图。 1 使用停用词过滤器 可以通过创建自定义分析器的方式使用停用词方法是在分析器中指定停用词过滤器在过滤器中可以指定若干个停用词。下面使用standard分词器和停用词过滤器组成一个自定义分析器进行索引定义DSL如下 PUT /hotel { settings: { analysis: { filter: { //定义分词过滤器 my_stop: { //指定停用词过滤器 type: stop, stopwords: [ //指定停用词集合 我, 的, 这 ] } }, analyzer: { //自定义分析器 standard_stop: { tokenizer: standard, filter:[my_stop] //指定分词过滤器 } } } }, mappings: { properties: { title: { type: text, analyzer: standard_stop //指定自定义分析器 } } } } 使用上述分析器进行文本分析DSL如下 POST /hotel/_analyze { //使用title字段的分析器分析文本 field: title, text: 我的酒店 } 分析结果如下 { tokens : [ { //“我”和“的”已经被过滤 token : 酒, start_offset : 2, end_offset : 3, type : IDEOGRAPHIC, position : 2 //“酒”是分词后的第3个词索引位置为2 }, { token : 店, start_offset : 3, end_offset : 4, type : IDEOGRAPHIC, position : 3 } ] }通过以上结果可以看到“我的酒店”中的“我”和“的”已经被停用词过滤器过滤只剩下“酒”和“店”。但是“酒”的开始位置是2“店”的开始位置是3说明分析结果中“我”和“的”的位置被保留了下来这种特意保留停用词的方式有助于后续的模糊搜索。 2 在内置分析器中使用停用词 其实像standard这种常用的分析器都自带有停用词过滤器只需要对其参数进行相应设置即可。以下示例中使用standard分析器并通过设置其stopwords属性进行停用词的设定 PUT /hotel { settings: { analysis: { analyzer: { //自定义分析器 my_standard: { type: standard, //自定义分析器封装标准分析器 stopwords:[我,的,这] //设置标准分析器的停用词 } } } }, mappings: { properties: { title: { type: text, analyzer: my_standard //设置自定义分析器 } } } } 设置完成后分析目标文本和上面的结果是一致的。 3 在IK分析器中使用停用词 在默认情况下IK分析器的分词器只有英文停用词没有中文停用词。以下示例为测试中文停用词的使用情况 POST _analyze { analyzer: ik_max_word, //使用ik_max_word分析器 text: 最清新的一个酒店 } 返回结果如下 { tokens : [ //切分的词语列表 { //第1个切分的词语 token : 最, start_offset : 0, end_offset : 1, type : CN_CHAR, position : 0 }, { //第2个切分的词语 token : 清新, start_offset : 1, end_offset : 3, type : CN_WORD, position : 1 }, { //第3个切分的词语 token : 的, start_offset : 3, end_offset : 4, type : CN_CHAR, position : 2 }, { //第4个切分的词语 token : 一个, start_offset : 4, end_offset : 6, type : CN_WORD, position : 3 }, { //第5个切分的词语 token : 酒店, start_offset : 6, end_offset : 8, type : CN_WORD, position : 4 } ] } 由上面的结果可知分析结果中“最”“的”和“一个”这3个停用词没有被过滤。 如果用户想要添加中文停用词需要通过自定义停用词文件的形式进行添加。在${ES_HOME}/plugins/ik-analysis/config目录下创建my_stopword.dict文件并在其中添加中文停用词即可如图5.16所示。 添加完停用词后保存文件并退出然后修改${ES_HOME}/plugins/ik-analysis/config/IKAnalyzer.cfg.xml文件设置配置项ext_stopwords的值为停用词词典的文件名称如图5.17所示。 配置完成后重启ES再使用上面的文本进行分析分析结果如下 { tokens : [ //“最”“的”和“一个”这3个停用词已经被过滤 { token : 清新, start_offset : 1, end_offset : 3, type : CN_WORD, position : 0 }, { token : 酒店, start_offset : 6, end_offset : 8, type : CN_WORD, position : 1 } ] } 根据上面的结果可知之前配置的停用词已经生效分析结果中“最”“的”和“一个”这3个停用词已经被过滤。 9 拼音搜索 拼音搜索在中文搜索环境中是经常使用的一种功能用户只需要输入关键词的拼音全拼或者拼音首字母搜索引擎就可以搜索出相关结果。在国内中文输入法基本上都是基于汉语拼音的这种在符合用户输入习惯的条件下缩短用户输入时间的功能是非常受欢迎的如图5.19所示为分别在艺龙App和携程App上输入wfj后的搜索结果。 在ES中可以使用拼音分析器插件进行拼音搜索插件的项目地址为https://github.com/medcl/elasticsearch-analysis-pinyin该插件对较新的ES版本并不支持需要用户自行进行编译安装。 1 拼音分析器插件的安装 如果要安装拼音分析器插件则需要安装Git和Maven这两个工具。首先使用Git命令从互联网中复制该项目命令如下 https://github.com/medcl/elasticsearch-analysis-pinyin/releases/tag/v7.8.0 2 拼音分析器插件的使用 拼音分析器提供的分析器为pinyin另外还提供了与其同名的分词器和分词过滤器。安装完成后可以使用pinyin分析器或分词器进行验证。 下面使用pinyin分析器对待测试文本进行分析DSL如下 POST _analyze { analyzer: pinyin, //使用pinyin分析器分析文本 text: 王府井 } 分析结果如下 { tokens : [ { //“王”的拼音形式 token : wang, start_offset : 0, end_offset : 0, type : word, position : 0 }, { //“王府井”的拼音首字母 token : wfj, start_offset : 0, end_offset : 0, type : word, position : 0 }, { //“府”的拼音形式 token : fu, start_offset : 0, end_offset : 0, type : word, position : 1 }, { //“井”的拼音形式 token : jing, start_offset : 0, end_offset : 0, type : word, position : 2 } ] } 在上面的代码中“王府井”被切分成拼音wang、fu、jing及首字母wfj。 也可以将拼音分析器应用到索引的字段中。以下示例中将自定义的ik_pinyin_analyzer分析器设置为酒店索引中title字段的默认分析器DSL如下 PUT /hotel { settings: { analysis: { analyzer: { //自定义分析器 ik_pinyin_analyzer: { tokenizer: ik_max_word, //设置分词器为ik_max_word filter:[pinyin_filter] //设置分词过滤器为pinyin_filter } }, filter: { //定义分词过滤器 pinyin_filter: { type: pinyin, //封装pinyin分词过滤器 keep_first_letter: true, //设置保留拼音的首字母 keep_full_pinyin: false, //设置保留拼音的全拼 keep_none_chinese: true, //设置不保留中文 } } } }, mappings: { properties: { title: { type: text, analyzer: ik_pinyin_analyzer //设置使用自定义分析器 } } } } 为演示方便下面向酒店索引中写入如下数据 POST /_bulk {index:{_index:hotel,_id:001}} {title: 文雅假日酒店} {index:{_index:hotel,_id:002}} {title: 北京金都嘉怡酒店} {index:{_index:hotel,_id:003}} {title: 天津金都欣欣酒店} {index:{_index:hotel,_id:004}} {title: 金都酒店} {index:{_index:hotel,_id:005}} {title: 文雅精选酒店} 搜索关键词wy目的是想搜索“文雅”相关的酒店DSL如下 GET /hotel/_search { query: { //搜索匹配wy的文档 match: { title: wy } } } 搜索结果如下 { … hits : { … hits : [ { _index : hotel, _type : _doc, _id : 005, _score : 0.919734, _source : { title : 文雅精选酒店 //字段中的“文雅”和查询词wy匹配 } }, { _index : hotel, _type : _doc, _id : 001, _score : 0.816522, _source : { title : 文雅假日酒店 //字段中的“文雅”和查询词wy匹配 } } ] } } 由此可见使用带有拼音词语过滤器的分析器后就可以匹配查询词中的拼音首字母了。正如上面的一些示例使用拼音分析器时有很多的选项可以设置。例如是否显示单字拼音的首字母、是否显示组合词的首字母、是否显示查询词的全部拼音等具体的设置内容可以参考官网说明本节不再赘述。 10 高亮显示搜索 “高亮显示”的英文为highlight是指在搜索结果中通过对文档标题的部分匹配字符串进行颜色如红色或者字体如加粗等处理在视觉呈现上使匹配的字符串与未匹配的字符串有明显的区分效果。我们在电商网站中经常会看到有这样的搜索效果因为这可以让产品的属性和卖点受到更多的关注从而提高搜索转化率。如图5.23所示为在京东商城网站上搜索“家用高清摄像头”时的搜索结果列表。 1 初步使用高亮显示搜索 在ES中通过设置DSL的highlight参数可以对搜索的字段高亮显示。例如下面搜索title字段并且对结果进行高亮显示 GET /hotel/_search { query: { match: { title: 金都酒店 } }, highlight:{ //设置高亮搜索的字段 fields: { title: {} } } } 以上DSL中增加了highlight的子DSL在其中设定对title字段的匹配结果进行高亮显示的标记标签此处使用默认的HTML标签em/em因此将title对应的值置为空对象。上述DSL的搜索结果如下{ … hits : { … hits : [ { _index : hotel, _type : _doc, _id : 004, _score : 0.73944557, _source : { title : 金都酒店 }, highlight : { title : [ //使用默认的HTML标签em/em标记匹配的词语 em金都/emem酒店/em ] } } … ] } }当然如果希望使用其他HTML标签对匹配内容进行标记可以在DSL中进行更改。以下DSL将匹配内容标记标签改为了high/highGET /hotel/_search { query: { match: { title: 金都酒店 } }, highlight:{ fields: { title: { //设置默认使用标签high/high 标记匹配词语 pre_tags: high, post_tags: /high } } } }执行上面的DSL后搜索结果如下 { … hits : { … hits : [ { _index : hotel, _type : _doc, _id : 004, _score : 0.73944557, _source : { title : 金都酒店 }, highlight : { title : [ //使用标签high/high 标记匹配词语 high金都/highhigh酒店/high ] } } … ] } }2 选择高亮显示搜索策略 ES支持的高亮显示搜索策略有plain、unified和fvh用户可以根据搜索场景进行选择。 plain是精准度比较高的策略因此它必须将文档全部加载到内存中并重新执行查询分析。由此可见plain策略在处理大量文档或者大文本的索引进行多字段高亮显示搜索时耗费的资源比较严重。因此plain策略适合在单个字段上进行简单的高亮显示搜索。 unified策略是由Lucene Unified Highlighter来实现的其使用BM25Best Match25算法进行匹配。在默认情况下ES高亮显示使用的是该策略。 为了弥补上述两种策略在大文本索引高亮显示搜索时的速度低问题Lucene还提供了基于向量的高亮显示搜索策略fvhfast vector highlighter。fvh策略更适合在文档中包含大字段的情况如超过1MB下使用如果计算机的I/O性能更好如使用SSD则fvh策略在速度上的优势更加明显。 选择高亮显示搜索策略时只需要在highlight子句中指定type字段的值即可。以下示例中设置高亮显示搜索时使用plain策略DSL如下 GET /hotel/_sear { query: { match: { title: 金都酒店 } }, highlight:{ fields: { title: { type: plain //设置使用plain匹配策略 } } } }如果要使用fvh策略进行高亮显示搜索需要设定字段的term_vector属性值为with_positions_offsets示例如下 PUT /hotel { mappings: { properties: { title: { type: text, analyzer: ik_max_word, //设定字段的term_vector属性值为with_positions_offsets term_vector: with_positions_offsets } … } } }然后在查询的DSL中指定高亮显示搜索的type为fvh具体DSL如下 GET /hotel/_search { query: { match: { title: 金都酒店 } }, highlight: { fields: { title: { type: fvh //使用fvh策略进行高亮显示搜索 } } } }3 在Java客户端中进行高亮显示搜索 使用Java客户端进行高亮显示搜索时需要创建一个HighlightBuilder类的实例然后通过preTags()和postTags()方法分别设置高亮显示的前缀和后缀并通过方法field()设置高亮显示的字段。遍历结果时通过SearchHit.getHighlightFields()方法可以获取所有高亮显示的字段及其对应的高亮显示结果的映射结构为MapString,HighlightField形式。当获取到某字段对应的高亮显示结果后可以通过HighlightField.getFragments()方法获取结果的Text数组形式后续进行遍历取出即可。以下示例是在Java客户端上进行高亮显示搜索 public void hightLightSearch() { SearchRequest searchRequest new SearchRequest(); //新建搜索请求 SearchSourceBuilder searchSourceBuilder new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchQuery(title, 金都). operator(Operator.AND)); //新建match查询并设置operator的值为and searchRequest.source(searchSourceBuilder); //设置查询 //新建高亮显示搜索 HighlightBuilder highlightBuilder new HighlightBuilder(); highlightBuilder.preTags(high); //设置高亮显示标签前缀 highlightBuilder.postTags(/high); //设置高亮显示标签后缀 highlightBuilder.field(title); //设置高亮显示字段 searchSourceBuilder.highlighter(highlightBuilder); //设置高亮显示搜索 try { SearchResponse searchResponse client.search(searchRequest, RequestOptions.DEFAULT); //执行搜索 SearchHits searchHits searchResponse.getHits(); //获取搜索结果集 for (SearchHit searchHit : searchHits) { //遍历搜索结果集 Text[] texts searchHit.getHighlightFields().get(title). getFragments(); //得到高亮显示搜索结果 for (Text text : texts) { //遍历高亮显示搜索 System.out.println(text); //打印每一个高亮显示结果 } System.out.println(--------------------------------------); } } catch (Exception e) { e.printStackTrace(); } }11 拼写纠错 用户在使用搜索引擎的过程中输入的关键词可能会出现拼写错误的情况。针对错误的关键词绝大多数的搜索引擎都能自动识别并进行纠正然后将纠正后的关键词放到索引中匹配数据。如果拼写错误特别多导致无法纠正则会直接告知用户当前搜索没有匹配的结果。如图5.24所示的左右两幅图分别是在京东商城和天猫商城中搜索“薯偏”后的返回结果。 通过图5.24可以看到两个应用都识别出了“薯偏”是一种拼写错误并给出了正确的拼写词“薯片”。在搜索结果的展示上天猫商城保守一些主要展示了“薯”对应的匹配结果京东商城则直接展示了“薯片”对应的匹配结果。 1 使用Elasticsearch进行拼写纠错 也可以使用ES进行拼写纠错首先需要搜集一段时间内用户搜索日志中有搜索结果的查询词然后单独建立一个纠正词索引。当用户进行搜索时如果在商品索引中没有匹配到结果则在纠正词索引中进行匹配如果有匹配结果则给出匹配词并给出该匹配词对应的商品结果如果没有匹配结果则告知用户没有搜索到商品流程如图5.25所示。 在ES中进行纠错匹配时使用fuzzy-match搜索该搜索使用编辑距离和倒排索引相结合的形式完成纠错倒排索引前面已经介绍过了那么什么是编辑距离呢词语A经过多次编辑后和词语B相等编辑的次数就叫作编辑距离。可以这样定义一次编辑替换一个字符或删除一个字符或插入一个字符或交换两个字符的位置。 假设有词语A为“景王”词语B为“王府井”词语A需要进行如下编辑才能等于词语B 1将“景王”两个字符交换位置变为“王景”。 2在“王景”中间添加“府”变成“王府景”。 3将“王府景”中的“景”替换为“井”。 经过上述编辑词语A和词语B相等则词语A到词语B的编辑距离为3。上面的例子比较极端词语A和词语B的编辑距离比较远在搜索场景中绝大多数查询词的编辑距离一般不超过2。 为演示方便首先创建一个纠错索引名称为error_correct索引创建语句如下 PUT /error_correct { mappings: { properties: { hot_word: { //设置hot_word的类型为text并指定分析器为ik_max_word type: text, analyzer: ik_max_word } } } }接着向该索引中写入以下数据 POST /_bulk {index:{_index:error_correct,_id:001}} {hot_word: 王府井} {index:{_index:error_correct,_id:002}} {hot_word: 王府中环} {index:{_index:error_correct,_id:003}} {hot_word: 双井} {index:{_index:error_correct,_id:004}} {hot_word: 成府路} {index:{_index:error_correct,_id:005}} {hot_word: 大王庄}ES的match查询支持模糊匹配这里的模糊匹配指的是ES将查询文本进行分词进而得到分词列表然后将列表中的词语分别和索引中的词语进行匹配这时按照编辑距离进行模糊匹配在符合编辑距离阈值的情况下才算是匹配。 以下是搜索“王府景”时指定编辑距离为1的搜索纠错的DSL GET /error_correct/_search { query: { match: { hot_word:{ query: 王府景, operator: and, fuzziness: 1 //指定编辑距离为1 } } } }上述DSL的执行结果如下 { … hits : { … hits : [ //命中的文档列表 { _index : error_correct, _type : _doc, _id : 001, _score : 1.2354476, _source : { hot_word : 王府井 //“王府井”和王府景的编辑距离为1 } }, { _index : error_correct, _type : _doc, _id : 004, _score : 0.0, _source : { hot_word : 成府路 //“成府路”和王府景的编辑距离为1 } } ] } }通过以上结果可以看出纠错结果基本符合预期但是“成府路”也出现在搜索结果中这是为什么呢 按照hot_word字段默认的分析器对查询词“王府景”和查询词“成府路”进行分析查询词“王府景”被切分成了“王府”和“景”查询词“成府路”被切分成了“成”“府”和“路”。因为“王府”和“府”的编辑距离为1符合模糊匹配的编辑距离的阈值因此“成府路”被匹配上。 2 更精准的拼写纠错 解决上面的问题有两种思路第一种思路是将“成府路”作为新词加入用户的自定义词典中此时ES会将“成府路”切分成一个整体“成府路”它和“王府”的编辑距离是2不符合阈值因此不匹配第二种思路是加入更严格的匹配条件。第一种思路受经验影响比较大需要人工参与。本节主要介绍使用第二种思路来解决问题。 针对5.9.1节的“王府景”匹配问题可以采用短语进行匹配查询但是其必须满足以下3个条件 ·文档中必须包含“王府景”3个字 ·文档中必须满足“府”的位置比“王”的位置大1 ·文档中必须满足“景”的位置比“王”的位置大2。 上述条件缺一不可。但是现有的文档中没有一个文档同时符合这个条件甚至连第一个条件都不满足与其最接近的文档是“王府井”但是该文档中不包含“景”。我们可以换个角度考虑问题“王府景”和“王府井”其实属于音同字不同的情况如果将查询词和索引文档字段都切分成拼音的形式“王府景”切分成拼音wang、fu、jing候选项“王府井”切分的结果与查询词是一致的且其拼音形式的位置排列与查询词也相同这样就符合短语匹配的条件了。因此我们将字段hot_word变换一下建立一个子字段pinyin该字段使用拼音分析器进行切分DSL如下 PUT /error_correct { settings: { analysis: { analyzer: { //自定义分析器 pinyin_analyzer: { tokenizer: my_pinyin } }, tokenizer: { my_pinyin: { //定义分词过滤器 type: pinyin, keep_first_letter: false, keep_separate_first_letter: false, keep_full_pinyin: true } } } }, mappings: { properties: { hot_word: { type: text, analyzer: ik_max_word, fields: { //建立子字段 pinyin: { type: text, analyzer: pinyin_analyzer //使用自定义分析器 } } } } } }在上面的拼音分析器设置中设置拼音单字的首字母和拼音组合的首字母全部不使用只使用拼音单字的全拼形式。接着使用fuzzy-match和match_phrase进行联合查询DSL如下 GET /error_correct/_search { query: { bool: { must: [ { match: { hot_word: { query: 王府景, operator: and, fuzziness: 1 //设置编辑距离为1 } } }, { match_phrase: { //使用match_phrase匹配子字段 hot_word.pinyin: { query: 王府景, slop: 0 //设置分词匹配的间隔为0 } } } ] } } }使用上述DSL进行查询后ES返回的结果如下 { … hits : { … hits : [ { //“成府路”不再命中 _index : error_correct, _type : _doc, _id : 001, _score : 3.1889093, _source : { hot_word : 王府井 } } ] } }从上述结果中可以看到在返回的匹配结果中干扰项“成府路”已经不再显示只有“王府井”被命中显示。
http://www.dnsts.com.cn/news/33529.html

相关文章:

  • 片网站无法显示ui设计灵感网站
  • 网站模板吧智能网站建设公司排名
  • 网站后端开发流程住房和城乡建设部是国家认定网站吗
  • 网站开发投入资金免费微网站系统源码
  • 网站空间 哪个公司好江西h5响应式网站建设设计
  • 商家在携程旅游网站怎样做宣传深圳网络设计
  • 百度做个网站多少钱网站线上推广方式
  • 一个外国设计网站网址全网营销销售
  • 校园二手市场网站建设方案网站效果展示
  • 说明怎样做才能通过互联网访问你制作的网站大学网站建设考核办法
  • 教人做辐射4mod的网站徐州手工活外发加工网
  • 网站建设征求意见通知网站制作优势
  • 网站不收录怎么办阳泉网站开发
  • 网站开发环境构建Wordpress已有数据库表
  • 网站制作的基本概念做网站对企业有什么好处
  • 个人可以建网站新建网站的价格
  • 企业网站免费建站wordpress高效写文章
  • 网站建设验收方案wordpress修改菜单
  • 大学学科建设网站大米网络营销推广方案
  • 合肥建设银行网站首页平乡县网站建设平台位置
  • 织梦收费嘉兴网站seo外包
  • 网站建立者网站代运营公司有哪些
  • 台州网站策划台州网站策划网页制作代码步骤
  • 海阳手机网站开发wordpress部署wamp
  • 汽配网站源码佛山网站优化公司
  • 平台网站建设公司广东深圳网站
  • 赣州市建设工程造价管理网站怎么让网站页面自适应
  • 服装网站建设目标长沙网站开发的网站
  • 合肥公司网站建设价格低wordpress的slider
  • 做的比较好的p2p网站wordpress小米论坛主题