Solr 教程(一)

原文:Apache Solr

协议:CC BY-NC-SA 4.0

一、Apache Solr:简介

Electronic supplementary material The online version of this chapter (doi:10.​1007/​978-1-4842-1070-3_​1) contains supplementary material, which is available to authorized users.

搜索无处不在,已经成为我们数字生活的一部分!你打开浏览器,很有可能你的主页是你首选的搜索引擎。你智能手机的搜索引擎只是轻轻一扫。打开一个电子商务网站,搜索框就出现在页面的中央或顶部。基本上,每个需要公开数据的门户都需要一个搜索引擎。这证明了一个搜索引擎对于一个企业或者它正在构建的产品是多么的重要。

当今的企业有大量的信息要公开,而且这一数量还将继续增长。浏览所有数据以找到相关信息几乎是不可能的,也是乏味的。这个问题的唯一解决方案是搜索引擎。

如果你有大量的数据,却很难在需要的时候以你需要的方式找到你想要的信息,那么这些数据几乎毫无价值,是时候呼吁开发或升级你的搜索引擎了。因为您正在阅读这一章,我假设您正在构建或计划构建一个搜索引擎,并且您理解为什么您的企业需要一个搜索引擎。所以事不宜迟,我们继续吧。

本书的目标是帮助你使用开源的 Apache Solr 开发一个搜索引擎。首先,你需要明白每个搜索引擎都是不同的,都有自己独特的挑战,需要以不同的方式解决。我们将探讨常见问题及其解决方案,并提供解决本书流程中特定问题的方法。

本章首先介绍了 Apache Solr,并提供了其特性的高级视图。它涉及到 Solr 的几个方面,以便您在开始概念证明或开发之前有一个全面的了解。

本章涵盖以下主题:

  • Solr 的重要特性
  • Solr 的重要组成部分
  • Solr 的使用超出了它的搜索引擎功能
  • Solr 与其他解决方案的比较
  • Solr 生态系统中使用的技术

概观

Solr(发音为 solar)是一个企业级的、速度惊人的、高度可伸缩的搜索平台,使用 Apache Lucene 构建。经过多年的发展,有了这样一个充满活力的社区,Solr 已经成熟到了这样一个水平,它提供了开箱即用的所有急需的特性以及定制它的条款。它是云就绪型的,具有强大的健壮性、容错性和可靠性。

Solr 是用 Java 编写的,作为独立的服务器运行。入门极其容易。您所需要做的就是运行一个带有启动/停止命令的脚本。由于 Solr 完全基于配置,所以它只要求您互相注册组件。即使没有任何 Java 知识,你也可以构建一个像样的搜索引擎,只要你不需要定制。Solr 还提供了一个易于监控的图形管理员界面,可以通过指向运行搜索引擎的端口从浏览器访问该界面。

Note

Apache Lucene 是一个流行的完全用 Java 编写的开源搜索库。它广泛用于索引大量文档和支持全文搜索。

内部 Solr

要选择一个框架,您需要从内部、特性、功能、可用性、性能和可伸缩性等方面进行评估。这一节将回答您的一些问题,包括 Solr 内部有什么,如何配置它,以及如何使用它。本节介绍的特性可能不是 Solr 如此受欢迎的原因,但是作为您对 Solr 基本理解的一部分,了解这些特性是很重要的。下一节将介绍使 Solr 流行的特性,这样您将对 Solr 的特性有全面的了解。以下几点提供了 Solr 特性的快速概述:

  • 倒排索引:Lucene 为您添加到 Solr 中的文档构建倒排索引,并在查询时搜索匹配的文档。你可以把倒排索引想象成类似于本书末尾的索引。
  • 向量空间模型:默认情况下,Lucene 使用向量空间模型(VSM)和布尔模型来确定文档与用户查询的相关性。简而言之,布尔模型认可,VSM 排名。
  • 基于配置:solrconfig.xmlschema.xml是 Solr 的两个主要配置文件。schema.xml文件主要定义模式中的字段以及这些字段的行为(在索引和查询时文本将如何被标记)。其他的几乎都进solrconfig.xml了。您也可以不使用模式,让 Solr 在索引数据时自动创建字段。这些配置可以手动编辑,也可以通过调用相应的 API 来动态修改。从 Solr 5.0 开始,您甚至可以通过 API 调用上传 JAR 文件。
  • 分析链:您的搜索查询和被索引的文档经过一系列分析器和标记器(一个标记器的输出被提供给链中的另一个标记器)。最后一个标记器的输出是被索引和匹配的术语。
  • Java: Solr 和 Lucene 都是用 Java 写的。Solr 5.0 需要 Java 7+才能运行。要定制 Solr 的任何特性,您需要扩展适当的 Java 类。
  • SolrJ: Solr 捆绑了一个 Java 客户端库,可以用来索引文档和查询结果。库也可用于其他语言,如 Perl 和 Python。

是什么让 Apache Solr 如此受欢迎

Apache Solr 是使用最广泛的搜索解决方案之一,每月有数百万次下载,数万个应用程序在生产中,数百次提交。以下是使它如此受欢迎的一些因素:

  • Lucene: Solr 在其核心使用 Lucene 搜索库,并对其进行包装以添加特性,并将其公开为可以通过 HTTP 访问的 RESTful 服务。Solr 和 Lucene 的开发在 2010 年 3 月合并,两者的代码库都驻留在 Apache Subversion (SVN)的同一个主干中;因此,你一定会在最新的 Solr 版本中获得所有最新的 Lucene 特性。
  • 高可伸缩性和容错性:您可以添加或删除 Solr 的计算能力,只需根据需要添加或删除实例的副本。SolrCloud 甚至将您的应用程序抽象为不知道数据是如何分布的,并使您免于陷入进一步的细微差别,如负载平衡和分片。索引到 Solr 的数据可以在多个实例之间复制;因此,即使一个实例关闭,数据仍然可以访问。
  • 企业就绪:Solr 在搜索需求和处理大量负载方面得到了许多领先组织的充分证明和信任。它可以部署在独立的传统分布式架构中,也可以根据组织的需求部署在云模式中,无论组织规模大小。
  • 全文搜索:由于 Solr 构建在 Lucene 之上,它提供了所有需要的匹配功能,包括令牌、短语、模糊、通配符、拼写检查和自动完成。
  • 基于 HTTP 的 RESTful XML/JSON:Solr 作为 RESTful web 服务公开,可以通过 HTTP 访问。数据可以以 XML、JSON、CSV 和二进制格式交换。
  • 灵活且可扩展:Solr 具有开箱即用的多种功能。尽管如此,如果它不符合你的需求,也不用担心;Solr 是灵活和可扩展的。您可以通过扩展 Java 类并在适当的文件中添加所创建类的配置来修改和定制组件的行为。
  • 容易配置:如果你知道你的模式,你可以预定义它;否则,您可以选择无模式,让 Solr 定义字段。此外,您可以通过 API 调用来修改您的配置。
  • 全面的管理界面:这是另一个使 Solr 相当容易使用的特性。Solr 提供了一个功能强大、用户友好的界面,可以在浏览器中通过 HTTP 访问。它提供了几乎所有需要的洞察力,使您能够查看配置文件;检查文本分析;添加/删除碎片;实时管理日志;搜索、添加、删除和更新文档。触发数据导入流程;查看线程和系统属性;还有很多。
  • 充满活力的社区:Solr 是 Apache Software Foundation (ASF)的一个项目,拥有一个由 100 多名开发人员和提交人员组成的充满活力且不断发展的社区。每个版本都添加了许多功能,并进行了改进。该项目已经成熟到这样一个水平,它有一个令人难以置信的多才多艺的功能集。

主要构件

Solr 和 Lucene 的类是有组织和分层的。每个都被设计成执行特定的工作。您所需要做的就是在配置文件中对它们进行适当的配置,这样它们就可以根据需要相互注册。Solr 还允许您编写自定义组件并将其插入。概括地说,以下是 Solr 的一些主要构建块和重要组件:

  • 请求处理程序:所有对 Solr 的请求都由实现SolrRequestHandler的一个类来处理。您将处理程序配置为映射到一个特定的 URI 端点,向该端点发出的请求开始由它提供服务。
  • 搜索组件:搜索组件定义了实现搜索处理程序提供的特性的逻辑。这些组件应该在一个SearchHandler中注册,这是一个服务于用户查询的请求处理器。例如,查询、拼写检查、分面和点击突出显示等功能作为组件实现,并注册到 SearchHandler。多个组件可以注册到一个搜索处理程序。
  • 查询解析器:它将用户查询翻译成 Lucene 能够理解的指令。它们通常注册在SearchComponent中,这个组件定义了执行搜索的逻辑。
  • 相似性:这个类决定 Lucene 如何对术语进行加权和对文档进行评分。如果你想改变评分行为,这就是要扩展的类。
  • 响应编写器:这决定了应该如何格式化对用户查询的响应。对于每种响应类型,比如 XML、JSON 或 Velocity,都有一个单独的响应编写器。
  • 分析器/标记器:Lucene 理解的最小数据单元是一个标记。AnalyzertokenizerTokenFilter的实现决定如何将文本分解成记号。
  • 更新请求处理器:在索引文档时,您可以调用一组UpdateRequestProcessor作为链的一部分,对数据执行定制操作。

历史

2004 年,Solr 作为一个内部项目由 CNET 的 Yonik Seeley 创建。2006 年初,CNET 将这个项目捐赠给了 Apache 软件基金会。经过一段时间的孵化,Solr 被释放。随着时间的推移,分布式搜索、点击突出显示、增强的搜索和索引功能、分面、拼写检查、云功能和无数其他功能已经添加进来,使其用户、贡献者和提交者社区成为当今最有活力的社区之一。以下说明了 Solr 是如何成熟的:

  • Solr 1.x:这是该产品的企业级版本。Solr 1.3 于 2007 年 1 月发布。Solr 1.4 于 2009 年 11 月发布,增强了索引、搜索、复制、富文档索引和更好的数据库集成。
  • Solr 3 . x:2011 年 3 月,Solr 和 Lucene 项目的开发合并,所以没有 Solr 的 2.x 版本。Solr 的下一个版本直接标记为 3.1,以匹配 Lucene 版本。Solr 3.x 专注于空间搜索等新特性,以及处理管道的 UIMA、UI 的 Velocity 等集成。
  • Solr 4.x: Solr 4.0 主要是关于分布式搜索和 SolrCloud,使 Solr 更加可靠、容错和可伸缩。
  • Solr 5.x: Solr 5.0 于 2015 年 2 月发布,重点是易用性和硬化。最近的版本集中在安全性、分析和扩展 API 上。有关详细信息,请参考下一节。

Solr 5.x 的新特性

Solr 4.x 引入了 SolrCloud,这是一种面向分布式搜索和可伸缩性的新方法和设计。5.x 版将 Solr 作为一个独立的服务器,有以下主要变化:

  • 独立服务器:如果你是 Apache Solr 的现有用户,是时候从新的角度来看待它了。它不再以 WAR (web archive)文件的形式分发,您应该将它部署在您最喜欢的 servlet 容器中,而是作为一个独立的服务器,您应该使用它来解决您的业务问题,而不必担心部署细节。这样做是为了更好地利用容器的网络堆栈功能。
  • 易用性:Solr 5.0 更容易上手和使用。启动、停止和将 Solr 公开为服务就像运行一个命令一样简单。它还提供了更好的自我发现,更有组织性,甚至更可配置。通过使用 AngularJS 对管理 UI 进行了重构,以获得更好的用户体验。
  • 分布式 IDF:反向文档频率,Solr 评分中最重要的因素之一,现在可以全局计算。
  • 新的 API:引入了新的 API,并且扩展了现有的 API。JSON 请求 API 允许搜索请求有一个 JSON 主体。
  • 安全性:Solr 5.2.0 引入了一个可插拔的认证模块,并提供了一个基于 Kerberos 的插件。还提供了授权框架。
  • 分析:facets 模块已经扩展到支持分析和聚合。
  • Clusterstate 拆分:将clusterstate拆分为每个集合使得 SolrCloud 更具可伸缩性。集群将只知道它需要知道的东西,而不是所有东西。

超越搜索器

Solr 的发展已经超越了它的搜索引擎能力,可以作为一个数据存储来使用。如果您将 Solr 用于索引和搜索需求,并且还需要一个数据存储,那么将 Solr 作为一个替代的 NoSQL 解决方案是值得考虑的。MongoDB 等 NoSQL 解决方案支持全文搜索,因此它们可以满足您简单的搜索需求。类似地,Solr 可以用作数据存储,尽管这不是它的主要用例。Lucene 中的更新是以删除和添加的方式实现的,可能不适合需要频繁更新的系统。此外,在选择 NoSQL 数据库时,会对许多参数进行评估。不幸的是,这方面的讨论超出了本书的范围。

此外,Solr 可以用作简单需求的分析工具,比如计数、切片和分组。一个数据分析系统必须能够处理大量的数据,Solr 是一种经过验证的快速技术。因此,您可以使用 Solr 对索引数据执行一些分析。Solr 4.9 允许您通过 AnalyticsQuery API 插入自定义的分析算法。Solr 5.0 通过搜索分析组件支持开箱即用的 OLAP 操作。Solr 5.2 支持 HyperLogLog,这是一种计算不同值的概率方法。

Solr 与其他选项

本节将 Solr 与关系数据库和 Elasticsearch 进行比较。我选择将 Solr 与关系数据库进行比较,以便刚接触搜索和 NoSQL 的开发人员能够从数据库的角度理解和理解 Solr。相比之下,Elasticsearch 是另一个流行的开源搜索引擎,它的比较可以帮助你了解 Solr 与它的关系,以及你是否应该评估 Elasticsearch 以供你使用。

关系数据库

传统的 SQL 数据库被设计为查询表以找到匹配的结果,并且不具有对这些结果进行排序的能力。当你开发你的搜索引擎时,你希望你的搜索结果在一定的基础上被排序,并解释为什么一个特定的文档排在一个特定的位置或在另一个文档之上。例如,基于诸如文档中匹配的标记的最大数量、语料库中标记的稀有性、文档是最新的、或其他参数的组合等逻辑,文档可以排在结果集的顶部。以下是 Solr 和传统数据库之间的一些主要区别:

  • 相关性排序:Solr 排序基于布尔模型和向量空间模型的组合。布尔模型批准文档,并使用 VSM 对那些批准的文档进行排名。相比之下,传统数据库只找到应该构成结果集一部分的文档;他们只有审批流程,没有对文档进行排序的规定。
  • 规范化与非规范化:关系数据库中的数据应该是规范化的,并且在表之间建立一种关系。但是 Solr 中的数据是非规范化和扁平化的。Solr 确实支持连接,但是其行为和实现是不同的,并且不如表连接强大。如果数据存储在一个表中,并且要导入到 Solr 中,那么应该由索引器程序或 Solr 的 dataimport contrib 模块对其进行反规范化。
  • 模式与无模式:关系数据库需要在创建表时定义一个模式。如果您想要添加一个新列,则需要修改该表。但是 Solr 是灵活的。如果您知道您的模式,您可以在配置文件中定义它,或者您可以选择无模式。
  • 纵向扩展与横向扩展:Solr 在企业系统中表现出色并取得优势的一个方面是它易于横向扩展。关系数据库很难向外扩展;它们通常会扩大规模,但成本很高。在传统的 Solr 架构中,数据可以被分发和分片。SolrCloud 使向外扩展变得更加容易,并且可以在商用机器集群上运行。
  • 文本分析和导航:Solr 提供了灵活的文本分析和导航特性,这对于开发搜索引擎非常有意义。这些特性在传统数据库中是完全没有的。

这里需要理解的重要一点是,最好将 Solr 用作从主数据存储(如传统数据库)导入数据的辅助数据存储。每当您对索引过程进行更改或升级 Solr 版本(或类似的版本)时,您可能需要从头开始构建索引。拥有主数据存储简化了重新编制索引的过程。

弹性搜索

Elasticsearch 是一个流行且广泛使用的开源搜索引擎。Solr 和 Elasticsearch 都建立在 Lucene 之上,拥有活跃的社区,并且有商业背景。不同之处在于它们在 Lucene 之上构建包装器和实现特性的方式。以下是它们的一些主要区别:

  • Lucene:根据 Lucene 搜索 Solr aces Elasticsearch。因为 Solr 和 Lucene 的开发是合并的,所以 Solr 总是和 Lucene 有相同的版本。有了 Solr,你总能得到最新版本的 Lucene,而 Elasticsearch 可能会落后几个版本。在撰写本章时,Solr 5.3.1 运行 Lucene 5.3.1,而 Elasticsearch 1.6.0 运行 Lucene 4.10.4。
  • 开源:Solr 和 Elasticsearch 都是开源的。然而,Solr 是 Apache 软件基金会的一个项目,因此是真正意义上的开源;甚至你也可以是一个委托人。Elasticsearch 由它的创始公司 Elastic 提供支持,只有他们的员工才能提交。
  • 历史:Solr 于 2006 年开源,当时是唯一流行的开源搜索引擎。Elasticsearch 于 2010 年发布,尽管它比较年轻,但它已经变得非常流行和广泛使用。
  • 分布式和可伸缩性:Solr 最初关注的是与查询、分面等相关的核心搜索问题和特性。它支持传统主从结构形式的分布式搜索。Elasticsearch 发布时采用了真正分布式和可伸缩的架构,这是它的主要优势。后来 Solr 4.0 开始用 SolrCloud 支持分布式和可伸缩的架构。
  • 集群管理:Solr 使用 Apache ZooKeeper,这是一个非常流行和成熟的配置维护解决方案。反过来,Elasticsearch 有一个内置的框架,名为 Zen Discovery,更容易受到裂脑问题的影响。在裂脑场景中,一个集群指定两个主服务器,这会导致数据丢失。
  • REST 端点:两者都公开 REST 端点。Elasticsearch 纯粹是 JSON in 和 JSON out,而 Solr 支持多种格式,包括 XML、JSON、CSV 和 binary。
  • 推送查询:过滤是 Elasticsearch 的一个特性,当新文档符合您指定的条件时,它会通知应用程序。Solr 不支持推送查询。
  • 分析、监控和度量:Solr 更关注文本搜索和支持特性。但在分析和监控方面,Elasticsearch 表现出色。它提供了无数的监控选项,而 Solr 中的支持是有限的。ELS 堆栈(Elasticsearch、Logstash 和 Kibana 组合在一起)允许您实时获得可操作的见解。栈广泛用于与日志管理相关的需求。
  • 文本分析:在 Solr 中,应该使用托管 API 来预定义或配置分析器。在 Elasticsearch 中,甚至可以在查询时设置分析器。
  • 易用性:Elasticsearch 一直很容易上手和运行,但最近的 Solr 5.0 也不甘落后。如果您在无模式模式下运行 Solr,索引和搜索只是一个两步过程:下载和开始。但是 Solr 一般期望你配置两个 XML 文件,schema.xmlsolrconfig.xml。这些文件有很好的文档记录,但需要一些理解,从长远来看,这可以提供更好的可管理性。

相关技术

通过本书的课程,在为你的需求开发解决方案时,你会遇到一些相关的项目。我在整本书中尽可能详细地介绍了这些项目。如果您想更深入地了解它们,请参考它们各自的手册。这些项目如下:

  • 阿帕奇动物园管理员:这个控制着 SolrCloud 的心跳。它是一个中央服务,用于以容错和高度可用的方式维护集群配置、存储状态和同步信息。要使 SolrCloud 正常工作,至少应该有一个 ZooKeeper 实例启动并运行。
  • Apache OpenNLP:这是一个 Java 库,用于文本的自然语言处理。它支持理解和解释人类语言文本的任务。在这本书里,你将学会应用这些技术来构建一个强大的搜索引擎。
  • 阿帕奇·UIMA:如果你的数据是非结构化的,Solr UIMA 贡献模块可以用来给数据结构化。UIMA 允许我们定义一个定制的管道来分析大量的非结构化文本,并对提取的元数据进行注释,这些元数据可以添加到 Solr 字段中。
  • Carrot clustering:通过使用 Carrot2,可以将相似或语义相关的搜索结果聚集在一起,只需对 XML 配置做一些修改就可以做到这一点。
  • Apache Tika:这个工具包提供了一个框架,用于从许多不同格式的文件(如 Word、PPT 和 PDF)中解析和提取内容和元数据。Solr 提供了一个 Solr Cell 框架,它使用这个工具包来索引这些文件的内容和元数据。

摘要

本章简要介绍了 Apache Solr,概述了 Solr 的内容,Solr 如此受欢迎的原因,以及为什么应该在项目中使用它。我还简要介绍了 Solr 的新特性。随着 Solr 目前的成熟,它不仅仅局限于作为一个搜索引擎,还被广泛用作 NoSQL 数据库和分析引擎。

下一章将介绍如何设置 Solr 以及内部的工作原理。第三章是关于信息检索的概念和搜索引擎如何工作的内部原理,独立于其他章节,可以不按顺序阅读。

资源

Apache Solr 的官方网站是 http://lucene.apache.org/solr/ 。Solr 的最新版本可以从这个位置下载。随着每个二进制版本的发布,Solr 提供了特定于该版本的官方文档、变更的细节和 Javadocs。

