数据库组合索引全文索引
有没有想过搜索引擎如何工作? 在这篇文章中,我想向您展示搜索引擎内部运作的高级视图,以及如何使用它来快速访问您的数据。 我将不涉及任何技术细节,我在此描述的内容适用于任何基于Lucene的搜索引擎,无论是Lucene本身, Solr还是Elasticsearch 。
输入项
通常,搜索引擎与索引数据的实际数据源无关。 大多数情况下,您是通过已经需要采用预期格式的API将数据推送到其中的,其中大多数是字符串和数据类型(例如整数)。 这些数据最初是驻留在文件系统,网站还是数据库中的文档中都没有关系。
搜索引擎正在处理包含字段和值的文档。 尽管不总是直接使用,但您可以将文档视为JSON文档。 想象一下,对于这个帖子,我们正在构建一个图书数据库。 在我们的简化世界中,一本书仅包含一个标题和一个或多个作者。 这将是两个示例文档:
{
"title" : "Search Patterns",
"authors" : [ "Morville", "Callender" ],
}
{
"title" : "Apache Solr Enterprise Search Server",
"authors" : [ "Smiley", "Pugh" ]
}
即使在我们的案例中两个文档的结构相同,也不需要固定文档的格式。 两个文档可能具有完全不同的属性,但是都可以存储在同一索引中。 实际上,您将尝试使文档保持相似,毕竟,您需要一种在应用程序中处理文档的方法。
Lucene本身甚至没有密钥的概念。 但是,当然,您需要一个密钥来在更新文档时标识您的文档。 Solr和Elasticsearch都具有可以由应用程序选择或自动生成的ID。
分析
对于被索引的每个字段,都使用一种称为分析的特殊过程。 它的作用因现场而异。 例如,在一个简单的情况下,它可能只是在空白处拆分了术语并删除了所有标点符号,因此搜索模式将变成两个术语Search和Patterns 。
索引结构
搜索引擎使用的结构的倒排索引类似于包含搜索项作为键和对文档的引用作为值的地图。 这样,搜索过程只是对索引中术语的查找,这是一个非常快速的过程。 这些可能是为我们的示例文档建立索引的术语。
领域 | 术语 | 文件编号 |
标题 | 阿帕奇 | 2 |
企业 | 2 | |
模式 | 1个 | |
搜索 | 1,2 | |
服务器 | 2 | |
索尔 | 2 | |
作者 | 来电者 | 1个 |
莫维尔 | 1个 | |
普格 | 2 | |
笑脸 | 2 |
真实索引包含更多信息,例如位置信息,以启用短语查询和频率来计算特定搜索词的文档相关性。
如我们所见,索引包含对该文档的引用。 该文档(也与搜索索引一起存储)不一定与我们的输入文档相同。 您可以为每个字段确定是否要保留通常由名为存储的属性控制的原始内容。 通常,应该存储要与搜索结果一起显示的所有字段。 为很多完整的书编制索引时,您不需要在结果页中显示它,最好根本不存储它。 您仍然可以搜索它,因为索引中有这些术语,但是您无法访问原始内容。
有关分析的更多信息
通过上面的索引结构,我们已经可以想象一本书的搜索过程如何工作。 用户输入一个术语,例如Solr ,然后使用该术语来查找包含该术语的文档。 在用户正确键入术语的情况下,此方法很好用。 搜索solr与我们当前的示例不匹配。
为了减轻这些困难,我们可以使用上面已经提到的分析过程。 除了将字段值拆分为令牌的令牌化之外,我们还可以进行进一步的预处理,例如删除令牌,添加令牌或修改令牌(TokenFilter)。
对于我们的书架来说,一开始可能只需对输入的数据进行小写即可。 因此,字段值Solr将作为solr存储在索引中。 为了使用户还可以使用大写字母搜索Solr ,我们还需要对查询进行分析。 通常,它是与用于索引编制的过程相同,但也有一些情况适用于不同的分析仪。
分析过程不仅取决于文档的内容(字段类型,文本字段的语言),还取决于您的应用程序。 采取一种常见的情况:向索引添加术语的同义词。 您可能会认为您只是拿了一个庞大的同义词列表,如WordNet ,并将其添加到每个应用程序中。 实际上,由于误报过多,这可能会降低用户的搜索体验。 此外,对于用户域的某些术语,WordNet可能根本不包含正确的同义词。
复制
设计索引结构时,有两个竞争因素:通常,您要么针对查询速度进行优化,要么针对索引大小进行优化。 如果您有大量数据,则可能需要注意,您仅存储真正需要的数据,甚至只将查找所必需的术语放在索引中。 通常,对于较小的数据集,索引大小并不重要,您可以设计查询性能的索引。
让我们看一个对两种情况都有意义的示例。 在我们的图书信息系统中,我们希望显示作者姓氏的字母导航。 如果用户单击A,则应显示所有以字母A开头的作者的书籍。 使用Lucene查询语法时,您可以通过通配符支持执行以下操作:只需发出包含用户单击的字母和后缀*的查询,例如a *即可 。
使用最新的Lucene版本,通配符查询已变得非常快,尽管如此,这仍然是查询时间的影响。 您也可以选择其他方式。 为数据建立索引时,您可以添加另一个仅存储名称首字母的字段。 这是在Elasticsearch中相关配置可能看起来的样子,但是Lucene和Solr的概念是相同的:
"author": {
"type": "multi_field",
"fields": {
"author" : {
"type": "string"
},
"letter" : {
"type": "string",
"analyzer": "single_char_analyzer"
}
}
}
在后台,将为字段author.letter创建另一个术语词典。 对于我们的示例,它将如下所示:
领域 | 术语 | 文件编号 |
作者信 | C | 1个 |
中号 | 1个 | |
P | 2 | |
小号 | 2 |
现在,无需在author字段上发出通配符查询,我们可以直接使用字母查询author.letter字段。 您甚至可以使用诸如刻面提取索引中字段的所有可用术语之类的技术,从索引中的所有术语构建导航。
结论
这些是搜索引擎索引数据的基础。 倒排索引结构通过将一些处理移到索引阶段,从而使搜索真正变得非常快。 当我们不受任何索引大小问题的束缚时,我们可以设计索引以提高查询性能,并添加其他字段来复制某些数据。 查询的这种设计使搜索引擎类似于使用了多少NoSQL解决方案。
如果您想更深入地研究主题,我建议您观看Adrien Grand的演讲“ Lucene索引中的内容”。 他展示了我在这里提到的一些概念(以及更多),以及在Lucene中如何实现这些概念。
翻译自: https://www.javacodegeeks.com/2014/05/the-absolute-basics-of-indexing-data.html
数据库组合索引全文索引