`

Elasticsearch 全文搜索 (四) - 控制分析及相关度

阅读更多

原文链接:http://blog.csdn.net/dm_vincent/article/details/41773959

 

控制分析(Controlling Analysis)

查询只能摘到真实存在于倒排索引(Inverted Index)中的词条(Term),因此确保相同的分析过程会被适用于文档的索引阶段和搜索阶段的查询字符串是很重要的,这样才能够让查询中的词条能够和倒排索引中的词条匹配。

尽管我们说的是文档(Document),解析器(Analyzer)是因字段而异的(Determined per Field)。每个字段都能够拥有一个不同的解析器,通过为该字段配置一个特定的解析器或者通过依赖类型(Type),索引(Index)或者节点(Node)的默认解析器。在索引时,一个字段的值会被该字段的解析器解析。

比如,让我们为my_index添加一个新字段:

PUT /my_index/_mapping/my_type
{
    "my_type": {
        "properties": {
            "english_title": {
                "type":     "string",
                "analyzer": "english"
            }
        }
    }
}

现在我们就能够通过analyze API来比较english_title字段和title字段在索引时的解析方式,以Foxes这一单词为例:

GET /my_index/_analyze?field=my_type.title   
Foxes

GET /my_index/_analyze?field=my_type.english_title 
Foxes

对于title字段,它使用的是默认的standard解析器,它会返回词条foxes。 对于english_title字段,它使用的是english解析器,它会返回词条fox

这说明当我们为词条fox执行一个低级的term查询时,english_title字段能匹配而title字段不能。

类似match查询的高阶查询能够理解字段映射(Field Mappings),同时能够为查询的每个字段适用正确的解析器。我们可以通过validate-query API来验证这一点:

GET /my_index/my_type/_validate/query?explain
{
    "query": {
        "bool": {
            "should": [
                { "match": { "title":         "Foxes"}},
                { "match": { "english_title": "Foxes"}}
            ]
        }
    }
}

它会返回这个explanation

(title:foxes english_title:fox)

match查询会为每个字段适用正确的解析器,来确保该字段的查询词条的形式是正确的。

默认解析器(Default Analyzers)

尽管我们能够为字段指定一个解析器,但是当没有为字段指定解析器时,如何决定字段会使用哪个解析器呢?

解析器可以在几个级别被指定。ES会依次检查每个级别直到它找到了一个可用的解析器。在索引期间,检查的顺序是这样的:

  • 在映射文件中指定字段的analyzer,或者
  • 在文档的_analyzer字段上指定分析器,或者
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置默认分析器default
  • standard分析器

在搜索期间,顺序稍微有所不同:

  • 在查询参数中指定analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置默认分析器default
  • standard分析器

NOTE

以上两个斜体表示的项目突出显示了索引期间和搜索期间顺序的不同之处。_analyzer字段允许你能够为每份文档指定一个默认的解析器(比如,englishfrenchspanish),而查询中的analyzer参数则让你能够指定查询字符串使用的解析器。然而,这并不是在一个索引中处理多语言的最佳方案,因为在处理自然语言中提到的一些陷阱。

偶尔,在索引期间和查询期间使用不同的解析器是有意义的。比如,在索引期间我们也许希望能够索引同义词(Synonyms)(比如,对每个出现的quick,同时也索引fastrapidspeedy)。但是在查询期间,我们必须要搜索以上所有的同义词。相反我们只需要查询用户输入的单一词汇,不管是quickfastrapid或者speedy

为了实现这个区别,ES也支持index_analyzersearch_analyzer参数,以及名为default_indexdefault_search的解析器。

将这些额外的参数也考虑进来的话,索引期间查找解析器的完整顺序是这样的:

  • 在映射文件中指定字段的index_analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在文档的_analyzer字段上指定分析器,或者
  • 在映射文件中指定类型的创建索引的默认分析器index_analyzer
  • 在映射文件中指定类型的默认分析器analyzer
  • 在索引映射文件中设置创建索引的默认分析器default_index
  • 在索引映射文件中设置默认分析器default
  • 在节点级别设置创建索引的默认分析器default_index
  • 在节点级别设置默认分析器default
  • standard分析器

而查询期间的完整顺序则是:

  • 在查询参数中指定analyzer,或者
  • 在映射文件中指定字段的search_analyzer,或者
  • 在映射文件中指定字段的analyzer,或者
  • 在映射文件中指定类型的查询索引的默认分析器analyzer
  • 在索引映射文件中设置查询索引的默认分析器default_search
  • 在索引映射文件中设置默认分析器default_search
  • 在节点级别设置查询索引的默认分析器default_search
  • 在节点级别设置默认分析器default
  • standard 分析器

配置解析器

能够指定解析器的地方太多也许会吓到你。但是实际上,它是非常简单的。

使用索引设置,而不是配置文件

第一件需要记住的是,即使你是因为一个单一的目的或者需要为一个例如日志的应用而使用ES的,很大可能你在将来会发现更多的用例,因此你会在相同的集群上运行多个独立的应用。每个索引都需要是独立的并且被独立地配置。

所以这就排除了在节点上配置解析器的必要。另外,在节点上配置解析器会改变每个节点的配置文件并且需要重启每个节点,这是维护上的噩梦。让ES持续运行并且只通过API来管理设置是更好的主意。

保持简单(Keep it simple)

多数时候,你都能提前知道你的文档会包含哪些字段。最简单的办法是在创建索引或者添加类型映射时为每个全文字段设置解析器。尽管该方法稍微有些繁琐,它能够让你清晰地看到每个字段上使用的解析器。

典型地,大多数字符串字段都会是精确值类型的not_analyzed字段,比如标签或者枚举,加上一些会使用standard或者english以及其他语言解析器的全文字段。然后你会有一两个字段需要自定义解析:比方title字段的索引方式需要支持"输入即时搜索(Find-as-you-type)"。

你可以在索引中设置default解析器,用来将它作为大多数全文字段的解析器,然后对某一两个字段配置需要的解析器。如果在你的建模中,你需要为每个类型使用一个不同的默认解析器,那么就在类型级别上使用analyzer设置。

NOTE

对于日志这类基于时间的数据,一个常用的工作流是每天即时地创建一个新的索引并将相应数据索引到其中。尽管这个工作流会让你无法预先创建索引,你仍然可以使用索引模板(Index Templates)来为一个新的索引指定其设置和映射。

 

 

 

相关度出问题了(Relevance is Broken)

 

在继续讨论更加复杂的多字段查询前,让我们先快速地解释一下为何将测试索引创建成只有一个主分片的索引

经常有新的用户反映称相关度出问题了,并且提供了一个简短的重现:用户索引了一些文档,运行了一个简单的查询,然后发现相关度低的结果明显地出现在了相关度高的结果的前面。

为了弄明白它发生的原因,让我们假设我们创建了一个拥有两个主分片的索引,并且索引了10份文档,其中的6份含有单词foo。在分片1上可能保存了包含单词foo的3份文档,在分片2上保存了另外3份。换言之,文档被均匀的分布在分片上。

什么是相关度一节中,我们描述了在ES中默认使用的相似度算法 - 即词条频度/倒排文档频度(Term Frequency/Inverse Document Frequency,TF/IDF)。词条频度计算词条在当前文档的对应字段中出现的次数。词条出现的次数越多,那么该文档的相关度就越高。倒排文档频度将一个词条在索引的所有文档中出现程度以百分比的方式考虑在内。词条出现的越频繁,那么它的权重就越小。

但是,因为性能上的原因,ES不会计算索引中所有文档的IDF。相反,每个分片会为其中的文档计算一个本地的IDF。

因为我们的文档被均匀地分布了,两个分片上计算得到的IDF应该是相同的。现在想象一下如果含有foo的5份文档被保存在了分片1上,而只有1份含有foo的文档被保存在了分片2上。在这种情况下,词条foo在分片1上就是一个非常常见的词条(重要性很低),但是在分片2上,它是非常少见的词条(重要性很高)。因此,这些IDF的差异就会导致错误的结果。

实际情况下,这并不是一个问题。当你向索引中添加的文档越多,本地IDF和全局IDF之间的差异就会逐渐减小。考虑到真实的世界中的数据量,本地IDF很快就会变的正常。问题不是相关度,而是数据量太小了。

对于测试,有两种方法可以规避该问题。第一种方法是创建只有一个主分片的索引,正如我们在介绍match查询时做的那样。如果你只有一个分片,那么本地IDF就是全局IDF。

第二种方法是在搜索请求中添加?search_type=dfs_query_then_fetchdfs表示分布频度搜索(Distributed Frequency Search),它会告诉ES首先从每个分片中获取本地IDF,然后计算整个索引上的全局IDF。

TIP

不要在生产环境中使用dfs_query_then_fetch。它真的是不必要的。拥有足够的数据就能够确保你的词条频度会被均匀地分布。没有必要再为每个查询添加这个额外的DFS步骤。

 

分享到:
评论

相关推荐

    elasticsearch-analysis-dynamic-synonym-7.12.1.zip

    Elasticsearch是一款流行的开源搜索引擎,用于处理、存储、搜索和分析大量数据。同义词插件是其功能扩展,它允许用户在搜索时将多个词视为等价,提高搜索的准确性和用户体验。 描述中的"作者自己编译"意味着这个...

    基于ElasticSearch的搜索系统的设计与实现

    用户只需输入关键词,系统即可进行智能分析,匹配到相关度高的结果。这种混合搜索方式既考虑了关键词的广泛匹配,也兼顾了精确搜索的需求。 4. 权限控制与数据安全 为了保护敏感数据,系统实现了接口级别的权限...

    elasticsearch-8.10.4-windows-x86_64.zip

    Elasticsearch 8.10.4 是一个高度可扩展的全文搜索引擎,广泛应用于数据分析、日志聚合、实时搜索和大数据处理。这个压缩包“elasticsearch-8.10.4-windows-x86_64.zip”是针对Windows 64位系统的版本,包含了运行...

    elasticsearch-6.3.0.tar.zip

    Elasticsearch 6.3.0 是一个高度可扩展、开源的全文搜索引擎,以其强大的分布式特性和实时分析能力而闻名。这个版本包含了多个关键性的改进和优化,旨在提供更高效、稳定的服务。让我们深入探讨一下这个版本的一些...

    elasticsearch-5.0.1-src-core-main.zip eclipse工程的

    Elasticsearch 5.0.1 是一个高度可扩展的开源全文搜索引擎,它以其强大的分布式特性、实时分析能力以及对海量数据的高效处理而闻名。这个压缩包"elasticsearch-5.0.1-src-core-main.zip"包含了Elasticsearch的核心源...

    Elasticsearch 服务器的简要介绍.docx

    ### Elasticsearch 服务器的相关知识点 #### 一、Elasticsearch 概述 - **定义与功能**:Elasticsearch 是一款基于 Lucene 开发的分布式搜索和分析引擎,它位于 Elastic Stack 的核心位置。Elasticsearch 提供了...

    基于ElasticSearch的搜房网实战1

    **ElasticSearch** 是一个分布式、RESTful风格的搜索和数据分析引擎,用于解决全文搜索、结构化搜索和分析的需求。在这里,它作为核心的搜索组件,负责处理和索引房地产信息,提供快速的搜索响应。 **MySQL** 是一...

    elasticsearch-6.8.2.tar.gz

    Elasticsearch 6.8.2 是一个高度可扩展的开源全文搜索引擎,它不仅是一个搜索引擎,还具有数据分析和存储的功能,使得数据处理变得更加高效和便捷。这个版本在Elasticsearch的发展历程中扮演着重要的角色,提供了...

    elasticsearch-6.4.3

    3. **全文搜索**:Elasticsearch基于Apache Lucene,支持复杂的全文检索,包括模糊搜索、短语搜索、同义词搜索等,能快速返回相关度高的结果。 4. **实时分析**:Elasticsearch能够在数据被索引后立即进行搜索,...

    Elasticsearch顶尖高手系列课程-核心知识篇+高手进阶篇(免费无加密)

    由于其高度可扩展性、高可用性和强大的搜索能力,Elasticsearch在大数据领域有着广泛的应用,例如日志分析、全文搜索、实时监控等场景。 ### 核心知识篇 #### 1. 基础概念 - **文档(Document)**:Elasticsearch中...

    dyt-es-jd.zip

    Elasticsearch 是一款高性能、分布式、全文搜索引擎,常用于大数据量的实时分析和检索。SpringBoot 则是简化 Spring 应用开发的框架,以其简洁、快速的配置方式深受开发者喜爱。下面将详细阐述这两者如何结合以及在...

    ElasticSearch安装手册1.01

    Elasticsearch 是一个高度可扩展的开源全文搜索引擎,它提供了实时、分布式的搜索和分析功能。Spring Cloud 是一套微服务解决方案,它可以帮助开发者快速构建分布式系统中的配置管理、服务发现、断路器、智能路由、...

    Mastering Elasticsearch(中文版).pdf

    - **filters和scope在ElasticSearch Faceting模块的应用**:Faceting(多维度分析)是Elasticsearch中一项重要的特性,它可以基于特定的字段对搜索结果进行分组。Filters和scope在faceting中的应用可以帮助开发者更...

    ElasticSearch入门

    Elasticsearch(简称 ES)是一种基于 Lucene 的开源分布式搜索引擎,它提供了全文检索、分析、实时等高级功能。作为NoSQL数据库的一种,Elasticsearch以其高效、灵活和可扩展性在大数据时代备受青睐,广泛应用于日志...

    ElasticSearch7.6.2 五种工具安装包之一

    Elasticsearch 7.6.2 是一个高度可扩展、高性能的开源全文搜索引擎,广泛用于实时数据分析、日志聚合和搜索应用。它基于 Lucene 库构建,提供了分布式、RESTful 风格的接口,使得操作简单而高效。Elasticsearch 的五...

    elasticsearch_18实用知识库分享

    Elasticsearch 提供了 Keyword 字段的查询相关度评分控制,可以对搜索结果进行优化。 24. Elasticsearch 之单请求多查询 Elasticsearch 支持单请求多查询,可以同时执行多个查询。 25. Elasticsearch 之 Exists ...

Global site tag (gtag.js) - Google Analytics