Solr cwiki ( https://cwiki.apache.org/confluence/display/solr/Apache+Solr+Reference+Guide )和 wiki ( https://wiki.apache.org/solr/ )是在线 Solr 信息的两个主要来源。cwiki 是一个由 ASF 社区维护的合流站点,所有的提交都由 Solr 提交者执行。现有的信息是经过官方批准和核实的。如果你对任何 cwiki 页面有任何建议,请随意添加评论。提交者将根据建议做出响应或做出适当的更改。

Solr wiki 是一个易于编辑的网页集合,由社区维护,托管在 MoinMoin web 引擎上。任何有权限的人都可以编辑页面。如果你想要编辑权限,写信给 Solr 邮件列表或 IRC 频道。

如需提问、讨论问题或为社区做出贡献,请参考位于 http://lucene.apache.org/solr/resources.html 的 Solr 资源页面了解更多信息。

二、Solr 设置和管理

索引和搜索是 Solr 中执行的两个主要操作。索引是将内容添加到 Solr 索引以使其可搜索的过程。但是在索引之前,首先需要设置 Solr。版本 5.0 的主要焦点是提高易用性,这使得 Solr 的设置过程变得非常容易。这些步骤非常简单,如果您在无模式模式下运行 Solr,使 Solr 能够动态猜测字段类型并定义字段,整个设置过程可以在几分钟内完成。

本章首先介绍 Solr 基础知识,包括它的术语和目录结构。然后,您将设置 Solr 并简单地索引和搜索示例文档。对于初次使用或从 4.x 版本迁移过来的用户,本章采用了一种简单的演示方法。在阅读这些章节的过程中,您将会看到更高级的例子,并获得一些关于 Solr 特性和组件的背景知识。

此外,您将了解 Solr 的主要用户选项和管理特性。通过这些解释,您将看到 Solr 在早期版本中是如何工作的。为了易于理解和方便,本章假设一个环境只有一个 Solr 实例(或服务器)。第十章重点介绍分布式方法和 SolrCloud,它支持复制、可伸缩性和容错。

本章涵盖以下主题:

  • Solr 作为独立服务器
  • 重要术语和目录/文件结构
  • 实用程序脚本
  • Web 管理界面
  • 存储器管理
  • 实例管理
  • 常见例外

独立服务器

Solr 作为一个独立的服务器运行,预先捆绑了启动和运行实例所需的一切。在 5.0 版之前,Solr 是作为 WAR 文件分发的。要部署它,要么使用预绑定的 Jetty 实例,要么将dist/solr-<version>.war复制到 Tomcat 或另一个 servlet 容器。但是现在 Solr 抽象了部署过程,需要您将它视为一个独立的服务器,而不必担心在哪里以及如何部署。如果您使用的是以前的版本,您需要从记忆中抹去这些知识,并开始使用为管理提供的脚本。对于那些对它现在是如何部署的感到好奇的人,Solr 在内部使用 Jetty servlet 容器——但那是一个实现细节,你应该把它看作一个独立的服务器。在其他容器中部署 Solr 的灵活性已经被取消,以便更好地利用容器的网络堆栈特性。

图 2-1 用一个 Tomcat 的例子来描述 Solr 作为一个服务器以及在 4.x 和 5.x 版本中的部署有何不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-1。

Solr versions 4.x and 5.x

在 Solr 5.3.0 之前的版本中,您可以嗅探到server/webapps目录中的solr.war

Note

术语“独立服务器”在这里指的是您看待 Solr 的新视角,而不是指只有一个 Solr 实例的环境。在 SolrCloud 模式下,这里提到的每个独立服务器都是一个实例(或节点)。

先决条件

Apache Solr 是用 Java 编写的,安装 Solr 5.3.1 的唯一先决条件是 Java 7 或更高版本。建议使用更新版本 u55 或更高版本。强烈建议不要使用以前的版本。如果你的机器运行的是 Java 8,那就更好了,因为它可以提高性能。继续之前,请检查您的 Java 版本,如下所示:

$ java –version

java version "1.8.0_31"

Java(TM) SE Runtime Environment (build 1.8.0_31-b13)

Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

对于 4.8.x 之前的 Solr 版本,可以使用 Java 6。如果前面的命令没有在您的机器上找到 Java 安装,您可以从 www.oracle.com/technetwork/java/javase/downloads/index.html 下载一个副本。安装步骤参见 www.java.com/en/download/help/download_options.xml

[计] 下载

可以从 http://lucene.apache.org/solr/downloads.html 下载 Solr 的最新二进制。下载页面包含对 Apache 镜像站点的引用。单击建议的选项或任何备份站点,下载最新的二进制文件(zip 或 tar)。

下载完成后,使用适当的工具从压缩的二进制文件中提取目录,如下所示:

$ tar –xvf solr-5.3.1.tgz (*nix)

$ unzip solr-5.3.1.zip (Windows)

术语

为了避免歧义并更好地理解 Solr,了解一些术语以及 Solr 上下文中使用的文件是很重要的。在我们进一步讨论之前,本节先介绍常见术语,然后是 SolrCloud 特定术语,最后是一些重要的文件。

通用术语

以下是所有类型的 Solr 设置中使用的通用术语列表:

  • Solr 实例:这个通用术语用在应用服务器的上下文中——例如,Tomcat 实例或 Jetty 实例。这里它指的是运行在 Java 虚拟机(JVM)内部的 Solr 服务器。可以配置零个或多个内核在 Solr 实例中运行。每个 Solr 实例都需要引用一个单独的 Solr 主目录。
  • Solr 核心:您的每个索引和该索引所需的文件构成一个核心。因此,如果您的应用程序需要多个索引,您可以在一个 Solr 实例中运行多个内核(而不是多个 Solr 实例,每个实例包含一个内核)。物理上,每个内核映射到 Solr 主目录中的一个子目录。
  • Solr home:这是 Solr 几乎所有内容都参考的目录。它包含关于核心及其索引、配置和依赖性的所有信息。本书使用术语$SOLR_HOME来指代这个目录。
  • Solr shard:这个术语用在分布式环境中,在这种环境中,您在多个 Solr 实例之间划分数据。特定实例上的每个数据块称为一个碎片。碎片包含整个索引的子集。例如,假设您有 3000 万个文档,并计划将它们分成三份,每份包含 1000 万个文档。您将需要三个 Solr 实例,每个都有一个具有相同名称和模式的核心。在提供查询服务时,任何一个碎片都可以接收请求,并将其分发给其他两个碎片进行处理,获得所有结果,然后将合并后的结果返回给客户端。

太阳云术语

在 Solr 中,可以有两种类型的分布式架构:传统和 SolrCloud。从 1.3 版开始,分布式搜索的传统方法使用主从架构。在这种方法中,索引是在主服务器上创建的,它被复制到一个或多个专用于搜索的从服务器上。这种方法有几个限制,你会在第十章中了解到。

为了解决这些限制,SolrCloud 发布了 4.0 版。这种革命性的方法建立了一个 Solr 服务器集群,以提供容错和高可用性,并提供分布式索引、集中式配置、自动负载平衡和故障转移等功能。

SolrCloud 引入了与传统架构略有不同的新术语。如果您正在使用 SolrCloud,记住这些术语很重要。为了简单起见,本书使用与传统架构相关的术语,除非我们正在做一些特定于 SolrCloud 的事情。以下列表定义了与 SolrCloud 相关的关键术语:

  • 节点:Solr 的单个实例在 SolrCloud 中称为一个节点。
  • 集群:环境中的所有节点。
  • 集合:簇中的完整逻辑索引。集合中的所有碎片都使用同一套配置文件。
  • 碎片:一个集合的逻辑部分或切片。每个碎片由一个或多个索引副本组成,以实现冗余。
  • 副本:碎片的物理副本,作为 Solr 核心在节点中运行。
  • 首领:在一个碎片的所有复制品中,有一个被选为首领。SolrCloud 将所有请求转发给 shard 的领导者,后者将请求分发给副本。
  • ZooKeeper: ZooKeeper 是一个 Apache 项目,被分布式系统广泛用于集中配置和协调。SolrCloud 使用它来管理集群和选举领导者。

重要的配置文件

您可以开发一个成熟的搜索引擎,并将其投入生产,甚至不用编写一行 Java 代码。Solr 使这成为可能,它允许您只通过修改 XML 就可以配置所有的特性和模式。您可以通过注册组件并在基于 XML 的配置文件中适当地链接它们来实现一个特性。以下是一些主要的配置文件:

  • solr.xml:在启动 Solr 实例时,solr.xml是 Solr 在$SOLR_HOME目录中寻找的第一个文件。该文件主要包含与 SolrCloud 相关的信息。它的配置适用于 Solr 实例,而其他文件特定于一个核心。Solr 曾经引用这个文件来识别要加载的内核。在 4.4 版中,引入了自动核心发现,在solr.xml中创建条目的规定已被否决,从 5.0 版起不再受支持。
  • solrconfig.xml:该文件包含与请求处理、响应格式化、索引、配置其他组件、管理内存、缓存和提交相关的特定于核心的配置和定义。
  • schema.xml : C包含整个模式——字段的定义、类型(也称为fieldType)和评分策略(如果有的话)。fieldType定义了要在字段上执行的文本分析,以控制索引和搜索时的匹配行为。
  • core.properties : Solr 引用该文件进行核心发现。这是一个 Java 属性文件,包含特定于核心的配置,例如核心的名称和数据目录的路径。您还可以在该文件中将自定义属性定义为键值对,并在 Solr 配置文件中引用它来进行值替换。它可以位于任何子目录和任何深度,该目录被视为核心目录。唯一的限制是同一个目录层次不能有多个core.properties(不能在另一个核心中创建一个核心)。

目录结构

要设置和使用 Solr,您需要理解两组目录结构。一个是 Solr 发行版(从下载的 tar 或 zip 中提取的目录),另一个是 Solr 主目录,其中包含所有内核的索引和配置。

太阳能装置

Solr 5.x 发行版的目录结构不同于以前的版本。这一改变是为了让 Solr 更有条理,更易于使用。图 2-2 显示了这个新的目录结构。省略号(…)表示该目录包含其他文件或目录。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-2。

Solr installation directory structure

以下是 Solr 发行目录中所有目录和重要文件的描述:

  • bin:包含启动、停止和管理 Solr 的实用程序脚本。该目录在 4.8 版中引入,包含适用于 Windows 和*nix 机器的脚本。以下列表描述了这些脚本:
    • 用于启动、停止和其他管理目的的脚本。接下来的章节将对此进行更详细的介绍。
    • solr.in.sh/solr.in.cmd:特定于实例的设置的环境文件。
    • 使用这个脚本,您可以强制终止在特定端口上运行的 Solr 实例。Windows 没有相应的实用程序。
    • solr.<port>.port:当您使用脚本启动 Solr 实例时,会创建这个文件。它供内部使用,在停止实例时会自动删除。
    • post:将文档索引到 Solr 的脚本。
    • 如果你想把 Solr 作为一个服务来安装,这个脚本可以让你以一种交互的方式来完成。
    • init.d:如果想在 Unix 环境下使用init进程运行 Solr,可以参考的目录。
  • 除了核心库之外,Solr 还包含了其他的库,它们是 Solr 的一部分,但是是来自其他项目的贡献,在需要的时候使用。该目录包含以下子目录,每个子目录构成一个模块:
    • analysis-extras:这包含了额外的国际化和多语言支持的分析器。
    • clustering:上一章提到了 Carrot2。该目录包含在 Solr 中使用 Carrot2 时实现集群的插件。
    • 如果 Solr 是您的二级存储,而 SQL 数据库是您的一级存储,那么您不必担心编写自己的客户端程序来从数据库中获取数据并对其进行索引。DataImportHandler是一个贡献的插件,允许您从各种来源导入数据,只需少量的 XML 更改。它不限于数据库,还可以用于从 XML 和 HTTP 数据源导入数据。
    • dataimporthandler-extras:包含使用DataImportHandler导入数据时可能需要的附加插件。
    • extraction:要从 Microsoft Word 文档或 Adobe PDFs 等富文档中提取数据,可以使用 Apache Solr 内容提取库(Solr Cell)。这个插件使用 Apache Tika 进行提取,我们在第一章的中提到过。
    • 如果你的文本不是英文的,你的项目可能需要这个模块。Apache Solr 语言标识符插件允许您识别文本的语言并适当地处理它。
    • map-reduce:这个实验模块使您能够使用 map-reduce 作业建立索引。
    • morphlines-cell:这是一个内容提取的实验模块。
    • morphlines-core:这是另一个实验性的插件,它依赖于 Kite Morphlines 框架,在加载到 Solr 时,可以快速轻松地执行海量数据的提取、转换和加载(ETL)。
    • 这个世界上并不是一切都是完美的,你的数据可能就是如此。如果您的数据不是结构化的,您可以在索引数据时使用非结构化信息管理体系结构(UIMA)项目。
    • 如果你想为你的搜索引擎设计一个用户界面,你可以在 Solr 中使用 Apache Velocity 模板引擎。
  • docs:这包含了你下载的 Solr 版本的特定文档。
  • licenses:这包含了 Solr 提供的所有库的许可信息。
  • 默认情况下,这个目录是与 Solr 实例相关的所有内容的中心位置。它包含服务器、Solr 主目录和日志。它还包含 Jetty 配置文件,可以修改这些文件来改变服务器的行为;但是,您应该避免这样做,因为 Solr 希望您忽略实现细节。对于任何定制,您都应该调整bin脚本中可用的属性。对于生产环境,建议将 Solr 主目录和日志位置配置为不同于服务器目录。以下是服务器目录中的子目录:
    • contexts : Solr 内部使用 Jetty,这个目录包含 Jetty 为 Solr 所需要的部署描述符。
    • etc:该目录包含 Jetty 配置文件。
    • lib:这包含了 Solr 实例所需的 Jetty 和其他库。
    • logs:默认情况下,Solr 日志在此目录下创建。
    • modules:Jetty 使用它来包含模块定义。
    • resources:包含log4j.properties等配置文件。
    • scripts:包含 SolrCloud 的实用脚本。
    • 这是默认的 Solr 主目录,您在“通用术语”一节中已经了解了。我们将在下一节更详细地讨论它。
    • solr-webapps : Jetty 提取这个目录中的 Solr。
    • start.jar:用于启动 Jetty 的可执行 JAR。Solr 5.3.0 已经过内部升级,可以在 Jetty 9 上运行。Solr 不再支持使用“java -jar start.jar”直接运行它,bin/solr 脚本是唯一的方法。

Note

在本书中,术语$SOLR_DIST指的是本节讨论的 Solr 发行目录。

Solr Home

Solr 主目录包含 Solr 配置文件和索引,是与 Solr 实例相关的所有内容的主目录。一个 Solr 实例可以有多个内核,它们都在这个目录中定义。Solr 服务器需要一个对主目录的引用,如果没有提供,将采用配置的默认路径。为了成功启动核心,Solr 要求配置和库以适当的方式可用。在$SOLR_HOME中创建一个lib目录或者包含相关库的核心目录也是一个很好的实践。

图 2-3 显示了一个样本 Solr 主目录,包含三个内核,分别位于core1core2/sub-dir1core3,由相应的core.properties文件检测。您还可以在$SOLR_HOME中看到一个lib目录,在所有已定义的内核之间共享依赖关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-3。

Solr home directory structure

以下是 Solr 主目录中所有子目录和重要文件的描述:

  • solr.xml:这已经在“术语”一节中介绍过了。
  • zoo.cfg:包含 ZooKeeper 的配置。第十章采访动物园管理员。如果没有使用 SolrCloud,可以忽略这个文件。
  • configsets:如果您想在实例上的多个内核之间共享配置,您可以使用 Solr 4.8 中引入的配置集。即将到来的“核心管理”部分将更详细地介绍这一点。
  • 将所有的公共库保存在这个目录中,以便在所有内核之间共享。
  • 核心(core1core2/sub-dir1core3):在这个例子中,我们有三个索引,所以我们有三个核心。该目录是所有核心相关文件的根目录。
    • core.properties : Solr 引用该文件进行核心的自动发现。它可以出现在目录树中的任何级别,包含该文件的目录将是核心根目录。在图 2-3 中,core2的目录为core2/sub-dir1。因此confdata,以及核心特有的一切都应该存在于sub-dir1。该文件是一个 Java 属性文件,您可以在其中配置特定于核心的属性。
    • conf:该目录包含所有内核特有的配置文件,包括solrconfig.xmlschema.xml
    • 这个目录是为你的索引准备的。index子目录包含 Solr 索引,它是在索引文档时创建的。tlog子目录包含您的事务日志,这对确保文档写入的一致性至关重要。
    • lib:该目录包含所有特定于核心的依赖项。

动手练习

您一定渴望快速启动 Solr 实例并开始搜索结果。本节采用一种简单的方法来启动 Solr、索引文档和搜索结果。在我们在接下来的章节中讨论更详细的例子之前,对整个过程的概述将对您的实验有所帮助。在下一节中,您将更详细地研究如何启动和管理 Solr。

开始 Solr

您可以使用发行包中提供的脚本(从 4.10 版开始)来启动 Solr。

$ cd bin

$ ./solr start

Started Solr server on port 8983 (pid=2108). Happy searching!

现在,您的 Solr 实例已经启动,您可以将浏览器指向http://localhost:8983/solr。图 2-4 显示了 Solr 管理界面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-4。

Dashboard, the home page of the Solr admin interface

如果您的仪表板显示如图 2-4 所示,则 Solr 已经成功启动。如果出现错误,要么不显示该页面,要么在仪表板顶部高亮显示错误信息,如图 2-5 所示。如果错误出现在某个特定的内核中,如图 2-5 所示,其他内核将按预期工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-5。

Core initialization exception

在图 2-4 左侧选项卡的底部,您会看到“无内核可用”这是因为我们还没有配置任何核心。如您所知,要创建一个索引,您需要定义一个核心,而核心在物理上位于SOLR_HOME目录中。所以首先你应该知道你的SOLR_HOME在哪里,或者让服务器把你的首选目录称为SOLR_HOME。在下一节中,您将在默认的SOLR_HOME目录中创建一个核心,这个目录是分布目录中的server/solr

如果您想在特定端口上运行 Solr,可以按如下方式进行:

$ ./solr start –p 8980

指定希望 Solr 运行的端口。前面的命令在端口 8980 上运行 Solr。该参数是可选的。默认情况下,Solr 运行在端口 8983 上。

同样默认情况下,脚本在后台模式下运行 Solr,输出被发送到solr-<PORT>-console.log。如果您运行 Solr 的时间很短,并且希望在控制台上打印输出,那么您可以使用–f选项来运行它:

$ ./solr start –f –p 8983 –V

-V是可选的详细模式,即使在后台模式下运行 Solr 时也可以使用。

创建一个核心

在 Solr 5.x 中创建内核最简单的方法是无模式化。在无模式模式下,字段是在索引文档时由字段猜测机制动态定义的。下面是一个快速创建无模式核心的例子,默认情况下,当您没有提供配置目录时,Solr 会创建它:

$ ./solr create -c hellosolr

Setup new core instance directory:

/home/applications/solr-5.3.1/server/solr/hellosolr

Creating new core ’hellosolr’ using command:

http://localhost:8983/solr/admin/cores?action=CREATE&name=hellosolr&instanceDir=hellosolr

{

"responseHeader":{

"status":0,

"QTime":2461},

"core":"hellosolr"}

-c <corename>是您要创建的核心的名称。

刷新您的 Solr 管理页面,您将看到“No cores available”消息被一个列出您创建的核心的下拉菜单所取代。

索引一些数据

选择 hellosolr 核心并转到 Documents 选项卡。此选项卡允许您直接从界面中索引文档。图 2-6 显示了屏幕快照。要索引文档,您需要选择一种文档类型并以该格式提供数据。让我们将 Solr 附带的样本数据编入索引,并在example/exampledocs中提供。因为我们的核心是无模式的,所以我们可以索引目录中的任何 XML 或 JSON 文件,而不用担心字段定义。使用以下步骤对 Solr 提供的money.xml文件中的文档进行索引:

From the Document Type drop-down list, select File Upload.   Browse the money.xml file.   Click the Submit Document button to index the documents in that file.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-6。

Uploading the file for indexing

或者,从“文档类型”下拉列表中,您可以选择 XML 选项并粘贴文档进行索引。成功上传或提交后,您将看到回复状态“成功”此状态表示文档已被索引,但只有在提交更改后才能满足搜索请求。默认情况下,管理界面触发此提交,因此您可以开始搜索结果。

Note

example/exampledocs中的文件包含 Solr 指定格式的文档,不要随意上传文档。要索引您自己的数据,请创建一个遵循示例文件中约定的文档。

搜索结果

访问查询选项卡,然后单击执行查询按钮。这将显示您索引的文档。默认情况下,Solr 从索引中获取前 10 个文档。在“查询”窗格中,q 文本框包含您的查询,您需要以“字段名:查询”的格式指定该查询。这里,* *表示所有字段中的所有值。如果您想要特定查询的结果,例如在manu字段中包含短语“Bank of America”的所有文档,您可以在 q 文本框中键入 manu:“Bank of America”。wt参数指定了响应格式。图 2-7 显示了 json 格式的结果,JSON 被选为 wt 值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-7。

Search results

既然您已经理解了索引和搜索的简单过程,那么您可以跳过任何不需要的部分,直接跳到与您相关的部分。但是,我建议你按照顺序来。在接下来的部分中,您将深入了解设置和管理任务的细节。

Solr 脚本

Solr 脚本是在 4.10 版中引入的,从 Solr 5.3.0 开始,脚本是启动 Solr 的唯一条款。对 start.jar 的支持——用 Jetty 运行 Solr 的传统方式——已经被撤销,以支持 HTTP 和 HTTPS Jetty 模块。因此,要启动和停止 Solr,应该使用以下脚本:

bin/solr – *nix

bin/solr.cmd – Windows

Note

为了避免出现重复的代码,本书使用名称bin/solr来指代这两个脚本。这两个脚本的目的是相同的。每一种都有其特定的环境。

在本节中,您将详细了解如何使用bin/solr脚本来启动、停止和管理 Solr。这里提供的例子假设您在 Windows 机器上运行来自bin目录的脚本。

启动 Solr

启动 Solr 很容易!你已经在“动手练习”部分完成了。在这一节中,您将了解更多关于它的细节。

Solr 可以两种模式启动:单机和 SolrCloud。我们忽略了传统的分布式架构,因为它的启动机制与独立模式相同。默认情况下,Solr 以独立模式运行,为了简单起见,本章将对此进行介绍。以下命令使用默认端口 8983 上的默认设置启动 Solr。

$ solr start

您可以向 Solr 提供额外的参数来覆盖默认设置,如下例所示。

$ solr start -p 8983 -h localhost -m 4g

  • -p指定服务器端口
  • -h指定主机名
  • -m指定 JVM 的堆大小。此参数为-Xms 和-Xmx 指定了相同的值

如果您正在运行 Solr 的早期版本,您可以使用下面指定的server目录中的start.jar来启动它:

$ java -jar start.jar

了解脚本支持的命令及其提供的选项的最简单方法是利用bin/solr脚本的help命令。您将在下一节学习使用帮助菜单。

使用 Solr 帮助

bin/solr脚本冗长且有据可查。最好的方法是使用 help选项。这提供了所有可用的命令以及一些示例:

$ solr -help

Usage: solr COMMAND OPTIONS

where COMMAND is one of: start, stop, restart, healthcheck, create, create_core, create_collection, delete

下面是一个独立的服务器示例(它在后台通过端口 8984 启动 Solr):

$ solr start -p 8984

下面是一个 SolrCloud 示例(它使用 localhost:2181 在云模式下启动 Solr 以连接到 ZooKeeper,最大堆大小为 1GB,并启用了远程 Java 调试选项):

$ solr start -c -m 1g -z localhost:2181 -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1044"

Pass -help after any COMMAND to see command-specific usage information,

such as:    solr start -help or solr stop -help

现在,如果您知道想要使用的命令,您可以通过在命令名称后键入–help来获得关于其用法的更多信息:

$ solr stop -help

Usage: solr stop [-k key] [-p port]

-k key      Stop key; default is solrrocks

-p port     Specify the port the Solr HTTP listener is bound to

-all        Find and stop all running Solr servers on this host

停止 Solr

您可以通过运行如下脚本来停止 Solr:

$ solr stop –p 8983

这将停止在端口 8983 上运行的 Solr 实例。必须提供–p–all参数。如果指定–all,该命令将停止所有正在运行的节点。此外,只有当 Solr 已经用bin/solr脚本启动时,前面的命令才会停止 Solr。

当您使用bin/solr脚本启动 Solr 时,它会在bin目录中创建一个solr-<port>.port文件,以标识正在运行的 Solr 实例,然后stop命令会删除这个文件。

重启 Solr

您可以使用restart命令重启一个正在运行的 Solr 实例。start 选项的所有参数都与 restart 一起使用;唯一的区别是–p <port>选项是强制的。以下是重启在端口 8983 上运行的 Solr 实例的示例命令:

$ solr restart –p 8983

确定 Solr 状态

使用status命令,您可以在机器中验证 Solr 的所有运行实例。该命令提供实例运行的端口号、Solr 主目录的路径、分配的堆内存量及其消耗状态:

$ solr status

Found Solr process 8076 running on port 8983

{

"solr_home":"D:\\applications\\solr-5.3.1\\server\\solr\\",

"version":"5.3.1 1703449 - noble - 2015-09-17 01:48:15",

"startTime":"2015-11-05T18:07:32.916Z",

"uptime":"0 days, 0 hours, 57 minutes, 44 seconds",

"memory":"80.7 MB (%16.4) of 490.7 MB"}

}

配置 Solr 启动

在启动 Solr 之前,您可能希望定制一些属性,比如服务器主机/端口、堆空间分配和 Solr home。以下是这种自定义的两种常用方法:

  • solr.in环境文件中设置属性
  • 将这些值作为参数传递给solr脚本

环境文件是设置属性的推荐位置,也是持久的。在多次重新启动之间,环境会保留下来。如果通过传递参数来启动 Solr,它将覆盖或附加到环境文件中定义的属性值。

您可以通读环境文件中的注释,或者运行这个命令来查找所有的 Solr 启动选项:

$ solr start -help

管理 Web 界面

在运行 Solr 的过程中,您使用了 Solr 管理界面进行索引和搜索。Solr admin UI 是一个非常强大的工具,它为 Solr 管理员和开发人员提供了关于他们的核心、实例以及整个集群和环境的深刻见解。它为用户提供了一个丰富的界面来查看配置文件、运行查询、分析文档等等。以下是使用 Solr 管理界面的主要原因:

  • JVM 属性和线程转储:Java Properties 选项卡提供了运行 Solr 的 JVM 的属性,比如类路径和内存设置。“线程转储”选项卡允许您检查服务器线程信息,如线程状态、执行时间和堆栈跟踪。
  • 核心管理:控制台中的核心管理选项卡允许您添加、卸载、重新加载、重命名、优化和交换核心。
  • 日志管理:Logging 选项卡用一种颜色方案显示日志消息。每种颜色代表不同的日志记录级别。为了方便起见,这些消息是折叠的,可以单击以展开为详细视图。该选项卡还允许您动态更改包和类的日志记录级别。
  • Core overview:选择 Core,默认情况下会加载“overview”页面,提供重要的统计信息,包括索引中的文档数、索引的总大小、上次索引时间、复制信息以及与 core 目录相关的信息。
  • 搜索:选择一个核心,然后单击 Query 选项卡进行查询、facet、拼写检查或调用任何自定义搜索处理程序。此页面经常用于运行、调试和评估即席查询。
  • 索引:选择一个核心并单击 Documents,通过提交表单来索引 XML、JSON 或 CSV 文档,或者您可以从本地驱动器上传一个文件。如果在solrconfig.xml中配置了数据导入,您可以从数据库中导入数据。对于此任务,“数据导入”选项卡提供了一个专用页面。
  • 分析:程序员经常使用管理界面来分析字段或字段类型的行为。您可以单击分析选项卡,在相应的字段中输入要索引或查询的文本,然后单击分析值按钮。该系统提供逐步的文本分析,在索引和查询时执行,并在两个标记匹配的步骤处突出显示文本。
  • 复制:如果您在传统的主从环境中运行 Solr,您可以通过 Replication 选项卡启用、禁用或强制核心的复制。
  • 浏览文件:文件选项卡列出了<core>/conf目录中的所有文件和目录。
  • 查看组件统计数据:插件/统计数据选项卡允许您查看重要的统计数据。
  • 使用模式浏览器:此屏幕允许您选择一个字段或字段类型,并浏览其模式信息和索引标记。这个屏幕对于探索索引术语非常有用。例如,如果要为字段生成停用词列表,可以使用浏览器提供的索引词和计数来评估候选停用词。
  • 可视化段信息:底层索引可以由一组子索引或段组成。“段信息”页面将这些段可视化,并提供有关它的元数据,如索引文档数和删除的文档数。

在 Solr 5.1 中,UI 已经使用 AngularJS 进行了重构。

存储器管理

在 Solr 中,核心包含一个索引,它的配置文件如solrconfig.xmlschema.xml,以及其他相关文件。每个核心可以有不同的索引结构,并可用于不同的搜索需求。Solr 实例可以有多个内核,它提供了对所有内核的统一管理。Solr 允许你动态地创建一个内核,重命名它,卸载它,等等。在本节中,您将学习如何在不重启 Solr 服务器的情况下执行所有这些任务。

配置集

Solr 4.8 引入了创建配置集的规定,配置集是一组可共享的配置文件,可用于创建新的内核。这些在分布式环境中很有用。Solr 5.x 发行版还捆绑了一些预配置的配置集,您可以参考这些配置集来创建您的核心,而不是从头开始编写。这些命名的配置集可以在server/solr/configsets目录中找到。以下是 Solr 5.3.1 中预绑定的配置集列表:

  • basic_configs:这包含运行 Solr 所需的最低配置。
  • 如果你想无模式化,你可以使用这个配置。它被配置为支持带有字段猜测的托管模式。
  • 这是一个成熟的配置,启用了大多数可选功能。您可以使用这个配置集作为核心配置的起点。

创建配置集

配置集目录的默认主目录是SOLR_HOME。您可以按如下方式创建配置集:

Create a configset directory in SOLR_HOME: $ cd $SOLR_HOME $ mkdir configsets   The configsets directory is your configset base directory. In this directory, you can create as many subdirectories as you need. The name of each subdirectory indicates the name of that configset: $ cd configsets $ mkdir configset1 configset2 configset3   Your named configset subdirectory should contain a conf subdirectory with solrconfig.xml, schema.xml, and other configuration files.   If you want to change the name of your configset base directory, you can do it in solr.xml: <solr>   <configSetBaseDir>sharedConfigSets</configSetBaseDir> </solr>

图 2-8 显示了一个配置集目录结构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-8。

Config Sets directory structure Note

在即将到来的版本中,Solr 将引入 REST API 来管理配置集。这个 API 将允许您将配置集上传到一个模板位置,并使用它们来创建核心。

创建核心

假设您有一个新的搜索需求,它需要一个具有不同结构的新模式定义。在上一节中,您使用默认模式创建了一个核心。在本节中,您将学习如何使用现有的配置集创建核心。在第四章中,您将学习如何创建模式和定义字段。

如果您的 Solr 实例已经包含一个核心,并且您希望对新的核心使用相同的配置,那么您可以使用该配置创建一个配置集。如果新模式是不同的,我建议您使用与 Solr 预绑定的 configset。命名配置集sample_techproducts_config是任何模式设计的良好起点,因为它定义了大多数 Solr 特性。

以下是在 Solr 中创建新内核的方法。创建核心后,通过获取状态或使用 Solr admin UI 来验证它。

bin/solr 脚本

bin/solr脚本可以在机器上运行的任何 Solr 实例中创建一个新的内核。创建核心的命令如下:

solr create –c <corename> -d <confdir> -p <port>

corename是强制参数。Solr 自动在SOLR_HOME中创建指定的核心目录,以及核心发现所需的core.properties文件。

confdir是您要使用的命名配置集之一或 conf 目录的路径。Solr 将配置文件从这个目录复制到核心目录。如果没有指定–d,Solr 将使用data_driven_schema_configs配置集。

port标识要在其中创建核心的本地 Solr 实例。如果没有指定port,将在脚本找到的第一个运行实例中创建核心。

下面是一个示例命令,它使用sample_techproducts_configs配置集在端口 8983 上运行的 solr 实例中创建一个名为 hellosolr 的核心。

$ ./solr create –c hellosolr -d sample_techproducts_configs -p 8983

或者,您可以使用带有相同选项的create_core命令:

solr create_core –c <core-name> -d <conf-dir> -p <path>

create选项检查 Solr 在指定端口上是以独立模式还是 SolrCloud 模式运行,并基于此调用create_corecreate_collectioncreate_collection选项用于 SolrCloud 模式。你会在第十章中看到一个系列创作的例子。

当使用脚本创建核心时,您不应该手动创建相应的目录,因为脚本会处理它。

核心管理 REST API

创建核心的另一种方法是调用核心管理 API。因为它是一个 REST API,你可以从你的程序中调用它,使用curl甚至浏览器。如果您想使用 API 创建一个核心,可以按如下方式进行:

http://host:port/solr/admin/cores?action=CREATE&name=corename&instanceDir=path/to/instance&config=solrconfig.xml&schema=schema.xml&dataDir=data

corenameinstanceDir是强制参数。如果不提供其他参数,Solr 会提供默认值。

您可以使用现有配置集创建核心,如下所示:

http://host:port/solr/admin/cores?action=CREATE&name=corename&instanceDir=path/to/instance&configSet=configset1

以下是使用核心管理 API 创建 hellosolr 核心的示例:

$ curl``http://localhost:8983/solr/admin/cores?action=CREATE&name=hellosolr

管理界面

Solr admin UI 提供了一个创建核心的屏幕——以及核心管理支持的所有操作。尽管本章涵盖了核心管理 API 提供的所有管理选项,但它仅涵盖了用于创建核心的 UI。

在浏览器中打开管理界面。打开“核心管理员”选项卡,然后单击“添加核心”按钮。在显示的表单中填入适当的值,然后单击添加核心。图 2-9 显示了创建核心的屏幕快照。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-9。

Solr admin screen for core creation

用手

您甚至可以手动创建一个核心,但是这需要 Solr 重启。以下是手动创建核心需要遵循的步骤:

Create a core directory in SOLR_HOME.   Create a core.properties file in that directory and define a property name=<corename> inside the file. corename is the name of your core.   Copy the conf directory in the newly created core directory.   Restart the Solr instance.

同样,您可以手动执行其他核心管理操作。

我介绍这种方法是为了帮助您更好地理解核心管理。您可以在试验和开发过程中采用这种方法。但是在生产中这样做会导致 Solr 实例停机,所以不推荐这样做。

核心状态

您可以通过使用核心管理 API 来获取注册的核心的状态。下面的调用给出了所有核心的状态。即使您尚未注册任何核心,也可以进行此呼叫:

http://localhost:port/solr/admin/cores?action=STATUS

如果您对特定内核的状态感兴趣,您需要用<corename>传递一个额外的core参数。

http://localhost:port/solr/admin/cores?action=STATUS&core=<corename >

bin/solr脚本没有为您提供获得核心状态的条款。通过使用这个脚本,您可以只获得 Solr 实例的状态。

卸载核心

如果不再需要核心,可以使用核心管理 API 卸载它。此处显示了卸载的终点以及所需的参数:

http://localhost:port/solr/admin/cores?action=UNLOAD&core=<corename>

只有在所有现有请求都得到服务后,才卸载核心。所有对核心的新请求都将抛出 404 错误。卸载还提供了通过分别传递参数deleteIndex=truedeleteDataDir=truedeleteInstanceDir=true来删除索引、数据和核心目录的选项。

deleteInstanceDir操作也删除了它的子目录。在这种情况下,您不需要在数据目录或索引目录上调用 delete。

Solr 脚本没有为卸载核心提供任何准备。

删除核心

如果你不再需要一个核心,可以用以下方法删除。

您可以使用bin/solr脚本:

solr delete -c <corename> -p <port>

或者,您可以使用核心管理 REST API:

http://localhost:port/solr/admin/cores?action=UNLOAD&core=<corename>&deleteInstanceDir=true

有关 API 的详细信息,请参考前面的“卸载核心”一节。

核心重命名

如果要更改活动核心的名称,可以使用核心管理 API,如下所示:

http://host:port/solr/admin/cores?action=RENAME&core=old&other=new

这会将核心从旧名称重命名为新名称。

核心互换

如果您想要交换两个核心的名称,您可以使用核心管理交换 API。例如,您可能需要在活动核心和备用核心之间切换:

http://host:port/solr/admin/cores?action=SWAP&core=core1&other=core2

核心分裂

Solr 允许您将一个索引拆分成两个或多个索引。当索引变得很大时,您可能希望这样做。这通常在 SolrCloud 中进行分片。以下是分割核心的端点和支持的参数:

http://host:port/solr/admin/cores?action=SPLIT&core=sourcecore&targetCore=core1&targetCore=core2

core参数表示您想要分割的源核心。为了写入目标内核,您需要提供targetCorepath参数。如果提供了path,索引的相等子集将被写入该路径。如果提供了targetCore,那么内核必须可用。索引块将被合并到目标核心。pathtargetCore参数都是多值的。前面的示例在内核core1core2之间拆分源内核中的索引。

索引备份

失败确实会发生,所以做备份总是让你感到安全。您可以在 Solr 中通过调用ReplicationHandler,组件将数据从主实例复制到从实例来进行备份。此处提供了用于备份的 API:

http://host:port/solr/core/replication?command=backup &name=backup-name&location=backup-location

默认情况下,Solr 会在数据目录中拍摄一个带有当前时间戳的索引快照。如果提供了 location 参数,快照将在绝对目录或 Solr 实例目录的相对目录中拍摄。快照目录以提供的名称或当前时间戳作为后缀。如果您的 Solr 版本早于 5.0,请确保在调用此 API 之前,在solrconfig.xml中配置了ReplicationHandler

您还可以配置 Solr 在commitoptimize期间自动备份索引,并可以指定要维护的备份数量:

<requestHandler name="/replication" >

<lst name="master">

<str name="replicateAfter">startup</str>

<str name="replicateAfter">optimize</str>

<str name="backupAfter">commit</str>

<str name="maxNumberOfBackups">2</str>

</lst>

</requestHandler>

Solr 允许您通过使用details命令来跟踪备份操作的状态:

http://host:port/solr/core/replication?command=details

索引恢复

Solr 5.2 引入了一个用于恢复备份索引的 API。该 API 将命名备份恢复到当前核心中,恢复完成后,搜索将开始显示快照数据。用于恢复备份的 API 如下:

http://host:port/solr/core/replication?command=restore&name=<backup-name >

Solr 不允许您在一个操作正在进行时执行另一个备份或恢复操作。

Solr 允许您通过使用restorestatus命令来跟踪恢复操作的状态:

http://host:port/solr/core/replication?command=restorestatus

在 Solr 5.2 之前的版本中,您需要手动恢复索引。手动过程要求您停止 Solr,重命名/删除索引目录,将快照目录重命名为索引,然后启动 Solr。

实例管理

在本节中,您将学习管理和定制应用于 Solr 实例的特性和属性。

设置 Solr 主页

你已经知道SOLR_HOME是什么,但是直到现在我们一直在谈论默认的 Solr home。从 Solr 5.0 开始,默认的主目录是server/solr,在更早的版本中是example/solr。最好让SOLR_HOME路径不同于您的服务器路径,这样升级就不会那么痛苦。如果您希望您的 Solr 服务器为您的SOLR_HOME指向一个不同的位置,您可以使用以下方法之一:

  • –s–solr.home选项启动 Solr 脚本:$ ./solr start -s /home/ solr
  • solr.in环境文件中设置SOLR_HOME属性:SOLR_HOME=/home/solr (*nix) set SOLR_HOME=D:\playground\solr (Windows)

您可以在 Solr admin UI 中通过在 JVM args 部分查找- Dsolr.solr.home来验证SOLR_HOME的路径。或者,您可以运行solr脚本来获取状态:

$ ./solr status

当使用脚本运行 Solr 时,不能使用–Dsolr.solr.home=/path/to/home设置 home 路径,因为如果 Solr 没有找到前面提到的 home 路径,它将引用默认的SOLR_HOME

内存管理

堆内存是 Solr 运行和完成所有处理所需的空间。因为 Solr 是用 Java 编写的,所以可以传递 JVM 参数–Xms–Xmx,这两个参数分别设置内存的初始大小和最大大小。默认情况下,Solr 5.3.1 将固定堆大小设置为 512MB,这对于您的初始实验来说已经足够合理了。当您计划将 Solr 投入生产时,您应该以最佳方式设置该值。建议将–Xms设置为与–Xmx相同的值,以避免一系列的堆扩展。确定最佳大小的最佳方法是通过实验,因为如果将最大堆大小设置得太低,系统可能会抛出OutOfMemoryError,如果设置得太高,垃圾收集将需要更长的时间:

SEVERE: java.lang.OutOfMemoryError: Java heap space

如果您收到前面的错误,是时候增加堆的大小了。下面是如何设置堆内存:

  • solr.in环境文件:SOLR_JAVA_MEM="-Xms1024m -Xmx1024m"中设置SOLR_JAVA_MEM属性
  • –m选项启动 Solr。使用此选项,您可以将–Xms–Xmx设置为相同的大小:solr start –m 1g

Caution

确保将最大堆设置为仅占总内存的一部分,并为操作系统留出适当的内存。

即使在设置了堆内存之后,如果您仍然在获取OutOfMemoryError,您可以进行堆转储来确定失败的原因。您需要在 solr.in 脚本中将HeapDumpOnOutOfMemoryErrorHeapDumpPath参数添加到 GC_TUNE 属性中,如下所示:

set GC_TUNE=–XX: +HeapDumpOnOutOfMemoryError ^–XX:HeapDumpPath=/var/log/dump/

每当 Solr 抛出OutOfMemoryError时,它就会转储你的堆。如果接下来出现此错误,请转到在指定路径下创建的文件并对其进行评估。

日志管理

日志对于调试和分析至关重要。生产中的日志设置将与开发或测试中的日志设置有所不同。在本节中,您将看到如何更改日志设置。

Solr 使用 Log4j 进行日志记录,因此依赖于log4j.properties文件。Log4j 配置参见 http://logging.apache.org/log4j/1.2/manual.html

日志位置

默认情况下,Solr 在发行版server/resources目录中提供了一个预配置的log4j.properties文件,它将日志消息写到server/logs/solr.log文件中。如果您的属性文件存在于不同的位置,您可以在solr.in环境文件中设置它。

LOG4J_PROPS=<dir-path>/log4j.properties

SOLR_LOGS_DIR=<log-dir>

LOG4J_PROPS=${solr.solr.home}/path/log4j.properties - relative to $SOLR_HOME

日志级别

默认记录级别设置为INFO。您可能希望根据您的需求和环境来更改级别。您可以对日志记录级别进行永久更改,或者如果您不希望更改持续下去,可以对调试进行临时更改。

如果您想要在 Solr 重启之间保持永久设置,您可以使用以下步骤:

Set the level in log4j.properties: log4j.rootLogger=INFO, file, CONSOLE   Set the threshold in solr.xml. Details are in the upcoming “Log Implementation” section. <int name="threshold">INFO</int>

如果您想临时更改日志级别,可以使用 Solr admin UI。从 Logging/Level 选项卡中,您可以更改根本身或者任何包或者子包的级别。请记住,因为这些更改是暂时的,所以它们会在内核重新加载或 Solr 重启时丢失。

日志实现

solr.xml还允许你管理你的日志。通过对solr.xml进行更改,您可以完全禁用日志记录,或者使用完全不同的日志记录实现。您可以设置大小来指定 Solr 在将事件刷新到日志文件之前应该缓冲的事件数量。您还可以更改日志记录级别。以下是一个配置示例:

<solr>

<logging>

<str name="enabled">true</str>

<str name="class">com.ClassName</str>

<watcher>

<int name="size">50</int>

<int name="threshold">INFO</int>

</watcher>

</logging>

...

</solr>

常见例外

本节介绍了在运行 Solr 和执行管理任务时出现的一些常见异常。

OutOfMemoryError—Java 堆空间

当分配给 JVM 的内存不够时,Solr 会抛出OutOfMemoryError。您需要为 Solr 分配更多的堆空间,或者优化您的设置。有关详细信息,请参考前面的“内存管理”部分。

outofmemoryerror—permgen 允许空间

如果你觉得堆空间和 PermGen 是一样的,那你就错了。您可能有足够的堆空间用于 JVM,但是用完了 PermGen(永久生成堆)。类装入器使用 PermGen 空间来存储所有的元数据,比如类的名称、属性和方法。只有当它们的类装入器准备好进行垃圾收集时,分配给它们的空间才会被回收。只有当加载了太多的类或发生内存泄漏时,才会出现此错误。第一种解决方案是通过将 PermGen 堆作为 Java 选项传递来增加其大小:

-XX:MaxPermSize=256m

如果在增加 PermGen 大小后仍然出现该异常,则需要检查自定义组件中可能存在的漏洞,或者查找配置问题。

太多打开的文件

如果您看到这个错误,您的 Solr 实例没有问题,但是您的机器限制了打开文件的数量。您可以按如下方式解决这个问题:

If you are using a *nix machine, increase the ulimit, as shown next. For a Windows machine, you can use Process Explorer. Refer to https://technet.microsoft.com/en-us/sysinternals/bb896653.aspx for more details. ulimit -n 1000000 – *nix   Set useCompoundFile to true in solrconfig.xml. Enabling this will use fewer descriptions while indexing but will lead to performance degradation: <useCompoundFile>true</useCompoundFile> - solrconfig.xml   Use a lower mergeFactor in solrconfig.xml, which will merge fewer segments and hence fewer open files: <mergeFactor>10</mergeFactor>

UnSupportedClassVersionException

如果 JVM 在加载 Solr 类时发现它的版本号不受支持,它会抛出这个异常。如果您收到这个错误,您可能正在旧版本的 JVM 上运行 Solr。

摘要

本章首先概述了 Solr 领域中使用的概念和术语。您学习了如何启动和运行 Solr 的第一个实例,然后创建核心、索引文档和搜索结果。然后,您简短地浏览了 Solr 管理界面。有了这些,我感觉新手对 Solr 会有一个基本的了解,会开始有家的感觉。然后,您探索了管理任务,如实例和核心管理,并了解了在使用 Solr 时可能遇到的常见异常。您可以将管理部分作为一个手册,在创建核心时或在实例运行之前参考。

下一章是关于信息检索,这对于解决复杂问题和在工作中表现出色是至关重要的。这一章与其他章节关系不大,可以不按顺序查阅。如果你急着学习更多关于索引和搜索文档的知识,你可以跳过下一章,在你喜欢的时候阅读。

三、信息检索

这本书的主要焦点是向你展示如何使用 Solr 开发一个搜索引擎。然而,搜索引擎不再是一个筒仓,需要与其他工具和技术集成,以满足复杂的信息需求。其他章节介绍了 Solr 的特性、它的组件、它们的用法以及相关的例子和用例,但是在您更深入地研究实现和任何更严肃的事情之前,让我们先了解一下信息检索。

理解信息检索(IR)对于预示搜索引擎开发中更大图景的整体观点是很重要的,这一点通常被忽略了。在这一章中,你将学习到信息检索系统开发中涉及的更广泛的概念、组件和阶段。这些知识将有助于将检索问题分类成小的可管理的单元,并通过迭代开发来驯服它。这一章也涵盖了一些工具和技术,这些工具和技术可以用来给搜索引擎带来智能,并使其更上一层楼。尽管本章指出了如何将这些方面与 Solr 联系起来,但是这些概念通常可以应用于任何搜索引擎。

这一章不仅能让开发者和搜索工程师受益,也能让项目经理和任何参与搜索引擎生命周期的人受益。

本章涵盖以下主题:

  • 信息检索导论
  • 数据分类和提取
  • 文本处理
  • 倒排索引
  • 信息检索模型
  • 信息检索过程
  • 结果评估

信息检索导论

信息检索是基于特定需求来表示、存储并最终获取信息的一系列活动。基于机器的信息检索是在 20 世纪 50 年代引入的,它的需求仅限于研究团体。后来在商业产品和垂直搜索引擎中实现。

信息检索是一个广泛的概念,搜索引擎是其主要应用之一。它的其他常见应用领域是推荐系统、文档分类和聚类、过滤和问答系统。要检索的信息可以以任何来源、格式和数量提供,并且可以应用于几乎任何领域,如医疗保健、临床研究、音乐、电子商务和 web 搜索。系统的使用可以局限于律师或医生等一组人,也可以是全世界都可以使用。

信息检索系统正在成为信息访问的主要形式。随着网络搜索引擎的出现,大规模的信息检索系统已经实现,而这仅仅是个开始。在当前 Android 和 iOS 智能手机及其更智能的应用程序的时代,信息需求急剧增加,随着物联网的发展,对信息的需求将会更大,甚至更加关键。有了这些,你可以想象机器需要处理的数据的种类和数量,以支持与这种需求相关的搜索。

搜索引擎

搜索引擎是最广泛使用的信息检索系统之一。像谷歌这样的网络搜索引擎是最明显的例子之一。每个搜索引擎都有自己的挑战,但其中一些挑战更多地与信息检索有关,而不是搜索引擎。对相关文档进行适当的排序和评估排序算法的有效性可以被认为是 IR 关注的问题,而性能和可伸缩性是搜索引擎关注的问题。

搜索引擎可以大致分为几类,每一类在某种程度上都有相似的信息需求。以下是更广泛的类别列表:

  • Web 搜索:这种方法在万维网上爬行,从 HTML 标签中提取内容,并对信息进行索引以使其可搜索。一些引擎还抓取图像和其他相关文件,并在索引之前处理文本以获取其他有趣的信息和链接。DuckDuckGo 是一个使用 Solr 开发的 web 搜索引擎的典型例子。
  • 垂直搜索:垂直搜索针对特定的领域、信息领域或行业,如医疗保健或金融。这些信息通常存在于主数据库或数据源中,如 Word 文档或 PDF 文件。这些类型的搜索通常是为满足特定需求而开发的。
  • 桌面搜索:这是设计来索引用户电脑中的文件,并使其可搜索。一些搜索引擎还会将文件内容和元数据一起编入索引,以使其可被搜索。麦克 OS X 的聚光灯就是一个典型的例子。
  • 其他:信息检索不再局限于文本,而是广泛用于搜索图像、音频指纹和语音识别。

任何信息检索系统的目标都是将数据转化为满足用户需求的可操作信息。在搜索引擎的情况下,信息属于为搜索请求而检索的相关文档。图 3-1 描述了将数据转化为信息的搜索系统中的组件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-1。

A search system

在接下来的部分中,您将了解重要的信息检索组件以及任何搜索引擎开发中通常遵循的过程。

数据及其分类

数据以不同的形式创建,以满足不同的需求——有些供人类使用,如博客和帖子,有些供机器使用,如表格或元数据中的数据。这些数据也有各种格式,如 Word 或 PDF,并保存在不同的数据源中。

根据数据的性质及其格式,系统需要执行不同的内容提取任务,这些任务可以是简单的数据库查询,也可以是复杂的过程,例如从图像中提取数据。

在学习更多关于内容提取的知识之前,您首先需要理解数据类别。要索引的数据可以分为三类:结构化、非结构化和半结构化。接下来将描述每个类别。

结构化的

结构化数据是一条符合预定义结构的信息。信息被组织成易于管理的单元,以便有效地存储、处理和检索。与非结构化数据相比,结构化数据更容易组织、存储和查询。如果关系数据库或表是信息的主要来源,那么数据通常是结构化的。结构化数据的一个简单例子是 web 表单或 Excel 表。这些值在逻辑上是分开的,每个值都可以索引到不同的字段。

结构化数据更容易接收,因为它不需要高度复杂的文本解析,检索技术和相关性规则的应用也更易于管理和有效。此外,它还具有更好的互操作性,方便其他机器使用。你周围的一切都会产生数据:你的相机、手机、GPS 设备和可穿戴设备。他们的数据越结构化,消费就越容易。

无社会组织的

反过来,非结构化数据不能被正式定义为可管理的单元,并且包含机器无法区分的自由格式文本块。这些块很难以编程方式解释,或识别相关联的上下文和概念,并且可能包含歧义和垃圾。它们可以包含基于域的各种信息(如人员、位置、日期、号码、疾病和症状)。非结构化数据的例子包括文本文件、pdf、Word 文档、书籍、日志和电子邮件。

我们周围的大多数文档都是非结构化的,因此对其进行处理和分析以找到其文本中的模式非常重要,这样机器就可以提取实体,解释语义,并过滤掉无关的数据。如果非结构化内容有关联的元数据,这可能是结构化信息的另一个有价值的来源。

值得注意的是,由于自然语言语法,即使是非结构化数据也有一些结构,以章节、段落和句子的形式存在。可以对该文本应用高级处理管道,以提取大量有趣的信息,并从中构建一些结构。看看维基百科:这是一种非结构化的数据形式,也有一些相关的结构。

非结构化文本可以通过使用人工智能等机器处理技术来结构化。您可以使用开源工具(例如,Apache UIMA)构建一个管道来注释文本流中的有用信息。Solr 通过处理器和过滤器为 UIMA 管道提供第一手支持。Apache Stanbol 是另一个允许您执行语义内容管理的项目。如果这对你不起作用,可以通过使用亚马逊机械土耳其人( www.mturk.com/mturk/welcome )等平台手工制作或众包结构。

半结构化的

半结构化数据是第三种形式,介于结构化和非结构化之间。这种数据具有某种结构,这种结构为互操作性提供了便利,但不能受模式的约束。没有规定结构的数量;数量取决于需要。XML 格式的文件是半结构化数据的典型例子。您可能需要执行一些类似于处理非结构化文本的处理,以便从中提取更有意义的信息,但是这个过程相对来说更容易。

内容提取

上下文抽取是信息流的第一步。在这个过程中,您从数据源中提取内容,并将其转换为可索引的文档。在 Solr 中,这个过程可以在 it 内部执行,也可以在索引文档的客户端应用程序中执行。你会在第五章的中看到 Solr 提供的文档索引选项的更多细节。

让我们假设正在为研究人员和学者开发一个搜索引擎。在这种情况下,大多数内容通常是非结构化的,并以 PDF、DOC 和 PPT 格式提供。这种非结构化数据的提取需要相当复杂的处理。要索引这些文档,首先需要检测内容类型,然后提取文本进行索引。解析器可用于从不同文件格式的内容中提取文本。表 3-1 提供了可用于文本处理的常见文件格式和开源工具的列表。

表 3-1。

File Formats and Open Source Tools

| 文件格式 | 开源工具 | | --- | --- | | 便携文档格式 | Apache 然后 Apache PDFBox | | 微软 Word/Excel/PowerPoint | Apache,然后 Apache OpenOffice | | 超文本标记语言 | jsoup HTMLCleaner | | 可扩展置标语言 | Apache[Xerces](http://java-source.net/open-source/xml-parsers/xerces)Java Architecture for XML Binding(JAXB)Dom4j Solr data importhandler 提供了许多其他的 SAX 和 Dom 解析器 | | 光学字符识别 | 宇宙魔方 | | 地理空间的 | 地理空间数据抽象库 | | 电子邮件 | JavaMail API | | 网络爬行 | 阿帕奇努奇 |

提取过程因数据源而异。如果数据在数据库中可用,它通常会是规范化的形式,因此应该在索引前展平。Solr 提供了定义反规范化过程的工具,或者如果您正在使用外部索引过程,您可以在该应用程序中完成。你将在第五章中通过使用 DataImportHandler Solr 模块学习如何从数据库中索引数据。

一个名为 Apache Tika 的开源项目为处理多种格式的文件提供了一个框架。它支持自动检测内容类型,并允许提取内容以及相关的元数据。Tika 并不自己完成所有的检测和提取工作;相反,它通过其接口包装了 Apache POI 和 Apache PDFBox 等库,以提供一种方便的提取方法。Tika 支持对各种文件格式的内容进行解析,例如包格式(.tar.jar.zip)、文本文档(.doc.xml.ppt.pdf.html)、图像(.jpeg.png.bmp)、音频(.mp3.wav)等等。

Tika 解析器通过隐藏文件格式的复杂性和调用单独的解析库来简化您的任务。它为客户端应用程序提取内容和元数据提供了一个简单而强大的机制。它为所有提取任务提供了一个单一的 API,使您不必为不同的提取需求学习和实现不同的 API。

Solr 提供了一个名为 Solr Content Extraction Library(Cell)的框架,它使用 Apache Tika 来暴露ExtractingRequestHandler,这是一个用于从不同格式的文件中提取内容并将其索引到各自的 Solr 字段的处理程序。第五章提供了使用 Solr Cell 提取内容的更多细节。

文本处理

如前一节所述,从数据库接收的原始文档或从二进制文档中提取的文本需要在被索引之前进行处理。处理任务可以是文本的清理、规范化、丰富或聚合。这些过程通常链接在一起以实现所需的输出,管道取决于您的处理需求,这取决于数据的性质和质量以及所需的输出。

在 Solr 中,文本处理可以分两步执行,由分析过程和更新请求处理器执行。这些步骤的目的是满足各种文本处理需求。分析过程满足单个字段级标记化和分析的需求,而更新请求处理器则满足其他文本处理需求,其作用范围是整个文档。更新请求处理器也称为预处理器或文档处理器。

不同系统之间的文本处理各不相同,在索引和搜索时也各不相同。例如,用户查询可能不需要清理或最少清理。接下来讨论各种文本处理类别。

清洗和正常化

并不是所有的数据都是重要的,一些重要的数据在被索引之前需要进行规范化和转换。常见的清理和规范化任务包括删除标点符号、删除停用词、小写、转换为最接近的 ASCII 字符和词干。这些是在任何搜索引擎中都应该执行的一些最基本的任务,并且对于匹配是至关重要的。

改进

文本充实是分析和挖掘内容的阶段,以找到充实、注释、实体提取的模式,并应用各种智能使内容更可用、更可理解和更相关。应用于文本的丰富取决于您的检索需求和您所担心的扩展深度。此外,建议在您的系统在清理和规范化方面表现合理,并检索相关的基于关键字的匹配之后,再尝试丰富。以下是可以应用于文本的一些丰富内容:

  • 实体提取:如果要索引的内容是非结构化的,或者任何字段都是全文的,那么您可能希望提取诸如人员、组织和位置之类的实体,并对内容进行注释。假设您正在索引来自临床试验的文本;您可以从文本中提取疾病、症状和解剖结构等实体,这样索引就更加结构化。然后,如果检测到用户查询是针对特定疾病或解剖结构的,则可以适当地对文档进行排序。
  • 词性标注:任何语言中的单词都可以根据语言的语法分类为预定义的词性(如名词或动词)。这些词类可用于形成短语并识别文本中的重要概念,这些概念可被提升以适当地排列文档。
  • 叙词表:叙词表(复数:叙词表)是一个受控词汇表,通常包含一个单词及其相关单词的列表。相关单词是语义元数据,例如同义词、反义词、更宽泛和更狭窄的概念、部分术语等等,并且支持的元数据列表可以在同义词词典之间变化。WordNet 是一个通用词典,也包含术语注释(定义)。这些词表由定期更新词汇表的社区维护。词汇表可以是通用的(如在 WordNet 中),也可以是特定的(如医学主题标题或 MeSH,它包含更深层次的术语列表,广泛用于医学科学领域)。你选择的词表取决于你的需要,你甚至可以选择使用多个词表。你可以在 http://wordnetweb.princeton.edu/perl/webwn 试试 WordNet 的现场演示。
  • 本体:本体是特定领域中概念及其关系的正式表示,例如更宽和更窄的概念。值得注意的是,一些叙词表也包含关系,但它们是非正式的,可以基于语言词典中的用法。此外,叙词表可以是通用的,而本体则局限于一个领域。

这只是冰山一角,也是一个活跃的研究领域。您所做的处理可以是高效检索和排列文档所需的任何事情。例如,如果文本包含评论,您可能想要进行情感分析;如果您正在索引新闻、期刊或法庭诉讼,您可能想要进行文本摘要。

文本处理不一定只在索引时应用。它还可以应用于用户查询,特别是查询扩展、概念识别和意图挖掘等场景。问答是一个典型的例子,用户查询通过一个管道,如查询类型分类。

表 3-2 列出了常见的预处理类型以及免费提供的工具和资源。

表 3-2。

Tools and Resources for Processing of Text

| 预处理 | 工具/资源 | | --- | --- | | 自然语言处理 | Apache OpenNLP 斯坦福 CoreNLP | | 使聚集 | 胡萝卜 2 阿帕奇驯象人槌 Weka | | 分类 | 阿帕奇驯象员马利特·韦卡 | | 受控词汇 | 国会图书馆主题词(LCSH)医学主题词(MeSH) | | 文本处理框架 | 阿帕奇 UIMA 门阿帕奇斯坦波尔阿帕奇 cTAKES(临床研究) | | 知识库 | DBpedia YAGO |

元数据生成

元数据是关于数据的数据,是访问文档和确定文档相关性的有用信息源。结构化元数据允许更容易的互操作性、交换和机器对数据的处理。

许多系统会自动为内容提供元数据,您无需担心如何生成元数据。网页具有以元标签形式关联的元数据,元标签包含关键字和页面内容的描述,并且被搜索引擎用于主题识别。如果您对摄影感兴趣,您可能知道您的相机会为您点按的每个图像生成 EXIF(可交换图像文件)格式的元数据,其中包括相机和镜头的详细信息、曝光信息和版权。最近的相机和移动电话也通过使用内置的 GPS 接收器以 EXIF 格式存储位置信息。在图 3-2 中,可以看到 JPEG 图像的元数据。想象一下,通过使用这些元数据,您可以根据提供的空间、相机或其他信息来调整文档的相关性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-2。

Metadata of a JPEG file

元数据模式标准已经由 Dublin Core 等社区定义,其中包含描述 web 和物理资源的术语。

如果元数据不是自动可用的,您可能希望手工制作它或者从内容提供商那里获得它。此外,还有半自动的方式来产生它。我们不会涉及这些,因为它们超出了本书的范围。

如果元数据被集成到包含内容的文件中,那么可以通过使用 Apache Tika 在 Solr 中使用它。您将在第五章中看到相关步骤。

倒排索引

从数据源提取的数据应该建立索引,以便快速准确地检索。如果您一直想知道为什么向 Solr 添加文档的过程通常被称为索引,那么倒排索引就是答案。Solr 内部使用 Lucene,当您添加文档时,它会创建一个倒排索引来使信息可搜索。

倒排索引是典型搜索引擎中的主要数据结构,它维护所有唯一术语的字典以及它们出现的所有文档的映射。每个术语都是一个键,它的值是一个发布列表,即该术语出现的文档列表。

Lucene 数据结构被称为倒排索引,因为遍历是向后的(或倒排的):从术语到文档,而不是像前向索引那样从文档到术语。倒排索引类似于本书末尾的索引,包含单词列表和单词出现的相应页面。在 Lucene 的上下文中,单词是术语的同义词,页面是文档的同义词。相比之下,前向索引类似于本书开头的目录。

倒排索引的方法是以术语为中心,而不是像前向索引那样以文档为中心。对于查询中的每个术语,面向文档的数据结构必须顺序扫描所有文档的术语,而倒排索引在索引中查找术语,并从发布列表中找到匹配的文档。这种方法提供了快速的全文搜索和更好的性能。

图 3-3 提供了倒排索引表示的简化视图。您可以看到,当一个文档被索引时,术语被作为关键字添加,它的文档映射在一个发布列表中。当用户启动查询时,倒排索引会提供关于所有匹配文档的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-3。

Lucene inverted index

发布列表还包含附加信息,如文档中的术语频率、索引时间提升和有效负载,这提供了便利和更快的搜索。

Note

用户查询和索引需要经过大量复杂的处理,为了简单起见,图 3-3 对这些处理进行了抽象。

检索模型

要搜索相关文档,您需要一个检索模型。检索模型是通过使用数学概念来定义检索过程的框架。它提供了确定与用户需求相关的文档的蓝图,以及一个文档为什么比另一个文档排序更高的推理。您选择的模型在很大程度上取决于您的信息检索需求。每个模型使用不同的方法来确定查询和文档之间的相似性。该模型甚至可以像返回 0 或 1 作为值的布尔模型一样简单。此外,系统的实现可以是解决实际用例的模型的变体或扩展。在第八章中,您将看到 Lucene 如何修改向量空间模型,这将在本节稍后讨论。

本节涵盖了搜索引擎通常使用的信息检索模型。

布尔模型

信息检索的布尔模型是基于集合论和布尔代数的简单模型。顾名思义,它将文档分为真或假(文档匹配或不匹配)。

让我们用 Solr 的说法来理解这一点。建立索引时,从文档中提取术语,并创建索引。因此,我们可以将文档视为一组术语。在搜索时,解析用户查询以确定术语并形成布尔表达式。用户查询可以包含运算符 AND、OR 或 NOT,它们在布尔表达式中具有特殊的含义,分别用于标识合取、联合或析取。Solr 还使用+和-符号将术语指定为“必须发生”或“不得发生”

所有满足表达式的文档都被认为是匹配的,其他的都被丢弃。以下是为指定的布尔表达式匹配和不匹配文档的示例:

Query:

(singer AND dancer) OR actor

Match:

"He started his career as a dancer but he is also a singer"

"Mr. Mark is a famous actor"

No Match:

"Who is the singer of this song?"

"He is an amateur dancer."

这种模型的挑战在于,它认为所有术语都是同等相关的,并且没有提供任何对文档进行排序的规定。因此,您需要一个更复杂的模型来根据相关性对文档进行排序。另一个挑战是将布尔查询转换成布尔表达式。

向量空间模型

布尔模型带你走了一半。对于用户查询,它确定匹配的文档,但是您可能还想知道匹配文档的相关程度。布尔模型在一个消耗成百上千个结果的系统中是可以接受的。但是如果最终用户是人类呢?在谷歌搜索时,你希望最佳匹配出现在第一页。当对文档进行排序时,您知道前几个结果是最相关的,并且您几乎不关心遍历许多结果页面后出现的结果。

向量空间模型(VSM)是一种检索模型,可用于根据用户查询对索引文档进行排序。查询响应包含文档以及分配给它的分数,分数表示与用户查询的相似程度。具有最高分数的文档被认为是最佳匹配。

向量空间模型通过高维空间中的术语权重向量来表示每个文档和查询,并基于查询和文档之间的角度来计算得分。图 3-4 描绘了一个 N 维空间,其中文档用实线表示,查询用强实线表示。VSM 使用下列步骤进行相关性排名:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-4。

Vector space model While indexing, represent each document as a weighted vector of term frequency and inverse document frequency   While searching, represent the query as a weighted TF-IDF vector   Compute the cosine similarity score between the query vector and each document vector   Rank documents with respect to the query   Return the matching top N rows in the response

默认的 Lucene 评分算法使用布尔模型和向量空间模型的组合来查找相关文档。由布尔模型批准的文档由向量空间模型排序。因此,Lucene 只为满足布尔查询的文档计算相似度。此外,它使用余弦相似性的修改形式来计算相关性排名。第八章详细介绍了 Lucene 评分。

这个模型非常适合自由文本查询。这个模型的局限性在于它忽略了术语之间的关系,并假设它们是独立的。它认为文本是一个单词包。

概率模型

概率模型通过估计文档相对于查询的相关性概率来对文档进行排序。评估的过程是至关重要的,这也是实现彼此不同的地方。这个模型基于这样一个概念,即对于一个查询,每个文档可以被分类为相关或不相关:P(R|D)或 P(NR|D)。

语言模型

语言模型是概率模型的一个分支,它根据文档生成查询词的概率对文档进行排序。它通常使用最大似然估计来估计概率。评估过程大致分为三个步骤:

Estimate the language model for each document in the corpus and sample them   Calculate the probability of observing the query terms in the sample   Rank the documents in the order of probability

因为每个文档都是用于估计的样本,所以它可能会稀疏,因此应该应用平滑来解决这个问题。语言模型可以是一元或多元的。更常见的 Unigram 模型分割了不同术语的概率,忽略了上下文。N-gram 模型估计每一项的概率,考虑先前上下文的 N-1 项。

信息检索过程

在前面的章节中,您了解了信息检索中的关键概念。现在,这个故事好的一面是 Solr 使您不必担心任何与倒排索引以及检索模型的实现细节有关的事情。Lucene 提供的默认模型非常适合全文搜索和大多数检索需求。如果您想集成任何其他检索模型,您可以扩展现有的 Java 类。

信息检索是一门实验性很强的学科,建议遵循检索过程的迭代开发和改进。图 3-5 描述了信息检索过程的各个阶段,这些阶段最终会导致更好的搜索引擎的开发。在实践中,多个阶段可以同时执行,或者在同一迭代中重复多次。Solr 的分层架构以及可配置和可插拔的组件提供了所需的便利性和灵活性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-5。

Stages in information retrieval process

计划

规划是一项极其重要的任务,尤其是在信息检索领域,这是一个耗时的过程。在开始设计模式和定义搜索特性之前,需要考虑许多因素和策略。你可能会觉得有些因素是不相关的,所以可能会忽略它们,但这可能会极大地影响用户体验和转化率。以下是您在开始开发之前应该考虑的一些因素。

了解垂直

如果你正在开发一个垂直搜索引擎,你的首要任务是理解问题陈述,然后了解领域。大多数领域都有自己独特的功能需求,并带来自己的挑战。例如,在地理搜索中,位置和邻近性对于计算文档的相关性至关重要,而在生物医学领域,跨多个资源的信息链接变得非常重要。

了解最终用户

最终用户是最终使用搜索引擎的人,了解他的真实需求很重要。除了检索相关文档,易用性、便利性和导航能力也应该是优先考虑的。用户通常遵循基于域或地区的模式。例如,用户可能对最相关的结果感兴趣,例如当你在 Google 中搜索时,而其他人可能需要所有匹配的结果,例如法律从业者对所有匹配的案件感兴趣。在音乐发现网站中,用户期望相关文档出现在结果集中的顶部;相比之下,在服装电子商务网站中,用户通常浏览数百个匹配的文档。理解系统的核心需求,并在初始迭代中努力解决它。

一些用户需求可能是具体的和主观的,通常难以执行和评估,优先级较低。在这种情况下,文档排名可能与一个用户高度相关,但与另一个用户无关。这些问题可以通过使用诸如用户特征分析和结果个性化等技术来解决。

了解内容

所有的数据都不重要,只有一部分数据满足了用户的信息需求。不需要的数据应该被丢弃,以避免任何垃圾进入系统。此外,一些数据需要丰富,以满足用户的检索需求。在规划阶段,理解数据是至关重要的,这样就可以应用适当的工具和技术进行提取、清理、丰富和其他所需的文本处理。要搜索的内容可能取决于三个维度,在大数据世界中通常称为 3v:

  • 数量:一些系统需要处理大量的数据,比如在网络搜索或社交网络中。脸书管理着一个超过 300 的数据仓库。搜索引擎应该是可扩展的,以支持高容量,这就是 SolrCloud 的用途。如果您正在编写定制组件,请从 SolrCloud 的角度考虑,并确保您的特性是云就绪的。
  • 多样性:多样性是指内容的不同形式。要索引的内容可以是结构化的,也可以是非结构化的。为了创建索引,可以从多个来源提取或聚合数据。假设您正在构建一个类似于 IMDB 的电影搜索引擎。这些内容可能来自许多来源,例如主数据源中的记录、内容提供商提供的元数据、第三方应用程序的评论以及 Twitter 或 YouTube 等社交媒体的趋势和流行信息。所有这些内容整合在一起将形成识别电影相关性的基础。
  • 速度:如果搜索引擎需要处理接近实时的查询,数据处理的速度很重要。Twitter 等公司每天处理超过 5 亿条推文,需要实时传输数据。在这种情况下,批处理不是一种选择。
了解媒介

媒介是指用户用来查询搜索引擎的设备。这一点通常被忽略,但在信息检索中却很重要。在手机上打字很困难,所以用户很可能会写一些包含重要关键字的简短查询,而且可能不是用自然语言。用户可以优选地使用单词的简短形式。诸如自动完成之类的功能是这类设备必须具备的。使用移动电话的一个好处是,它可以提供用户的额外信息,比如她的当前位置,这些信息可以用来提高本地化结果的排名。在网络上,搜索体验应该是不同的。你可以为诸如建议、诸如此类和推荐等功能提供大量空间。最重要的是,用户倾向于在网上更自然地书写。

不应该忽略搜索所使用的媒介,并且应该相应地规划你所提供的功能。

执行

在此步骤中,您将执行前面步骤中计划的信息检索任务。在得出结论之前,您需要通过多次实验和研究来执行文本处理和检索技术。在满足检索需求的同时,对于一个搜索引擎来说,其他重要的生产准备因素也不应该被忽视。例如,如果您的业务需要高度分布式和可伸缩的系统,请确保 SolrCloud 支持该功能。

评价

您学习了建立和改进搜索系统的信息检索模型和文本处理技术。检索模型为 Lucene 评分奠定了基础,Lucene 评分根据与用户查询的相似性对文档进行排序,文本处理策略在文档的可查找性方面起着关键作用。每当您调整文档的分数时,例如通过应用 boost,或者在文本处理中执行任何更改,您通常会寻求以下一些问题的答案:

  • 我的搜索结果是否显示了最相关的文档?
  • 是否遗漏了任何高度相关的文件?
  • 结果集中是否包含不良或不相关的文档?
  • 我的结果在这次迭代中有所改进吗,我如何度量改进?

有时你可能会发现系统遗漏了一些高度相关的文档,并调整引擎来提高它们的排名。这种活动反过来会影响文档与其他查询的相关性,这可能会被忽视,并可能在产品生命周期的后期被发现。因此,在执行阶段之后,检查和评估搜索结果变得至关重要。在本节中,您将了解文档的各种状态以及适用于信息检索的评估概念。

当您执行搜索时,匹配的文档将具有表 3-3 中提到的四种状态中的任何一种。表中的第一行表示理想情况下的结果状态(无论文档是否被正确识别)。表中的第一列代表您的系统,以及文档是否匹配用户查询。

表 3-3。

Contingency Table (2×2)

|   | 辨认 | 被拒绝 | | --- | --- | --- | | 相配的 | 正确肯定 | 假阳性 | | 不匹配 | 正确否定 | 假阴性 |

列联表中所有值的说明如下。

正确肯定

在这个场景中,为用户查询识别正确的文档。假设用户查询是“cancer”,应用程序检索匹配“cancer”的文档。这是一个真正积极的例子。

假阳性

在这种情况下,文档被错误地识别为匹配。例如,查询“癌症疾病”会得到一个关于癌症的结果,它指的是螃蟹或星座癌症。这种情况通常是由于低效的文本清理(例如,遗漏的停用词删除)而发生的,这会导致不相关的文档被识别为匹配。记住“垃圾进,垃圾出”这句话。这种情况也被称为假警报或 I 型错误。

正确否定

在这种情况下,文档被正确拒绝。例如,查询“癌症疾病”不会得到与螃蟹或星座相关的癌症结果。大多数文档应该属于这一类别,真正的否定对于确定检索结果的质量没有作用。

假阴性

在这种情况下,应该是响应的一部分的文档被错误地拒绝了。例如,如果系统被期望带来语义相关的结果,而与“良性肿瘤”相关的文档在用户查询“癌症疾病”时被遗漏,那么这就是假阳性的情况。这种情况通常是由于文档的不正确的规范化和丰富化而发生的,在这种情况下,即使添加一个标点符号或缺少小写字母也可能拒绝文档。这种类型的错误可以归类为第二类错误。

假阳性和假阴性的情况是不希望的,应该避免并减少到最低限度。误报场景导致结果分页,并影响用户体验和对系统的信心。如果搜索引擎是通过短消息服务这样的媒介访问的,假阳性匹配是完全不可接受的。假阴性场景甚至会变得更糟,直接影响业务;在电子商务网站上寻找产品的用户将无法发现该产品,即使该产品可从卖方处获得。

评估指标

您需要度量来确定检索的结果是否符合用户的期望。此外,您可能有兴趣将现有系统的结果与新的和改进的系统的结果进行比较。精确度和召回率是有助于评估结果的主要指标。精确度是另一个度量标准,但由于其不切实际的计算,通常会被避免。

准确

准确性通过考虑真阳性和真阴性(系统正确识别或拒绝文档的程度)来衡量有效性。下面是评估的算法:

)

其中

TP 是真阳性,

TN 是真负值,

FP 是假阳性,

FN 是假阴性

有趣的是,准确性从来没有被用来评估一个信息检索系统,因为使用它作为衡量标准可能会完全错误,因为它会考虑相关和不相关的文档。假设索引中有 100 个文档,对于一个查询,语料库只包含 10 个相关匹配。假设该系统是最差的系统之一,对于该查询,它检索 10 个文档,所有这些文档碰巧都不相关。以下说明了 accuracy 如何评估结果:

TP = 0 (no relevant document retrieved)

TN = 80 (out of 90 irrelevent documents, 80 were correctly rejected)

FP = 10 (10 irrelevant documents are incorrectly retrieved)

FN = 10 (10 relevant document incorrectly rejected)

)

从这个例子中,您可以看出,即使系统检索到 0 个相关结果,您仍然可以获得 80%的准确率。因此,通常避免将准确性作为衡量标准,而考虑精确度和召回率。

精确度和召回率

查准率和查全率是评价信息检索系统有效性的两个重要指标。Precision 是检索到的相关文档的分数,recall 是检索到的相关文档的分数。精确度和召回率可以使用以下公式计算:

)

)

假设您的索引有 20 个与音乐相关的文档和 10 个与电影相关的文档。现在,与音乐相关的查询可能返回 10 个文档,其中 5 个与音乐相关,5 个与电影相关。系统的精度将是 5/10 = 1/2,即 50%。召回率将是 5/20 = 1/4,即 25%。

简而言之,我们可以说精确度是质量的衡量标准,而召回率是数量的衡量标准。因此,高召回率意味着算法返回了大部分相关结果,而高精度意味着算法返回了比不相关结果更多的相关结果。

计算精度更容易,因为您需要从检索到的文档中识别相关的文档。假设您在 Solr 中查询 10 个文档,指定rows=10。在这种情况下,您甚至可以手动遍历文档来识别相关的文档。因为召回工作在相关文档上,这在语料库的所有文档中是很难识别的。它的计数可能非常大,手动遍历将是一个挑战。

根据你要解决的问题,这两种方法中的一种可能对你更重要。例如,在法律领域,您可能对检索所有相关文档感兴趣,因此高召回率会让您更感兴趣。如果您正在构建一个 web 搜索引擎,您会对检索最相关的文档感兴趣,因此您会对高精度感兴趣。通常,这两种方法一起使用来达到一种折衷,因为信息检索的一般目标是检索几个相关的文档并将最相关的文档放在最上面。

f-测度

F-measure 可用作系统的单一测量,因为它结合了精确度和召回率来计算结果。它计算精度和召回率的调和平均值如下:

)

摘要

这一章主要讲述与信息检索相关的概念和方法。您了解了信息检索模型和评估搜索结果有效性的方法。您还了解了可以用来开发更有效的搜索引擎的工具和资源。

下一章将介绍模式设计,接下来的章节将介绍文档索引和结果搜索。第十一章包含了与本章讨论的文本处理概念相关的例子。

四、模式设计和文本分析

Solr 中的搜索引擎开发最初遵循四个连续的步骤:Solr 设置、模式设计、索引文档和搜索结果。模式设计是定义数据结构的过程,是索引和搜索过程的先决条件。

本章包括定义字段、指定类型和其他功能。

文本分析在信息检索中的作用至关重要。是文本分析过程决定了术语(最小的信息,用于文档的匹配和评分)。本章涵盖了文本分析过程,包括分析器做什么,Solr 中可用的各种分析器/记号赋予器,以及将它们链接在一起。

在本章中,你将学习在无模式模式下运行 Solr,使用托管模式,以及使用 REST APIs。

本章分为以下几节:

  • 模式设计
  • 文本分析
  • 无模式化
  • 用于管理模式的 REST API
  • solrconfig.xml 文件
  • 常见问题

模式设计

模式设计是构建有效搜索引擎的最基本步骤之一。它是定义数据结构并应用文本分析来控制匹配行为的过程。

在定义模式之前,您应该理解您试图解决的问题,并准备好您的策略。你应该能够回答几个问题,包括这些:你用 Solr 做什么?你会提供什么样的搜索体验?数据的哪一部分应该是可搜索的?要检索什么信息?

Solr 通常用于索引非规范化数据。如果您的数据是规范化的,您可能希望在建立索引之前将其展平并定义结构。如果完全反规范化是一个挑战,Solr 允许您连接索引。但是 Solr 中的连接不同于数据库连接,它有自己的局限性。Solr 还支持索引层次数据,具有父子关系。第七章介绍了这些高级搜索功能。

所有的搜索引擎都是独一无二的,要么是因为领域、数据的性质,要么是其他因素。可以对全文或元数据进行搜索。此外,Solr 不仅仅局限于作为一个文本搜索引擎,它还被广泛用作 NoSQL 数据库和执行分析;已经看到了许多新的创新用例。例如,一个名为 Lucene Image Retrieval (LIRE)的项目使用 Solr 进行图像搜索。

如果您使用 Solr 作为 NoSQL 数据存储,或者想要快速开始,或者没有完整的数据可见性,或者正在使用动态的数据结构,您可以选择无模式,让 Solr 自动检测fieldType和索引文档。从 5.0 版开始,Solr 默认以无模式模式创建一个内核。在本章的最后你会学到更多关于这个主题的知识。

文档

在 Solr 中,每个搜索结果对应一个文档。这个基本的信息单元类似于数据库表中的记录。开发搜索引擎时,模式设计的第一步是确定搜索引擎的文档内容。相同的数据可以用不同的方式表示和索引,文档的定义也可以不同,这取决于您对引擎及其用途的预期结果。

比如印度电影业,大部分电影都有五到十首歌。如果你正在构建一个电影搜索引擎,每部电影就是一个文档。每个文档包含多首歌曲,索引为一个multiValued字段。相比之下,如果您正在构建一个音乐搜索引擎,每首歌曲的名称将是一个唯一的文档,而电影名称在这些文档中是多余的。

类似地,如果您正在开发一个在线书店,每本书或期刊都将是一个文档,其中包含 ISBN、书名、作者和出版商等信息。但是如果你正在为研究人员开发一个搜索引擎,也许这本书或杂志的每一章、主题或文章都可以是一个文档。

schema.xml 文件

schema.xml文件定义了文档结构及其包含的字段。向 Solr 添加数据或查询结果时会用到这些字段。在下一节中,您将了解 Solr 中的字段。

在 Solr 中,schema.xmlsolrconfig.xml是两个主要的配置文件。通常你会用它们来修改你的搜索策略和增强用户体验。这些文件可以位于$SOLR_HOME内核的conf目录中,也可以位于指定的配置集中。

schema.xml文件有明确的目的,而solrconfig.xml文件用于所有其他配置。以下是schema.xml支持的配置列表:

  • 定义field type s 和文本分析,如果支持的话
  • 定义每个字段及其适用的属性
  • 定义动态字段
  • 指定评分算法
  • 将数据从一个字段复制到另一个字段
  • 指定其他与字段相关的定义,例如唯一字段或默认字段的标识

Note

本章末尾讨论了solrconfig.xml文件。

正如文件扩展名schema.xml所述,配置是以 XML 格式指定的,其中<schema>是根元素。该元素支持两个属性:nameversionname属性为可用于显示的模式指定一个名称。属性声明支持的语法和行为的版本号。Solr 5.3.1 的最新版本是 1.5。以下是一个样本schema.xml文件:

<schema name="example" version="1.5">

<field name="title" type="string" indexed="true" stored="true"/>

<field name="isbn" type="string" indexed="true" stored="true"/>

..

<fieldType name="string" class="solr.StrField" sortMissingLast="true"/>

<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>

..

</schema>

应该重新加载核心以反映该文件中的任何更改。如果在索引时处理过程中进行了任何更改,那么在重新加载核心之后,应该重新索引文档。

菲尔茨

文档中的每一部分信息(例如,ISBN、书名、作者和出版商)都是一个字段,类似于数据库表中的一列。以下是schema.xml中一个字段的示例定义:

<field name="title" type="string" indexed="true" stored="true"/>

<field name="isbn" type="string" indexed="true" stored="true"/>

..

Solr 支持一组属性来配置字段的行为。在这些属性中,type定义了fieldType,它类似于 Java 的数据类型,但功能更强大。它将字段链接到索引和查询时要对其数据执行的分析链。

Note

Solr 的早期版本要求在<fields>元素中定义字段。最近的版本已经简化了结构,您可以直接在<schema>元素中指定字段。

字段属性

以下是字段支持的属性的描述。您还可以在field元素中定义fieldType的属性,这将覆盖在fieldType元素中指定的值。

名字

这个强制参数为字段指定一个名称,在对其执行任何操作(如索引、查询和突出显示)时都会引用该名称。

您只能使用字母字符、数字和下划线来命名字段。名称区分大小写。以下划线开头和结尾的名称(如_version__root_)被保留。

命名字段没有其他规范,但是建议遵循一个约定—例如,保持所有单词小写并用下划线分隔,或者遵循 camel 大小写以提高可读性。

类型

该强制参数指定了fieldType的名称。您将在下一节了解更多关于fieldType的内容。

系统默认值

此参数指定为文档编制索引时未提供值的字段的默认值。

当您希望自动索引字段的值而不是在每个文档中指定它时,此参数也很有用。一个经典的例子是索引时间戳,它指示文档被添加到 Solr 的时间。以下是用于索引时间戳的字段定义示例:

<field name="timestamp" type="date" indexed="true" stored="true"``default="NOW"

在这个例子中,type="date"属性将fieldType指定为TrieDateField,并且NOW被提供为default属性的值,该值指定当前时间戳。

该示例还包含indexedstored属性,它们是fieldType的属性,已经在我们的字段定义中被覆盖。有些fieldType参数通常会被字段覆盖,这种情况经常发生,以至于你可能会觉得它们是field而不是fieldType的属性。

保留字段名称

Solr 保留了以下划线开头和结尾的字段名,用于特殊目的。以下是一些保留字段名称:

  • _version_ : Solr 使用该字段进行事务日志记录,以支持 SolrCloud 中文档的乐观锁定和实时 get 操作。
  • _root_:支持嵌套文档(层次数据)需要该字段。它标识嵌套文档块中的根文档。
  • _text_:该字段为预定义的总括字段,支持无模式下的单字段搜索。

螺纹类型

fieldType元素决定了一个字段可以保存的值的类型、应该如何解释该值、可以对其执行的操作以及该字段将经历的文本分析。

字段类型的重要性在 Solr 中至关重要。字段类型和指定的分析链决定了在索引和查询文档时要应用的文本分析管道。匹配策略可以表示为字段定义中的一系列分析器、记号赋予器和记号过滤器。每当您想要调整查询词的搜索以匹配或不匹配索引词时,您通常会更改fieldType定义或其分析链。

下面是一个fieldType元素的例子,其中namefieldType标识符,class是 Solr 的实现类名,sortMissingLast是实现类所需的属性:

<fieldType name="string" class="solr.StrField" sortMissingLast="true" />

Note

Solr 的早期版本要求在<types>元素中定义字段类型。最近的版本已经简化了结构,可以在<schema>元素中直接指定字段类型。

支持的值的类型、字段的行为以及要对字段执行的文本分析取决于三种类型的配置:

  • 实现类
  • 属性
  • 文本分析

接下来将对每种方法进行描述。

实现类

实现类实现字段类型的功能。它决定了字段可以容纳的值的类型以及应该如何解释这些值。为了定制文本处理,实现类通常支持一组属性,其中一些被标记为强制的。

根据数据和要在字段上执行的操作类型,您需要选择一个fieldType。假设你的数据是布尔型的;您将选择实现类solr.BoolField。如果您的数据是整数类型,您可以选择实现类solr.TrieIntField。表 4-1 显示了 Solr 提供的数据类型和支持的实现类。

表 4-1。

Primary Data Types Provided and Their Implementation Classes

| 数据 | 实现类 | | --- | --- | | 线 | `solr.StrField` `solr.TextField` | | 布尔代数学体系的 | `solr.BoolField` | | 数字 | `solr.TrieIntField` `solr.TrieLongField` | | 浮动 | `solr.TrieFloatField` `solr.TrieDoubleField` | | 日期 | `solr.TrieDateField` `solr.DateRangeField` | | 二进制数据 | `solr.BinaryField` | | 空间坐标数据 | `solr.LatLonType``solr.PointType` | | 闭集值 | `solr.EnumField` | | 随机唯一 ID | `solr.UUIDField` | | 外部来源的价值 | `solr.ExternalFileField` |

以下是关于实现类的一些要点:

  • 添加到solr.StrField的文本按原样被索引和查询。没有分析(没有修改)可以应用于它。如果你想用空格分割输入的文本或者把它变成小写,那么solr.StrField并不适合你fieldType。如果您想按原样索引文本,它是合适的—例如,在文档标识符(如产品 SKU)的情况下。
  • solr.TextField允许您对文本执行定制分析,方法是应用一个包含分析器或标记器的链,以及在索引或查询文档时可以应用的标记过滤器列表。在执行分析时,您可以以任何想要的方式转换文本;例如,您可以拆分令牌、引入新令牌、删除令牌或用另一个令牌替换一个令牌。
  • solr.DateRangeField提供了在查询中表示日期范围的附加条款。与solr.TrieDateField的另一个区别是响应格式是字符串而不是日期。

有关 Solr 中可用字段类型的完整列表,请参考位于 https://cwiki.apache.org/confluence/display/solr/Field+Types+Included+with+Solr 的 Solr 官方指南。

Note

solr开头的类名是指一个标准包中的 Java 类(比如org.apache.solr.analysis),不需要提供完整的包名。

字段类型属性

在定义fieldType时,可以将附加属性指定为元素的一部分。这些属性可以是通用的,可以应用于任何fieldType,也可以是特定于实现类的。

下面是一个示例fieldType定义,用于具有不同的precisionStep属性值的数值数据。precisionStep属性支持更快范围的查询,但是增加了索引的大小。如果需要对字段执行范围查询,使用fieldType tint。否则,使用fieldType intprecisionStep="0"禁用不同精度级别的索引数据。

<fieldType name="int" class="solr.TrieIntField"

precisionStep="0" positionIncrementGap="0" sortMissingLast="true"/>

<fieldType name="tint" class="solr.TrieIntField"

precisionStep="8" positionIncrementGap="0" sortMissingLast="true"/>

在这个例子中,sortMissingLast是可以应用于任何fieldType的通用属性,precisionStep是实现类TrieIntField的属性。

以下是 Solr 提供的主要fieldType属性。

编入索引的

要使字段可搜索,必须对其进行索引。如果您要查询匹配文档的字段,必须通过设置属性indexed="true"对其进行索引。只有在启用该属性时,才能对生成的令牌进行索引,并使术语变得可搜索。如果您设置了indexed="false",这个字段上的查询操作将不会获取任何结果,因为没有术语被索引。

当您添加一个永远不会被查询的显示字段时,您可以设置indexed="false"

存信息的

只能显示存储的字段。如果您设置了stored="false",则无法显示该字段中的数据。

当您知道您永远不会将该字段的值返回给用户时,您可以设置stored="false"。此外,如果您将相同的文本索引到多个字段以执行不同的分析,在这种情况下,您可以将所有副本设置为indexed="true"并只存储它的一个副本。无论何时需要显示值,都可以从存储的字段中获取。以下是这种情况的模式定义示例:

<field name="title" type="string" indexed="true" stored="true"/>

<field name="title_ws" type="text_ws" indexed="true" stored="false"/>

<field name="title_gen" type="text_general" indexed="true" stored="false"/>

假设您想要查询并显示title_gen字段。在这种情况下,查询title_gen字段并显示title字段。下面是针对这种情况的一个示例查询:

$ curl``http://localhost:8983/solr/hellosolr/select?q=user

如果可能,设置stored="false",因为它将提供更好的性能并减小索引大小(存储信息的大小)。存储的字段越大,检索起来就越费钱。

以下是索引和存储参数的可能组合:

  • indexed="true" & stored="true":当您对查询和显示字段的值都感兴趣时。
  • indexed="true" & stored="false":当你想查询一个字段,但不需要显示它的值时。例如,您可能希望只查询提取的元数据,但显示从中提取元数据的源字段。
  • indexed="false" & stored="true":如果你从来不打算查询一个字段,只显示它的值。
  • indexed="false" & stored="false":忽略字段的输入值。如果被索引的文档或 Lucene 查询包含一个不存在的字段,Solr 可能会报告一个异常。您可以通过创建一个被忽略的字段(禁用这两个属性的字段)来处理此异常。现在,假设您有一个从字段中提取元数据的更新处理器,并且您只对提取的元数据感兴趣,而对非结构化字段的值不感兴趣。这个属性对于忽略这样的字段非常有用。

Note

需要注意的是,存储在字段中的值是它接收到的原始值,而不是经过分析的值。如果要在存储值之前对其进行转换,应该使用转换器或预处理器来完成转换。第五章涵盖了这一主题。

需要

将该属性设置为true会指定一个强制字段。如果被索引的文档不包含任何字段值,则不会被索引。默认情况下,所有字段都设置为required="false"

多值的

此布尔参数指定字段是否可以存储多个值。例如,一首歌可以有多个歌手,一个杂志可以有多个作者,等等。您可能希望将歌手和作者字段设置为multiValued="true"。以下是schema.xml中对singerauthor字段的示例定义:

<field name="singer" type="string" indexed="true" stored="true" multiValued="true"/>

<field name="actor" type="string" indexed="true" stored="true" multiValued="true"/>

因为您通常索引非规范化的数据,所以在schema.xml中很少有multiValued字段是很常见的。如果您将数据从多个源字段复制到一个目标字段,请确保您将目标字段定义为multiValued,因为 Solr 不允许将多个值复制到一个单值字段。如果源字段是multiValued,那么目的字段也应该定义为multiValued。默认情况下,所有字段都是单值的。

文档值

docValues是 Solr 4.0 中引入的一个有趣的特性。如果该布尔参数设置为true,则为该字段创建一个前向索引。倒排索引在排序、分面和突出显示方面效率不高,这种方法有望提高速度,并释放fieldCache。以下是启用了docValues的字段定义示例:

<field name="language" type="string" indexed="true" stored="false" docValues="true"/>

启用docValues需要重新索引所有文档。

排序丢失优先/排序丢失最后

这两个属性都有助于处理排序场景,在这种场景中,被排序的字段不包含某些文档的任何值。在字段上指定sortMissingLast="true"属性会将没有字段值的文档排在最后(在包含字段值的文档之后)。相反,指定sortMissingFirst="true"对结果集顶部没有字段值的文档进行排序。无论排序顺序是升序还是降序,都会保持这个位置。

默认情况下,这两个属性都设置为false,在这种情况下,升序排序会将所有缺少值的文档放在最前面,降序排序会将所有缺少值的文档放在最后。

位置增量间隙

在内部,multiValued字段通过填充值之间的空格来实现(在一个值的最后一个标记和下一个值的第一个标记之间)。可选属性positionIncrementGap指定值之间的虚拟空格数,以避免错误的短语匹配。

假设一个文档的multiValued字段singer有两个值bob marleyelvis presley。如果您指定positionIncrementGap="0",短语 query marley elvis 将匹配该文档,因为没有填充,它被视为同一个令牌流的一部分。如果您指定positionIncrementGap="100",即使是带有中度 slop 的短语也不会匹配,因为 marley 和 elvis 相距一百个空格。

精确步骤

这是一个高级主题,用于对数值和日期字段执行更快的范围查询。范围查询是对具有指定范围内的字段值的文档的搜索请求,例如价格范围为$500 到$1,000 的产品。范围查询在第六章中有更详细的介绍。

Solr 为数值字段指定的默认精度步长是 4,这对于执行更快的范围查询是最佳的。如果您不需要对数值字段执行范围查询,请指定precisionStep="0",这将提供更高效的排序。Solr 提供的schema.xml包含一般用途的数值型字段,如 int、float、precisionStep="0"和前缀为 t 的字段,如tintprecisionStep="8"用于需要范围查询的数值型字段。

步长值越小,生成的令牌越多,范围查询的速度越快,但消耗的磁盘空间也越多。通常,该值应保持在 1 到 8 之间。具体实现请参考 http://lucene.apache.org/core/5_3_1/core/org/apache/lucene/search/NumericRangeQuery.html#precisionStepDesc 的 Lucene Javadoc。

omitNorms

字段有与之相关联的规范,它包含额外的信息,如索引时间提升和长度规范化。指定omitNorms="true"会丢弃这些信息,从而节省一些内存。

长度规范化允许 Solr 对较长的字段赋予较低的权重。如果长度规范在您的排序算法中不重要(比如元数据字段),并且您没有提供索引时间提升,那么您可以设置omitNorms="true"。默认情况下,Solr 禁用基本字段的规范。

omitTermFreqAndPositions

索引张贴还存储诸如词频、位置信息和有效载荷(如果有的话)之类的信息。您可以通过设置omitTermFreqAndPositions="true"来禁用这些附加信息。禁用此属性可以节省内存,减小索引大小,并提供更好的性能。如果您需要支持字段上的查询,如短语查询或跨度查询,您不应该禁用omitTermFreqAndPositions,因为这些查询依赖于位置信息。在文档中出现频率较高的查询术语通常被认为与全文域更相关,并且该信息由术语频率维护。因此,您可能不希望在全文字段中禁用它。

省略位置

指定布尔属性omitPosition="true"省略了位置信息,但保留了术语频率。

术语向量

指定布尔属性termVectors="true"保留了完整的术语向量信息。该属性一般与termPositionstermOffsets一起使用。这些由诸如突出显示和“更像这样”之类的功能使用,以提供更好的性能;否则,将使用存储的值重新分析该字段。

期限头寸

指定布尔参数termPositions="true"会保留术语在文档中的位置。

术语偏移量

指定布尔参数termOffsets="true"会保留文档中术语的偏移信息。

术语有效负载

指定布尔参数termPayloads="true"将保留文档中该术语的有效负载信息。有效负载允许您给术语添加数值,您可以在评分中使用该数值。当您想给一个术语(如名词或相关词)一个高权重时,这个特性很有用。

Tip

如果记住类的实现、属性和(尚未涉及的)文本分析似乎太多而难以消化,不要担心!设计自己的模式的最好方法是使用 Solr 发行版中提供的成熟的schema.xml并编辑它。在 Solr 5.x 中,命名配置集sample_techproducts_configs中提供的schema.xml文件可以作为设计模式的参考点。

文本分析(如果适用)

表 4-1 介绍了字符串数据的字段类型solr. TextFieldTextField是一个字段类型的特殊实现,它支持带有单个标记器和多个标记过滤器的可配置链的分析器进行文本分析。分析器可以将输入文本分解成标记,这些标记用于匹配,而不是对整个文本执行精确匹配。反过来,solr.StrField只执行精确匹配,不能应用分析器。

关于TextField的文本分析将在下一节详细介绍。

copyField(复制字段)

您可能希望以多种方式分析同一文本,或者将多个字段中的文本复制到单个字段中。schema.xml中的copyField元素提供将数据从一个字段复制到另一个字段的功能。您在source属性中指定复制源字段名称,在dest属性中指定复制目的字段名称,每当您添加包含源字段的文档时,Solr 将自动将数据复制到目的字段。下面是一个copyField的例子,它将album字段的文本复制到多个字段进行不同的分析:

<copyField source="album" dest="album_tokenized"/>

<copyField source="album" dest="album_gram"/>

<copyField source="album" dest="album_phonetic"/>

如果您将数据从多个源复制到一个目标,或者任何源字段是multiValued,请确保目标字段也被定义为multiValued="true"。否则,Solr 将在索引文档时抛出异常。

复制字段属性

以下是copyField支持的属性。

来源

source属性指定要从中复制数据的字段。源字段必须存在。字段名可以以星号开始和结束,以便从所有匹配该模式的源字段中复制。

建筑环境及 HVAC 系统模拟的软件平台

dest属性指定数据将被复制到的目标字段。目标字段必须存在。字段名可以以星号开始和结束,以便将文本复制到与模式匹配的所有目标字段。只有在源字段中指定了通配符,才能在目标字段中指定通配符。

麦斯查斯

这个可选的 integer 属性允许您检查字段大小,防止索引急剧增长。如果索引到目标字段的字符数超过了maxChars值,这些多余的字符将被跳过。

定义唯一键

schema.xml中的元素<uniqueKey>类似于数据库中的主键。此元素指定唯一标识文档的字段名称。下面是一个示例定义,它将一本书的isbn指定为文档的唯一标识符。

<uniqueKey>isbn</uniqueKey>

声明一个uniqueKey不是强制性的,但是强烈建议定义它。您的应用程序也很有可能有一个。以下是定义uniqueKey字段的规则和建议:

  • 该字段应为字符串或 UUID 类型。
  • 对该字段的任何索引时间分析都可能破坏 SolrCloud 中的文档替换或文档路由,应该避免。
  • 具有多个标记的字段不允许作为uniqueKey
  • 动态字段不能用于声明uniqueKey
  • 不能使用copyField填充该字段的值。

如果您为一个文档编制索引,并且另一个文档已经存在,并且具有相同的唯一键,则现有文档将被覆盖。要更新文档而不是替换它,请使用 Solr 的原子更新特性。第五章提供了更多关于原子更新的细节。

动态字段

Solr 允许您通过指定创建字段的模式来定义动态字段,而不是显式声明所有字段。当索引一个文档时,如果任何指定的字段没有在schema.xml中定义,Solr 会寻找一个匹配的动态字段模式。如果一个模式存在,Solr 创建一个在<dynamicField>元素中定义的fieldType的新字段。

如果您想要对多个字段执行类似的分析,那么您可以为那个fieldType定义一个dynamicField,而不是显式地声明它们。假设您想要为字段电影名称、演员和导演创建 N 元语法。您可以创建如下所示的动态字段,而不是为每个字段显式定义字段:

<dynamicField name="*_gram" type="ngrams" indexed="true" stored="false"/>

同样,如果您正在执行多语言操作,动态字段对于存储特定于语言的信息会很有用:

<dynamicField name="*_ut_en" type="ngrams" indexed="true" stored="true"/>

<dynamicField name="*_ut_fr" type="ngrams" indexed="true" stored="true"/>

<dynamicField name="*_ut_sp" type="ngrams" indexed="true" stored="true"/>

有时,直到文档被索引时,您才知道字段类型—例如,从富文档中提取元数据时。在这种情况下,动态字段很有用。

dynamicField元素支持与字段定义相同的属性,所有行为保持不变。

默认搜索字段

如果搜索请求不包含要查询的字段名,Solr 将搜索默认字段。此元素指定要查询的默认字段。下面是一个不包含字段名的示例查询,Solr 使用默认字段进行查询。

schema.xml:

<defaultSearchField>aggregate_text</defaultSearchField>

Sample query:

select?q=solr rocks&defType=standard // lucene

select?q=solr rocks&defType=edismax  // qf parameter is not specified

在 Solr 3.6 中,该元素已被弃用,不应用作后备。相反,应该使用df请求参数。

索尔克尔·帕塞尔

如果查询中没有指定操作符,这个元素指定查询解析器使用的默认操作符。此处提供了一个示例solrQueryParser定义:

<solrQueryParser defaultOperator="OR"/>

这个元素从 Solr 3.6 开始就被弃用了,应该用q.op请求参数来代替。

类似

Lucene 使用Similarity类实现对文档评分。要使用默认实现之外的实现,可以通过使用该元素并在class属性中指定类名来声明它。下面是schema.xml中默认相似性的规范:

<similarity class="solr.DefaultSimilarityFactory"/>

可以对所有字段或特定字段应用不同的相似性算法。以下是在特定字段上指定不同相似性的示例:

<fieldType name="text_ib">

<analyzer/>

<similarity class="solr.IBSimilarityFactory">

<str name="distribution">SPL</str>

<str name="lambda">DF</str>

<str name="normalization">H2</str>

</similarity>

</fieldType>

<similarity class="solr.SchemaSimilarityFactory"/>

相似性实现在第八章中有更详细的介绍。

文本分析

我们对模式设计的讨论提供了文本分析的概述。在本节中,您将更详细地了解这一过程。

分析是将文本流转换成术语的阶段。术语是 Lucene 用来匹配和计算文档分数的最小信息单位。术语不一定是输入文本中的单词;术语的定义取决于你如何分析文本流。术语可以是整个输入文本、两个或多个单词的序列、单个单词或文本流中任何字符的序列。

图 4-1 描述了一个例子:由于不同的分析,相同的输入文本流发出不同的术语。如您所见,KeywordTokenizerFactory没有对流进行任何更改,发出的术语是整个输入文本;相比之下,WhitespaceTokenizerFactory在空白上拆分,并发出多个术语。在本章的后面,你会学到分析器和记号赋予器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-1。

Text stream and the emitted terms

为了理解匹配行为,表 4-2 提供了几个简单的用户查询,这些用户查询通过该分析在字段上进行搜索(或匹配)。为了简单起见,该表提供了一个单词的查询,您可以假设在查询时没有执行任何分析。

表 4-2。

Query Match Status

| 询问 | Tokenizer | 匹配状态 | 描述 | | --- | --- | --- | --- | | 拿铁咖啡 | `KeywordTokenizerFactory` | 不匹配 | "喝拿铁咖啡或卡布奇诺."是索引术语。 | | 拿铁咖啡 | `WhitespaceTokenizerFactory` | 比赛 | “拿铁”是索引术语。 | | 拿铁咖啡 | `WhitespaceTokenizerFactory` | 不匹配 | 索引术语是“latte ”,由于大小写不同,这些术语不会匹配。 | | 卡普契诺咖啡 | `WhitespaceTokenizerFactory` | 不匹配 | 索引术语“卡布奇诺”包含一个额外的句点,因此术语不同。 |

如果您在标记化之后应用了PatternReplaceCharFilterFactory来删除特殊字符,那么表 4-2 中的 Cappuccino 查询将会匹配。

这些是简单的示例,您可以根据需要应用其他处理(例如小写、转换为最接近的 ASCII 字符或删除特殊字符和符号)。您执行的处理取决于您的匹配要求;这并不是说使用KeywordTokenizerFactory进行的分析是错误的,而是因为它有不同的目的。

Lucene 同时使用布尔模型(BM)和向量空间模型(VSM)来确定文档与查询的相关性。组合工作如下:由 BM 匹配的文档由 VSM 排序。BM 确定一个术语在一个字段中是否匹配。然后,文本分析开始起作用,控制匹配行为,并确定与索引中的术语匹配的查询术语。分析链在文档匹配中起着至关重要的作用。

Note

查询解析器在确定匹配文档时也起着重要的作用。你会在第六章中了解到。

分析器定义了一个进程链,每个进程执行一个特定的操作,比如拆分空白、删除停用词、添加同义词或者转换成小写。每个进程的输出都称为令牌。由分析链中的最后一个过程生成的标记(要么被索引,要么被用于查询)被称为术语,并且只有被索引的术语才是可搜索的。被过滤掉的标记(例如通过停用词移除)在搜索中没有意义,并且被完全丢弃。

图 4-1 过度简化了 Solr 中一个术语的例子。Solr 允许您在索引和查询时对令牌流执行相同或不同的分析。大多数情况下还需要查询时分析。例如,即使您在索引时执行小写,表 4-2 中的后一个查询将导致不匹配,因为查询标记本身以大写字母开始。您通常在索引和搜索时执行相同的分析,但是您可能希望仅在索引时或仅在搜索时应用某些分析,如同义词扩展的情况。

图 4-2 描述了一个对文本流执行一系列分析的典型分析器。链中的第一个进程接收输入流,在空白上分割它,并发出一组标记。下一个进程检查非 ASCII 字符的标记;如果有的话,它们被转换成最接近的等效 ASCII 码。转换后的标记被输入到去除停用词的过程中,该过程过滤掉停用词列表中存在的关键词。下一个过程将所有标记转换成小写,然后词干分析器将标记转换成它们的基本格式。最后,修整标记,最后这个过程发出的术语最终被索引或用于查询。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-2。

A typical analysis chain

以下是构建图 4-2 中指定的分析链的示例fieldType定义:

<fieldType name="text_analysis" class="solr.TextField" positionIncrementGap="100">

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.AsciiFoldingFilterFactory"/>

<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />

<filter class="solr.LowerCaseFilterFactory"/>

<filter class="solr.PorterStemFilterFactory"/>

<filter class="solr.TrimFilterFactory"/>

</analyzer>

</fieldType>

图 4-3 描述了该fieldType定义的文本分析示例。假设您正在构建一个为用户发现电影的电影搜索引擎,即使查询部分匹配。系统使用前面的文本分析并将电影名索引为“杀死一只嘲鸟”,如您所见,“嘲鸟”中的字母“I”错误地带有重音。您将看到当一个几乎不记得正确的电影名称搜索的用户杀死知更鸟时,匹配是如何工作的。还要注意,像这位用户一样,大多数用户通常用小写字母提供查询。以下步骤说明了分析链如何导致用户找到《杀死拟声鸟》这部电影:

WhitespaceTokenizerFactory splits the text stream on whitespace. In the English language, whitespace separates words, and this tokenizer fits well for such text analysis. Had it been an unstructured text containing sentences, a tokenizer that also splits on symbols would have been a better fit, such as for the “Cappuccino.” example in Figure 4-1.   AsciiFoldingFilterFactory removes the accent as the user query or content might contain it.   StopFilterFactory removes the common words in the English language that don’t have much significance in the context and adds to the recall.   LowerCaseFilterFactory normalizes the tokens to lowercase, without which the query term mockingbird would not match the term in the movie name.   PorterStemFilterFactory converts the terms to their base form without which the tokens kill and kills would have not matched.   TrimFilterFactory finally trims the tokens.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-3。

Text analysis and term matching

代币

令牌存储文本和附加元数据,包括文本的开始和结束偏移量、令牌类型、位置增量信息、应用程序定义的位标志和字节有效负载。

如果您正在编写用于文本分析的自定义实现,那么不应该忽略额外的元数据,因为一些组件需要这些额外的信息才能工作。偏移值由突出显示等功能使用。位置增量值标识字段中每个标记的位置,在短语和跨度查询中起着重要作用。大于 1 的位置增量值表示有间隙(该位置的单词已被删除),例如,停用词的删除会留下间隙。值为 0 会将标记放置在与前一个标记相同的位置;例如,同义词丰富将同义词放在相同的位置。位置增量的默认值为 1。

条款

术语是分析过程的输出,每个术语都被索引并用于匹配。除了令牌类型和标志之外,术语包含与令牌相同的信息。

Note

术语令牌和术语有时可互换使用,以指代发出的令牌。

分析者

分析过程由分析器定义,分析器被指定为schema.xml<fieldType>的子元素。它分析输入文本,并有选择地通过分析链运行它。分析仪可以执行两种类型的分析,如下所述。

简单分析

元素指定了实现分析的类的名称。例如:

<fieldType name="text_simple" class="solr.TextField">

<analyzer class="org.apache.lucene.analysis.WhitespaceAnalyzer"/>

</fieldType>

前面用于简单分析的fieldType定义通过在空白上分割输入令牌流来发出术语。如果输入流是鲍勃·马利,那么类型为text_simple的字段的分析项将是BobMarley

分析链

analyzer元素包含一系列名为tokenizerfilter的子元素,而不是指定实现分析的类。这些元素链接在一起形成了处理和分析输入文本的管道。元素在链中的指定顺序很重要:它们应该按照您希望它们运行的顺序来指定。在高层次上,分析链可用于执行以下操作:

  • 根据空白、符号或大小写变化拆分文本
  • 常化
  • 清除垃圾
  • 执行浓缩

图 4-2 中的fieldType定义提供了一个分析链的例子。您会注意到这个分析器的fieldType定义不包含classname属性,就像简单分析一样。相反,它包含一组子元素,每个子元素对应于链中的一个文本分析过程。

分析阶段

在前面的例子中,我们为索引和查询文档执行了相同的分析。Solr 允许您在两个阶段(索引和查询)执行不同的分析,一个阶段甚至可以没有任何分析。例如,如果您希望 inc 与 incorporated 匹配,您可能需要进行同义词扩展,并且在一个阶段中进行,无论是索引还是查询,都将匹配这两个术语。

以下是关于文本分析的一些要点:

  • 分析器的范围限于它所应用的领域。它不能创建新的字段,并且不能将一个字段发出的术语复制到另一个字段。
  • copyField复制字段的存储值,而不是分析链发出的术语。

两个分析阶段的描述如下。

索引

当一个文档被添加到 Solr 时,索引时间分析适用。每个字段都有一个类型。如果fieldType定义了一个分析器,那么文本流将被分析,发出的术语将与位置和频率等发布信息一起被编入索引。图 4-4 描述了一个指数时间分析过程。需要注意的是,分析过程只影响索引词,存储的值始终是字段接收的原始文本。转换后的文本只能被查询,不能被检索。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-4。

Index-time analysis

通过使用type="index"属性指定 analyzer 元素,可以在索引时执行不同的分析,如下所示:

<fieldType name="text_analysis" class="solr.TextField" positionIncrementGap="100">

<analyzer type="index">

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.AsciiFoldingFilterFactory"/>

...

</analyzer>

<analyzer type="query">

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.AsciiFoldingFilterFactory"/>

...

</analyzer>

</fieldType>

Note

索引时间分析器或其分析链中的任何变化都需要对所有文档进行核心重载和重新索引。

询问

查询解析器为用户查询调用对字段的查询时分析。图 4-5 描述了一个查询时分析过程。您可以看到该分析不同于索引时间分析。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-5。

Query-time analysis

通过用fieldTypetype="query"属性指定 analyzer 元素,可以在查询时执行不同的分析。

Note

查询时分析器或其分析链中的任何更改只需要重新加载核心,而不需要重新索引。

分析工具

为了检查字段和分析过程,可以使用以下工具。

Solr 管理控制台

为了检查在schema.xml中定义的字段和fieldTypes,Solr 在管理控制台中提供了 Analysis 选项卡。关联页面为索引时和查询时分析提供了单独的字段。您需要输入要分析的文本,选择字段或fieldType,点击分析值。如果在两个文本框中都提供了值,则该过程会突出显示匹配的标记。如果您只对分析器发出的术语感兴趣,可以禁用详细输出选项。

在分析屏幕上,您可以在分析字段名下拉列表旁边找到一个问号符号,它会将您带到模式浏览器屏幕。此屏幕允许您查看字段的属性并检查索引术语。图 4-6 显示了一个字段的模式浏览器屏幕。它显示字段属性和索引到该字段的顶级术语以及术语频率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-6。

Schema Browser

卢克(男子名)

Lucene Index Toolbox (Luke)是一个很棒的开源工具,用于检查和修改索引。你应该使用与 Lucene 库相同的 Luke 版本。您可以在 https://github.com/DmitryKey/luke 找到该工具。

分析仪组件

分析链在<analyzer>元素中指定,由下面描述的三种组件组合而成。图 4-7 描述了一个文本流是如何流经分析器并发出令牌的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-7。

Analyzer components chaining

字符过滤器

该组件在记号赋予器处理字符之前对字符进行清理和预处理。多个CharFilters可以链接在一起,并且应该总是在Tokenizer之前配置。

令牌设备

Tokenizer接受文本流,处理字符,并发出一系列标记。它可以根据空格或符号等字符来中断文本流。相邻的字符序列构成了记号。它还可以添加、删除或替换字符。

Tokenizers应始终在TokenFilters之前指定,并且在分析器中只能指定一次。此外,记号赋予器没有关于它被指定的字段的信息。表 4-3 指定了 Solr 提供的记号赋予器实现。

表 4-3。

Tokenizer Implementations

| 履行 | 描述 | | --- | --- | | `KeywordTokenizerFactory` | 没有符号化。为整个文本创建单个标记。首选用于对元数据等字段进行精确匹配。输入:“鲍勃·马利是一位传奇歌手。”输出:“鲍勃·马利是一个传奇歌手。” | | `StandardTokenizerFactory` | 精密智能的通用型`Tokenizer`。它分割空白和标点符号,识别句子边界和网址。它使用 Unicode 标准单词边界规则。输入:“鲍勃·马利是一位传奇歌手。”输出:"鲍勃" "马利" "是" "一个" "传奇" "歌手" | | `WhitespaceTokenizerFactory` | 它只是在空白上分割。输入:“鲍勃·马利是一位传奇歌手。”输出:"鲍勃" "马利" "是" "一个" "传奇" "歌手。" | | `ClassicTokenizerFactory` | 它支持 Solr 3.1 中的`StandardTokenizer`行为。它可以识别电子邮件 ID,并保持它们的完整性(当前的`StandardTokenizer`因为有了`@`符号而将 ID 分开)。输入:“bob 的 id 是 contact@bob.com”输出:“Bob 的“id”是“contact@bob.com” | | `LetterTokenizerFactory` | 它将连续的字母视为记号,其他的都被丢弃。输入:“bob 的 id 是 contact@bob.com”输出:“Bob 的 id”是“contact”“Bob”“com” |
令牌过滤器

TokenFilter处理Tokenizer产生的令牌。TokenizersTokenFilters的重要区别在于Tokenizer输入是Reader,而TokenFilter输入是另一个TokenStream

TokenFilters应该总是在Tokenizer之后指定,并且可以指定任意次。另外,TokenFilter没有关于它正在处理的字段的信息。

Solr 提供了广泛的令牌过滤器工厂。下一节将介绍初级过滤器工厂。有关 Solr 提供的过滤器的完整列表,请参考位于 https://cwiki.apache.org/confluence/display/solr/Filter+Descriptions 的 Solr 官方参考指南。

常见文本分析技术

Solr 开箱即用提供了各种各样的分析器、令牌化器和令牌过滤器,可以快速轻松地构建一个有效的搜索引擎。在本节中,您将了解文本处理技术,使用这些字段分析器可以实现所需的搜索行为。

同义词匹配

在探索同义词匹配之前,让我们考虑一个例子。定义一词的同义词包括描述、详述、解释、说明和说明。在执行搜索之前,最终用户会考虑使用哪些关键字来表达意图和制定查询。假设用户正在寻找单词同义词的定义;他的查询可以是定义同义词、描述同义词、或定义一词的任何其它同义词。因此,维护术语的同义词非常重要。否则,即使您的语料库包含用户正在寻找的信息,系统也无法检索到它。

Solr 提供了SynonymFilterFactory来执行基于字典的同义词匹配。可以在一个文本文件中配置同义词,该文件包含一系列关键字及其匹配的同义词。以下是schema.xmlSynonymFilterFactory的定义示例:

<fieldType name="text_synonyms" class="solr.TextField">

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt"

ignoreCase="true" expand="false"/>

</analyzer>

</fieldType>

有关文件格式,请参考命名配置集中提供的样本synonyms.txt文件。

因素

SynonymFilterFactory支持以下参数:

  • synonyms:指定包含同义词映射的外部文本文件的名称。
  • ignoreCase:如果设置为true,查找时将忽略关键字的大小写。
  • expand:如果true,令牌将被扩展。如果false,同义词将折叠到关键字。

考虑到拥有一个通用同义词(适用于该语言)和特定同义词(特定于您的领域)的需要,您可以在一个分析链中配置多个SynonymFilters。基本上,如果需要,任何TokenFilter都可以被多次配置。

SynonymFilterFactory可以在索引时和查询时应用,但通常应用于两者之一。索引时同义词扩展会导致更大的索引大小,列表中的任何更改都需要重新编制索引。但它也有好处。扩展的标记将有助于逆文档频率(IDF ),其给予更稀有的单词更高的重要性。

查询时同义词扩展不会增加索引大小,也不会让您在更改同义词列表后重新建立索引,但是它会增加查询响应时间。查询时间扩展的问题在于包含多个单词的同义词,比如电影明星。在被分析器处理之前,这些词已经被QueryParser标记成电影和明星。短语查询的另一个问题是:短语中的标记会被扩展,这导致短语有多个标记,最终可能是不匹配的。例如,电影明星可以扩展到"(movie | cinema) (star | actor | cast)",最终无法匹配包含电影明星的文档。

语音匹配

语音匹配算法用于匹配发音相似的单词。当单词拼写错误时,编辑距离和 N-grams 特别适用,但当单词的写法不同但发音总是相同时,语音学也适用。

名字匹配是一个典型的例子:一个名字可以有多种拼写,但发音相同。为了匹配一个人的名字,语音算法变得更加重要,因为没有标准的名字定义或字典。一个名字可以有多个发音相同的变体。比如 Christy 和 Christie 是同一个名字的音素,两者都是正确的。

语音匹配可能不适用于打字错误,这是无意的,通常包括顺序错误的字母(例如,good typed as godo)。然而,如果错误是故意的,语音匹配可能是有效的,例如在 tweets 或短信中,用户可能会用 gud 替换 good,或者用 u 替换 you。

语音匹配的目的是提高召回率,并确保不会遗漏可能匹配的术语。建议对语音字段给予较低的提升,因为这可能最终匹配完全不相关的单词,要么是因为单词在语音上相似,但代表不同的概念,要么是因为算法的限制。

语音学是高度特定于语言的,并且大多数算法是为英语开发的。这些算法对记号进行编码,并且对于发音相似的单词应该是相同的。表 4-4 提供了 Solr 和样本定义支持的语音算法列表。

表 4-4。

Phonetic Algorithms

| 算法 | 定义 | | --- | --- | | 贝德-莫尔斯语音匹配(BMPM) | 为名字和姓氏提供了更好的代码。配置:`` | | 桑迪克斯 | 发展到匹配发音相似的姓氏。它生成四个字符的代码,以一个字母开头,后跟三个数字。配置:`` | | 变音 | 它通常用于匹配发音相似的单词,并不限于姓氏。配置:`` | | 双重变音 | 变音位的这种扩展解决了英语以外的语言的特殊性。配置:`` `` | | 精制 Soundex | Soundex 的改进版本,它为相同的代码匹配更少的名称。配置:`` | | 戴奇-莫科托夫 Soundex | Soundex 的改进。它为匹配姓名提供了很高的准确性,尤其是斯拉夫语和欧洲语。它生成六位数字的代码。配置:`` | | 穴居人 | 针对新西兰口音进行了优化。配置:`` | | 科隆音素(科隆音素) | 适合德语单词。配置:`` | | 纽约州身份识别和情报系统 | 提供比 Soundex 更好的结果,使用更复杂的代码生成规则。配置:`` |
N-Grams

N-Gram将输入的单词分解成多个子单词,称为 grams。例如,大小为 4 的输入令牌 hellosolr 的克数将是 hell、ello、llos、loso、osol 和 solr。如果用户查询是 solr,您可以看到最后生成的 gram 将匹配。

n-gram 对于匹配子字符串和拼写错误的单词很有用。它对于自动完成、前缀和后缀查询以及通配符搜索等功能也很有用。n 元语法提高了召回率,并匹配了否则会被遗漏的标记。

Solr 为 N 元语法提供了TokenizersTokenFilters。如果要在标记化的文本上生成克,可以使用TokenFilter;否则,可以使用Tokenizer。表 4-5 列出了 Solr 为 N-gram 提供的实现。

表 4-5。

N-Gram Implementations

| 履行 | 定义 | 例子 | | --- | --- | --- | | `NGramTokenizerFactory` `NGramFilterFactory` | 从所有字符位置生成指定范围内所有大小的 N 元字符属性:`minGramSize`:最小字符大小`maxGramSize`:最大字符大小配置:`` `` | 输入:hellosolr 输出:hel,ell,llo,go,oso,sol,olr,hell,that,llos,loso,oso,solr | | `EdgeNGramTokenizerFactory` `EdgeNGramFilterFactory` | 从指定的边生成指定范围内所有大小的 N-gram 属性:`minGramSize`:最小 gram 大小`maxGramSize`:最大 gram 大小`side`:应该从其生成 gram 的边。值可以是`front`或`back`。默认为`front`。配置:`` `` | 输入:hellosolr 输出:hell,hello |

与 N 元文法相比,边 N 元文法生成的令牌更少,性能更好。N-gram 提供了更好的回忆,但应该小心使用,因为它可能导致过匹配。

如果保持minGramSize较小,将会生成大量令牌,索引大小和索引时间将会增加,并会对性能产生影响。你应该只为几个字段生成 N-gram,并尽量保持minGramSize高和maxGramSize低。

叠瓦作用

Shingling 是以单词为基础而不是以字符为基础生成 grams 的。对于输入流 apache solr rocks,生成的瓦片区将是 apache solr 和 solr rocks。

通过允许您匹配子短语,Shingling 提供了一种提高相关性排名和精确度的机制。短语查询匹配整个标记序列,基于标记的匹配匹配一个发出的术语,而瓦片区介于两者之间。与短语相比,Shingling 提供了更好的查询性能,但需要额外的令牌。

瓦片区通常在索引时应用,但是也可以在索引和查询时应用。此外,瓦片区通常会得到很大的提升。

以下是schema.xmlSynonymFilterFactory的示例定义:

<fieldType name="text_shingles" class="solr.TextField">

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.ShingleFilterFactory" minShingleSize="2" maxShingleSize="3" outputUnigrams="false"/>

</analyzer>

</fieldType>

因素

ShingleFilterFactory支持以下参数:

  • minShingleSize:每个瓦片区的最小令牌数。默认值为 2。
  • maxShingleSize:每个瓦片区的最大令牌数。默认值为 2。
  • outputUnigrams:该布尔参数指定是否应该生成单个令牌。默认情况下,这被设置为true。如果这个参数是true,并且你正在给这个领域一个很高的提升,评估这个提升不会对相关性产生负面影响,因为你的总体意图是给由多个令牌组成的瓦片区更高的提升。
  • outputUnigramsIfNoShingles:该布尔参数指定如果没有生成瓦片区,是否应该生成单独的令牌。默认情况下,这被设置为false
  • tokenSeparator:这指定了用于连接形成瓦片区的标记的分隔符。默认值为" "
堵塞物

词干处理是将单词转换成基本形式的过程,以匹配单词的不同时态、语气和其他变化。基词也叫词干。值得注意的是,在信息检索中,词干提取的目的是匹配一个单词的不同词形变化;茎不一定是形态根。

词干分析器通常是特定于语言的。英语有多种词干分析器可供选择。对于其他语言,词干分析器也可用。表 4-6 指定了 Solr 中支持的主要词干分析器。

表 4-6。

Stemming Algorithms

| 史泰克 | 工厂级 | 特征 | 语言 | | --- | --- | --- | --- | | 波特茎 | `solr.PorterStemFilterFactory` | 基于算法。快速算法。 | 英语 | | 克斯特姆 | `solr.KStemFilterFactory` | 与波特斯干相似,但攻击性较弱,速度较快。 | 英语 | | 雪球 | `Solr.SnowballPorterFilterFactory` | 基于算法。比波特斯干慢。更有侵略性。 | 多种语言 | | 洪斯佩尔 | `solr.HunspellStemFilterFactory` | 基于词典和基于规则的词干分析器的组合。使用与 Apache OpenOffice 中相同的词典。 | 支持 99 种语言 | | 英语最小词干 | `solr.EnglishMinimalStemFilterFactory` | 不那么咄咄逼人。适用于轻词干和情况,如复数到单数的转换。 | 多种语言 |

图 4-8 显示了以旅行为基础的单词的词干结果。我们在索引时应用了PorterStemFilter,在查询时应用了EnglishMinimalStemFilter,以说明两种算法在结果和激进程度上的差异。PorterStemFilter更具攻击性,将 travel 的所有词形变化转换为其基本词,而EnglishMinimalStemFilter只对少数词形变化进行转换。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-8。

Stemming algorithm comparison Caution

在图 4-8 中,为了进行比较,在索引时和查询时配置了不同的词干分析器。很少会出现您希望这样配置的情况。

在对标记进行词干提取时,可能会出现过度提取和不足提取的问题,因此在选择词干提取算法时应考虑这些误差测量值。在越界中,两个完全不相关的单词源于同一个词根,尽管它们不应该是这样的(误报)。在理解中,两个相关的单词并不是源于同一个词根,尽管它们应该是(一个真正的否定)。比如,EnglishMinimalStemFilter不把 travel 词干化为 travel 就是理解不足的情况,PorterStemFilter把 university 和 universe 词干化为 universe 就是逾越的情况。

词干通常应该在索引和查询时使用。词干不会增加索引的大小。

Solr 分别用KeywordMarkerFilterStemmerOverrideFilter提供解决过度转向和转向不足问题的规定。

关键字标记过滤器

通过在文件中指定受保护的单词,防止单词被词干化。文件名应该在过滤器工厂的protected属性中指定。

KeywordMarkerFilter针对因越界而导致误报的黑名单词做出有效的解决方案。在前面的例子中,你看到大学被超越了。假设你不希望一个词被词干化;您可以将其添加到受保护的单词文件中并配置KeywordMarkerFilter。以下是schema.xml中的fieldType配置示例:

<fieldType name="text_stem" class="solr.TextField">

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt" />

<filter class="solr.PorterStemFilterFactory" />

</analyzer>

</fieldType>

KeywordMarkerFilterFactory应始终在出厂前配置词干分析器。如果在词干分析器之后配置它,它将不起作用。

StemmerOverrideFilter

为了解决理解不足的问题,Solr 提供了StemmerOverrideFilter。它覆盖由配置的词干分析器完成的词干,词干映射到词干覆盖文件中的单词。

词干替代文件名是在过滤器工厂的dictionary属性中配置的,它包含单词到制表符分隔文件中词干的映射。以下是schema.xml中的fieldType配置示例:

<fieldType name="text_stem" class="solr.TextField">

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.StemmerOverrideFilterFactory" dictionary="stemdict.txt" />

<filter class="solr.PorterStemFilterFactory" />

</analyzer>

</fieldType>

StemmerOverrideFilterFactory应始终在出厂前配置词干分析器。如果在词干分析器之后配置它,它将不起作用。

黑名单(停用词)

有些术语对你的搜索引擎来说并不重要。例如,像 a、an 和 the 这样的词会添加到单词包中,最终会增加误报率。您可能希望阻止这些词被索引和查询。Solr 提供StopFilterFactory将停用词文件中指定的词从字段标记中列入黑名单并丢弃。下面是一个配置示例:

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.StopFilterFactory" words="stopwords.txt"/>

</analyzer>

图 4-9 以电影搜索引擎为例说明停用词的去除;单词 movie 被假定为停用词。我们在停用词文件中添加了关键字 movie,并分析了电影《肖申克的救赎》的文本评论。停用字词过滤器从令牌流中移除令牌电影。此外,它在流中创建了一个间隙,这可以由令牌元数据确定,如位置、开始和结束偏移量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-9。

Stop-words removal

sample_techproducts_configs配置集中提供的stopwords.txt文件是空白的,它不包含任何条目。常见的英语单词如 a、an 和 the 通常是stopwords.txt文件的良好候选。要找到特定于您的内容的停用词,Solr 管理控制台中的模式浏览器是一个很好的起点。您可以选择一个字段,并通过单击“加载术语信息”按钮加载出现频率最高的术语。然后,您可以检查这些高频术语,以确定其中是否有一些可以作为停用词。

白名单(保留单词)

白名单与停用词删除或黑名单相反。这仅允许出现在指定列表中的那些令牌通过,所有其他令牌都被丢弃。假设您的应用程序支持一组指定的语言;在这种情况下,您可能希望应用只保留受支持的语言并丢弃所有其他文本的筛选器。

您可以通过使用KeepWordFilterFactory类在 Solr 中实现这一点。该过滤器通常在索引时应用。以下是一个配置示例:

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.KeepWordFilterFactory" words="keepwords.txt"/>

</analyzer>

以下是支持的参数:

  • words:包含允许单词的文本文件的路径。文件定义规则与停用字词文件相同。
  • ignoreCase:该布尔参数,如果设置为true,使过滤器对大小写变化不敏感。默认值为false
其他标准化

在上一节中,您了解了词干化,这是文本规范化的一种形式。类似地,您可能需要通过向分析链添加令牌过滤器来执行其他文本规范化。以下是其他常用的规范化器。

用小写字体书写

用户查询通常不遵循语言的大小写约定,大多以小写形式提供。因此,您可能希望您的搜索不区分大小写。实现这一点的最好方法是遵循一个惯例,即所有的标记都使用相同的大小写。Solr 提供了LowerCaseFilterFactory来将令牌中的所有字母转换成小写,如果不是的话。例如,鲍勃马利必须匹配鲍勃马利。以下是一个配置示例:

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.LowerCaseFilterFactory"/>

</analyzer>

这通常适用于索引和查询。

转换为最接近的 ASCII 字符

如果您希望您的搜索体验对重音不敏感,以便重音和非重音字符都匹配相同的文档,那么您应该将ASCIIFoldingFilterFactory添加到分析链中。此过滤器将 Unicode 字符转换为最接近的 ASCII 等效字符(如果有)。例如,Bełżec 应该与贝尔泽奇相匹配。下面是一个配置示例:

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.ASCIIFoldingFilterFactory"/>

</analyzer>

这通常适用于索引和查询。

移除重复的令牌

在对文本执行一系列操作之后,这个链可能最终会生成重复的标记,比如执行 enrichments 或 synonym expansion,然后进行词干分析。Solr 提供了RemoveDuplicatesTokenFilterFactory实现来删除相同位置的重复标记。以下是一个配置示例:

<analyzer>

<tokenizer class="solr.WhitespaceTokenizerFactory"/>

<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>

</analyzer>

这通常在步进时应用。

多语言支持

您执行的文本分析在很大程度上取决于您需要支持的语言。您可能正在开发一个特定语言的搜索引擎,或者您可能需要支持多种语言。为了支持特定的语言,您可以根据该语言的语言学来定义所有的fieldTypes。如果需要支持多种语言,可以为每种语言定义不同的fieldTypes,并将文本复制到相应的字段中。Solr 提供的命名配置集包含各种语言的fieldType定义,这里提供了一个例子:

<!-- German -->

<fieldType name="text_de" class="solr.TextField" positionIncrementGap="100">

<analyzer>

<tokenizer class="solr.StandardTokenizerFactory"/>

<filter class="solr.LowerCaseFilterFactory"/>

<filter class="solr.StopFilterFactory" ignoreCase="true"

words="lang/stopwords_de.txt" format="snowball" />

<filter class="solr.GermanNormalizationFilterFactory"/>

<filter class="solr.GermanLightStemFilterFactory"/>

<!-- less aggressive: <filter class="solr.GermanMinimalStemFilterFactory"/> -->

<!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="German2"/> -->

</analyzer>

</fieldType>

前面的fieldType定义是针对德语的。可以看到 Solr 提供了特定于它的工厂。在所提供的工厂中,它为词干分析器提供了多种实现,您可以使用最适合您需求的实现。

许多语言的字母表使用发音符号,如法语脚本,来改变它们所添加的字母的发音。规范化的一个简单方法是使用ASCIIFoldingFilterFactory,我们在上一节中讨论过,将带有重音符号的单词转换为最接近的 ASCII 字符。但是这对于像阿拉伯语这样的语言不起作用,因为阿拉伯语的发音符号不能转换成 ASCII 字符。

对于某些语言,Solr 提供了特定的记号赋予器和过滤器工厂,如ElisionFilterFactory来处理适用于所选语言的省略符号。此外,一些过滤器工厂接受包含特定于该语言的内容的不同输入文件。例如,英语中的停用词与保加利亚语中的停用词不同。Solr 在conf中提供了一个lang子目录,其中包含工厂可以使用的特定于语言的文件列表。

在像英语这样的语言中,您可以很容易地根据空格来识别单词,但是有些语言(例如,日语)不使用空格来分隔单词。在这些情况下,很难确定要索引哪些标记。下面是一个句子“你要喝什么,啤酒还是咖啡?”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Solr 提供了CJKTokenizerFactory,它将中文、日文和韩文文本分解成记号。生成的令牌是文本流中发现的双精度、重叠的 CJK 字符对。它还为日语提供了JapaneseTokenizerFactory和其他过滤器,这些过滤器在 Solr 附带的schema.xml文件中的fieldType text_ja中定义。图 4-10 中的例子显示了text_ja对日语文本进行的分析。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-10。

Text analysis example for Japanese language

您可以在 https://cwiki.apache.org/confluence/display/solr/Language+Analysis 查阅官方指南,了解 Solr 提供的语言特定工厂的完整列表。

无模式化

无模式模式是开始使用 Solr 的最快方式。它允许您从零模式手工制作开始 Solr,并简单地索引文档,而不用担心字段定义。在无模式模式下,你可以先跳过本章前面所读的内容。如果想要更好地控制字段定义或其他模式配置,可以使用托管模式和 REST APIs。

无模式模式本质上是一组 Solr 特性的适当打包,可以轻松设置和动态创建字段。以下是可以一起使用来支持这种动态模式的功能。

  • 自动字段类型识别
  • 自动字段创建
  • 托管模式和 REST APIs
  • 动态字段

如果您不熟悉 Solr,或者不知道文档结构或者结构经常变化,那么无模式模式非常有用。

Solr 为无模式模式捆绑了一个示例配置集。您可以通过运行 Solr 脚本来测试它,如下所示:

$ ./solr start -e schemaless

如果您想要创建一个无模式核心,您可以创建一个没有任何配置信息的核心/集合,或者指定预绑定的配置集data_driven_schema_configs。下面是一个创建无模式核心的示例:

$ ./solr create -c schemaless -d data_driven_schema_configs

$ ./solr create -c schemaless // by default uses data_driven_schema_configs

什么使 Solr Schemaless

如您所知,Solr 通过将一组特性捆绑在一起实现了无模式化。以下是可以用来实现无模式化的特性。

自动字段类型识别

每当 Solr 遇到模式中没有定义的新字段时,它都会对字段内容运行一组解析器,以识别字段类型。目前,Solr 只为原语fieldTypes提供字段类型猜测:Integer、Long、Float、Double、Boolean 和 Date。

请记住,使用动态字段的字段类型猜测是基于字段名模式的,但这里是基于字段内容的。Solr 通过提供以名称Parse*开始的更新处理器工厂来实现这个特性,它在预处理时标识字段类型。你会在第五章中读到更多关于更新处理器工厂的细节。

自动字段添加

对于未知的字段,如果 Solr 成功地猜出了fieldType,它会将该字段添加到模式中。字段添加由配置在用于字段类型猜测的处理器之后的AddSchemaFieldsUpdateProcessorFactory处理。

托管模式和 REST API

自动字段类型识别和字段添加仅限于原始字段类型。如果您想要为任何字段指定一个fieldType或者在其上定义文本分析,您可能想要添加一个字段和/或fieldType。您可以通过使用托管模式和 REST APIs 动态地完成这项工作。我们将在下一节更详细地讨论这一点。

动态字段

从早期版本开始,Solr 就支持动态字段,它支持有限但强大的无模式功能。它允许您将一个复杂的fieldType分配给一个匹配字段命名模式的新字段。

配置

本节指定了将 Solr 配置为无模式的步骤。如果您正在使用data_driven_schema_configs配置集创建一个核心,Solr 已经有了配置,您只需要开始索引文档。如果您想要手动定义或修改现有的无模式核心,请遵循以下步骤:

Define the following updateRequestProcessorChain with the update processor factories specified in sequence in solrconfig.xml. All the defined factories starting with Parse* perform the fieldType identification. The AddSchemaFieldsUpdateProcessorFactory is responsible for creating fields automatically, and the UUIDUpdateProcessorFactory generates unique identifiers for the document. The RemoveBlankFieldUpdateProcessorFactory and FieldNameMutatingUpdateProcessorFactory are for normalization of a field and its value. <updateRequestProcessorChain name="add-unknown-fields-to-the-schema">     <!-- UUIDUpdateProcessorFactory will generate an id if none is present in the incoming document -->     <processor class="solr.UUIDUpdateProcessorFactory" />     <processor class="solr.LogUpdateProcessorFactory"/>     <processor class="solr.DistributedUpdateProcessorFactory"/>     <processor class="solr.RemoveBlankFieldUpdateProcessorFactory"/>     <processor class="solr.FieldNameMutatingUpdateProcessorFactory">       <str name="pattern">[^\w-\.]</str>       <str name="replacement">_</str>     </processor>     <processor class="solr.ParseBooleanFieldUpdateProcessorFactory"/>     <processor class="solr.ParseLongFieldUpdateProcessorFactory"/>     <processor class="solr.ParseDoubleFieldUpdateProcessorFactory"/>     <processor class="solr.ParseDateFieldUpdateProcessorFactory">       <arr name="format">         <str>yyyy-MM-dd’T’HH:mm:ss.SSSZ</str>         <str>yyyy-MM-dd’T’HH:mm:ss,SSSZ</str>         <str>yyyy-MM-dd’T’HH:mm:ss.SSS</str>         <str>yyyy-MM-dd’T’HH:mm:ss,SSS</str>         <str>yyyy-MM-dd’T’HH:mm:ssZ</str>         <str>yyyy-MM-dd’T’HH:mm:ss</str>         <str>yyyy-MM-dd’T’HH:mmZ</str>         <str>yyyy-MM-dd’T’HH:mm</str>         <str>yyyy-MM-dd HH:mm:ss.SSSZ</str>         <str>yyyy-MM-dd HH:mm:ss,SSSZ</str>         <str>yyyy-MM-dd HH:mm:ss.SSS</str>         <str>yyyy-MM-dd HH:mm:ss,SSS</str>         <str>yyyy-MM-dd HH:mm:ssZ</str>         <str>yyyy-MM-dd HH:mm:ss</str>         <str>yyyy-MM-dd HH:mmZ</str>         <str>yyyy-MM-dd HH:mm</str>         <str>yyyy-MM-dd</str>       </arr>     </processor>     <processor class="solr.AddSchemaFieldsUpdateProcessorFactory">       <str name="defaultFieldType">strings</str>       <lst name="typeMapping">         <str name="valueClass">java.lang.Boolean</str>         <str name="fieldType">booleans</str>       </lst>       <lst name="typeMapping">         <str name="valueClass">java.util.Date</str>         <str name="fieldType">tdates</str>       </lst>       <lst name="typeMapping">         <str name="valueClass">java.lang.Long</str>         <str name="valueClass">java.lang.Integer</str>         <str name="fieldType">tlongs</str>       </lst>       <lst name="typeMapping">         <str name="valueClass">java.lang.Number</str>         <str name="fieldType">tdoubles</str>       </lst>     </processor>     <processor class="solr.RunUpdateProcessorFactory"/>   </updateRequestProcessorChain>   For the chain to be usable, UpdateRequestProcessorChain should be registered in the update handler that gets invoked for indexing the documents: <initParams path="/update/**">     <lst name="defaults">       <str name="update.chain">add-unknown-fields-to-the-schema</str>     </lst> </initParams>   Enable support for the managed schema in solrconfig.xml: <schemaFactory class="ManagedIndexSchemaFactory">   <bool name="mutable">true</bool>   <str name="managedSchemaResourceName">managed-schema</str> </schemaFactory>   After making the preceding changes, you are all set to index documents without worrying about whether the field is defined in schema.xml.

限制

在完全无模式模式下运行 Solr 有局限性。以下是需要注意的重要问题:

  • 自动字段添加支持一组有限的原语fieldTypes,并且不允许您应用analyzer或执行一组特定的文本分析。
  • Field Type识别可能导致错误的fieldType猜测,因为 Solr 通过处理器级联来识别fieldType。如果被索引的文档包含一个数字,Solr 将创建一个类型为TrieIntField的字段。现在,如果下一个文档包含浮点数,Solr 将无法索引该文档,因为它已经将该字段的fieldType定义为TrieIntField,并且字段一旦定义就不能自动更改。
  • 在定义一个字段时,您可能希望通过指定额外的属性(如precisionStep)来对其进行微调。一个自动的fieldType定义忽略了这个观点。

Tip

在无模式模式下运行 Solr 时,不应该手动修改模式。

用于管理模式的 REST API

在讨论无模式模式之前,我们使用schema.xml来定义模式。模式中的任何更改都需要您手动编辑schema.xml并重新加载核心。自从 Solr 诞生以来,这就是schema.xml被使用的方式。但是 Solr 的最新版本允许您通过 REST APIs 管理模式。Solr 提供 REST APIs 来读取、添加、删除和更新元素,以管理fieldfieldTypecopyFielddynamicField元素。

Solr 提供了基类IndexSchemaFactory的两个实现来管理模式。您需要在solrconfig.xmlschemaFactory元素中定义实现类:

  • ClassicIndexSchemaFactory:这是默认实现,您可以手动定义模式。schema.xml文件必须存在于conf目录中,并且应该手动修改。这个实现不支持通过 REST APIs 管理模式。
  • ManagedIndexSchemaFactory:这是通过 REST APIs 管理模式的实现。

配置

下面是使用 REST APIs 配置托管模式的步骤。

Define the schemaFactory element in solrconfig.xml and provide the implementation class as ManagedIndexSchemaFactory: <schemaFactory class="ManagedIndexSchemaFactory">   <bool name="mutable">true</bool>   <str name="managedSchemaResourceName">managed-schema</str> </schemaFactory> In Solr 5.x, if you create a core without specifying the configuration directory, it will by default use the data_driven_schema_configs configset, which creates a managed schema to support REST calls. The data_driven_schema_configs configset is provided with the Solr distribution and can be located in the $SOLR_DIST/server/solr/configsets directory. The following is the schemaFactory element in solrconfig.xml for the traditional approach to a schema definition: <schemaFactory class="ClassicIndexSchemaFactory"/>   The default file for a managed schema definition is managed-schema. You can change the filename by modifying the managedSchemaResourceName parameter. On creating a core, if the schema.xml exists but the managed-schema file doesn’t exist, in that case Solr will copy schema.xml to the managed-schema file and rename schema.xml to schema.xml.bak. Solr doesn’t allow you to change the name of managed schema file to schema.xml. The following is the property to be set for specifying the managed schema file name: <str name="managedSchemaResourceName">managed-schema</str>   If your schema is finalized, you may be interested in disallowing all future edits. To limit the REST APIs to support only read access, set the mutable Boolean parameter to false: <bool name="mutable">false</bool> It’s good to disable the mutable setting in production.

休息端点

一旦设置好managed-schema,就可以开始使用 REST API 执行读写操作了。所有写请求都会自动在内部触发核心重载,因此您不应该调用这些请求来反映这些更改。表 4-7 列出了 REST API 支持的操作、要调用的端点以及示例。

表 4-7。

REST Endpoints for Managing Schema

| 操作 | 端点和命令 | 例子 | | --- | --- | --- | | 读取模式 | `GET /core/schema` | `curl http://localhost:8983/solr/core/schema?wt=json` | | 读取字段 | `GET /core/schema/fields` `GET /core/schema/fields/fieldname` | `curl http://localhost:8983/solr/core/schema/fields?wt=json` | | 修改字段 | `POST /core/schema`命令:`add-field` `delete-field` `replace-field` | `curl -X POST -H ’Content-type:application/json’ --data-binary ’{` `"add-field":{` `"name":"title",` `"type":"text_general",` `"stored":true }` | | 读取字段类型 | `GET /core/schema/fieldtypes` `GET /core/schema/fieldtypes/name` | `curl http://localhost:8983/solr/core/schema/fieldtypes?wt=json` | | 修改字段类型 | `POST /core/schema`命令:`add-field-type` `delete-field-type` `replace-field-type` | `curl -X POST -H ’Content-type:application/json’ --data-binary ’{``"add-field-type" : {``"name":"text_ws",``"class":"solr.TextField",``"positionIncrementGap":"100",``"analyzer" : {``"tokenizer":{``"class":"solr.WhitespaceTokenizerFactory" }}}``}’ http://localhost:8983/solr/core/schema` | | 读取动态字段 | `GET /core/schema/dynamicfields` `GET /core/schema/dynamicfields/name` | `curl http://localhost:8983/solr/core/schema/dynamicfields?wt=json` | | 修改动态字段 | `POST /core/schema`命令:`add-dynamic-field` `delete-dynamic-field` `replace-dynamic-field` | `curl -X POST -H ’Content-type:application/json’ --data-binary ’{` `"add-dynamic-field":{` `"name":"*_en",` `"type":"text_general",` `"stored":true }` | | 读取副本字段 | `GET /core/schema/copyfields` | `curl http://localhost:8983/solr/core/schema/copyfields?wt=json` | | 修改副本字段 | `POST /core/schema`命令:`add-copy-field` `delete-copy-field` `replace-copy-field` | `curl -X POST -H ’Content-type:application/json’ --data-binary ’{``"add-copy-field":{``"source":"title",``"dest":[ "title_ut", "title_pn" ]}` |

其他托管资源

Solr 提供了使用 REST APIs 管理其他资源(如停用词和同义词)的条款。

使用步骤

下面是使用 REST APIs 管理停用词和同义词的步骤。

Add the implementing filter factory to the analysis chain <filter class="solr.ManagedStopFilterFactory" managed="product" /> // stopwords <filter class="solr.ManagedSynonymFilterFactory" managed="product" /> // synonyms   Assign a name to the managed resource The managed attribute assigns a name to the resource, as shown in the preceding example. This is useful if you want to support multiple stop words or synonyms, such as for the domain, feature, or language.   Access the resource over REST endpoint /core/schema/analysis/stopwords/<name> // syntax /core/schema/analysis/stopwords/product // example

关于 REST 端点的完整列表和使用信息,请参考 Solr 手册 https://cwiki.apache.org/confluence/display/solr/Managed+Resources

solrconfig.xml 文件

Solr 支持无数的特性,并允许对这些特性进行广泛的定制和控制。您可以使用solrconfig.xml来定义和配置您想要在搜索解决方案中提供的特性,并通过更改 XML 来管理它的行为和属性。在solrconfig. xml中可以配置的重要特性如下:

  • 定义请求处理程序,该处理程序指定 REST 端点和在其上公开的相应 Solr 特性。例如,/select端点的所有请求处理搜索请求,而/update端点处理索引请求。
  • 定义搜索组件、更新请求处理器和查询解析器,并将它们配置到一个处理程序或其他可以链接它们的组件。假设您想在搜索引擎中启用点击突出显示功能。您可以通过定义突出显示组件、配置参数以实现所需的行为,并最终将其链接到搜索处理程序来实现这一点。
  • 配置 Solr 核心使用的路径和文件,例如模式文件的名称。
  • 配置其他核心级属性,如缓存、包含的库、自动提交、索引合并行为和复制。

solrconfig.xml在定义和公开特性方面提供了高度的灵活性。您定义和配置 Solr 提供的组件或您通过扩展 Solr 基类开发的定制组件,然后将它们组装在一起以快速公开一个特性。

Note

没有一章专门介绍solrconfig.xml支持的定义和配置。相反,当我们讨论 Solr 提供的一个特性或搜索功能时,您将了解它们。

常见问题

本节提供了开发人员在定义schema.xml.时经常问的一些问题的答案

我如何处理异常,指示 version field 必须存在于模式中?

SolrCloud 中的乐观并发需要_version_字段,它支持实时 get 操作。Solr 希望它在schema.xml中定义如下:

<field name="_version_" type="long" indexed="true" stored="true" />

建议在schema.xml中有这个字段,但是如果你仍然想禁用它,你可以在solrconfig.xmlupdateHandler部分注释掉updateLog声明。

<!--updateLog>

<str name="dir">${solr.ulog.dir:}</str>

<int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>

</updateLog-->

为什么我的模式更改没有反映在 Solr 中?

为了反映schema.xml中的变化,应该重新加载内核。如果某个字段的索引时处理发生了任何变化,所有文档也应该重新编制索引。

我在 Solr 5.0 中创建了一个核心,但是缺少 Schema.xml。我能在哪里找到它?

默认情况下,Solr 5.0 创建的核心是无模式的。它将managed-schema用于所有的模式定义。如果您想创建一个包含用于手工制作的schema.xml的型芯,请按如下步骤操作:

solr create -c corename -d sample_techproducts_configs

摘要

良好的模式设计是构建真正有效的搜索引擎的基本步骤之一。如果您知道数据的结构,模式设计应该总是在索引过程之前。尽管随着搜索引擎的发展,您可能需要回头调整模式,但第一次就做对总是好的。

Solr 提供了一组适用于大多数情况的fieldTypes,但是我们都有自己独特的挑战,这可能需要我们配置自己的分析链。正如您所看到的,将流程配置到链上很简单,因为所有 Solr 配置都是在 XML 文件中定义的,您只需要添加新元素并适当地映射它们。

一些文本分析过程在处理时间和索引大小方面都是很昂贵的,所以应该仔细定义链。此外,无论何时对字段的索引时间处理进行更改,都必须重新编制索引才能反映这些更改。

本章主要关注设计模式和文本分析。您了解了各种分析过程、它们的用途以及可以使用它们的场景。“无模式化”将在单独的章节中介绍。

通过这一章,你可以深入到期待已久的索引和搜索概念中。下一章将介绍索引过程,接下来的章节将介绍搜索和高级功能。

1 概述 4 1.1 企业搜索引擎方案选型 4 1.2 Solr的特性 4 1.2.1 Solr使用Lucene并且进行了扩展 4 1.2.2 Schema(模式) 5 1.2.3 查询 5 1.2.4 核心 5 1.2.5 缓存 5 1.2.6 复制 6 1.2.7 管理接口 6 1.3 Solr服务原理 6 1.3.1 索引 6 1.3.2 搜索 7 1.4 源码结构 8 1.4.1 目录结构说明 8 1.4.2 Solr home说明 9 1.4.3 solr的各包的说明 10 1.5 版本说明 11 1.5.1 1.3版本 11 1.5.2 1.4版本 12 1.6 分布式和复制 Solr 架构 13 2 Solr的安装与配置 13 2.1 在Tomcat下Solr安装 13 2.1.1 安装准备 13 2.1.2 安装过程 14 2.1.3 验证安装 15 2.2 中文分词配置 15 2.2.1 mmseg4j 15 2.2.2 paoding 19 2.3 多核(MultiCore)配置 22 2.3.1 MultiCore的配置方法 22 2.3.2 为何使用多core ? 23 2.4 配置文件说明 23 2.4.1 schema.xml 24 2.4.2 solrconfig.xml 25 3 Solr的应用 29 3.1 SOLR应用概述 29 3.1.1 Solr的应用模式 29 3.1.2 SOLR的使用过程说明 30 3.2 个简单的例子 30 3.2.1 Solr Schema 设计 30 3.2.2 构建索引 30 3.2.3 搜索测试 31 3.3 搜索引擎的规划设计 32 3.3.1 定义业务模型 32 3.3.2 定制索引服务 34 3.3.3 定制搜索服务 34 3.4 搜索引擎配置 34 3.4.1 Solr Schema 设计(如何定制索引的结构?) 34 3.5 如何进行索引操作? 36 3.5.1 基本索引操作 36 3.5.2 批量索引操作 37 3.6 如何进行搜索 39 3.6.1 搜索语法 39 3.6.2 排序 42 3.6.3 字段增加权重 42 3.6.4 Solr分词器、过滤器、分析器 42 3.6.5 Solr高亮使用 46 4 SolrJ的用法 46 4.1 搜索接口的调用实例 46 4.2 Solrj的使用说明 47 4.2.1 Adding Data to Solr 47 4.2.2 Directly adding POJOs to Solr 49 4.2.3 Reading Data from Solr 51 4.3 创建查询 51 4.4 使用 SolrJ 创建索引 52 4.5 Solrj包的结构说明 53 4.5.1 CommonsHttpSolrServer 53 4.5.2 Setting XMLResponseParser 53 4.5.3 Changing other Connection Settings 53 4.5.4 EmbeddedSolrServer 54 5 Solr的实际应用测试报告 54 5.1 线下压力测试报告 54 5.2 线上环境运行报告 54 6 solr性能调优 55 6.1 Schema Design Considerations 55 6.1.1 indexed fields 55 6.1.2 stored fields 55 6.2 Configuration Considerations 55 6.2.1 mergeFactor 55 6.2.2 mergeFactor Tradeoffs 56 6.3 Cache autoWarm Count Considerations 56 6.4 Cache hit rate(缓存命中率) 56 6.5 Explicit Warming of Sort Fields 56 6.6 Optimization Considerations 56 6.7 Updates and Commit Frequency Tradeoffs 56 6.8 Query Response Compression 57 6.9 Embedded vs HTTP Post 57 6.10 RAM Usage Considerations(内存方面的考虑) 57 6.10.1 OutOfMemoryErrors 57 6.10.2 Memory allocated to the Java VM 57 7 FAQ 58 7.1 出现乱码或者查不到结果的排查方法: 58
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值