大多数应用程序必须具有某种搜索功能。 问题在于搜索功能通常是巨大的资源消耗,它们可能通过给数据库造成沉重的负担而破坏我们应用程序的性能。 因此,将负载转移到外部搜索服务器是个好主意。
这是我的Spring Data Solr教程的第一部分。 在本教程中,我们将对todo应用程序实现搜索功能,这是我的Spring MVC Test教程的示例应用程序。
我们搜索功能的要求很简单。 它必须返回一个待办事项列表,其标题或说明包含使用的搜索词。 搜索结果
页面还必须提供指向用于查看待办事项信息的页面的链接。
在开始执行搜索功能之前,我们需要看一下Solr搜索服务器。 此博客条目为我们提供了有关Solr的基本信息,分为三个部分:
- 第一部分为我们简要介绍了Solr及其数据模型。
- 第二部分描述了如何为Solr实例创建模式。
- 最后一部分描述了如何使用Solr提供的类似REST的HTTP API。
让我们开始吧。
Solr简介
首先让我们简要介绍一下Solr搜索服务器。 本简介非常薄,仅提供我们需要了解的信息,以了解我们搜索功能的实现。
同样,即使Solr严重依赖Lucene ,此博客条目也没有区别。
本节介绍
- Solr搜索服务器的数据模型。
- 将新文档添加到Solr后会发生什么。
- 对索引数据执行搜索查询时会发生什么。
数据模型
索引由本质上是字段集合的文档组成。 如果我们将此数据模型与关系数据库的数据模型进行比较,则会发现以下相似之处:
- 索引与数据库表大致相同。
- 文档与数据库表的一行相似。
- 字段的含义与数据库表的列相同。
文档的每个字段都可以被索引 , 存储或两者都被索引 。 这些术语的含义如下所述:
- 索引字段是可搜索和可排序的字段。 在搜索结果中不返回索引字段。
- 存储的字段是在搜索结果中返回其值的字段。
- 如果一个字段既被索引又被存储 ,则该字段既可搜索又可排序。 其值也会在搜索结果中返回。
向索引添加信息
将新文档添加到Solr后,以不同的方式处理索引字段和存储字段。 下面描述了这种差异:
- 索引字段经过分析阶段,该阶段通常将文本分解为单词并对其应用不同的转换。 该分析阶段的结果将保存到Solr索引中。
- 存储的字段的值按原样保存。
从索引中搜索信息
搜索功能可分为以下三个步骤:
- 通常,搜索查询所经历的分析阶段与索引字段相似。 这样做的目的是确保搜索查询与索引的内容匹配。
- Solr使用其索引执行搜索。
- 匹配的文档以请求的格式返回。 每个文档都包含其存储字段的值。
创建模式
该架构用于配置以下内容:
- 文档的字段。
- 将新文档添加到索引时,如何处理文档的字段。
- 对索引执行搜索时如何处理字段。
该模式是在名为schema.xml的文件中配置的,我们可以按照以下步骤为我们的应用程序创建模式:
- 配置使用的字段类型。
- 配置我们文档的字段。
- 配置复制字段。
- 配置文档的唯一键字段。
在以下小节中将更详细地描述这些步骤。 Solr实例的框架架构如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="todo" version="1.5">
<fields>
<!-- Configure fields here -->
</fields>
<!-- Configure unique key -->
<!-- Configure copy fields here -->
<types>
<!-- Configure field types here -->
</types>
</schema>
注意 :本节描述了我的博客条目“ 使用Maven运行Solr ”的示例应用程序的架构。
配置字段类型
字段类型指定以下内容:
- 字段的数据类型。
- 将信息添加到索引后如何对其进行分析。
- 从索引中搜索信息时如何处理信息。
我们可以使用fieldType元素配置字段类型。 下面描述了在我们的模式中使用的其属性:
- name属性说明字段类型的名称。 它基本上是一个别名,用于声明字段的类型。
- class属性声明实现所涉及字段类型的类。
- sortMissingLast属性指定当缺少此字段的值时如何进行排序。 如果此属性的值设置为“ true”,则最后返回在相关字段中没有值的文档。
- positionIncrementGap属性声明在同一文档的多个字段之间放置的空白空间。 此属性的值用于多值字段,其思想是防止跨不同字段的错误匹配。
- precisionStep属性用于数字字段的范围查询。 通过阅读NumericRangeQuery类的API文档,我们可以获得有关此信息的更多信息。
我们可以按照以下步骤配置架构的字段类型:
- 配置长字段的字段类型
- 配置字符串字段的字段类型
- 为包含文本的字段配置字段类型
下面将更详细地描述这些步骤。
配置长字段的字段类型
让我们从为未在索引或搜索阶段进行分析的长字段配置简单字段类型开始。 我们可以按照以下步骤配置此字段类型:
- 将字段类型的名称设置为“ long”。
- 将实现类的名称设置为“ solr.TrieLongField”。
- 将precisionStep属性的值设置为零。
- 将positionIncrementGap属性的值设置为零。
我们的字段类型声明如下所示:
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
配置字符串字段的字段类型
下一步是为在索引或搜索阶段未分析的字符串字段配置简单的字段类型。 我们可以按照以下步骤配置此字段类型:
- 将字段类型的名称设置为“字符串”。
- 将实现类的名称设置为“ solr.StrField”。
- 将sortMissingLast属性的值设置为'true'。
我们的字符串字段的声明如下所示:
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
为包含文本的字段配置字段类型
最后一步是配置text_general字段类型。 我们可以按照以下步骤进行操作:
- 创建一个新的字段类型。 将字段类型的名称设置为“ text_general”。 将实现类的名称设置为“ solr.TextField”。 将positionIncrementGap的值设置为100。
- 创建一个在索引时间运行的新分析器。 使用Unicode文本分段算法的分词规则配置将文本分成单词。 创建一个过滤器,以从文本中删除从stopwords.txt文件中找到的单词。 将文本转换为小写。
- 创建一个在查询阶段运行的新分析器。 配置使用Unicode文本分段算法的分词规则将搜索查询分解为多个词 。 创建一个过滤器,以从搜索查询中删除从stopwords.txt文件中找到的单词。 确保已应用从onymous.txt找到的同义词 。 将搜索查询转换为小写。
text_general字段类型的声明如下所示:
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<!-- Configures the analysis done at the index phase -->
<analyzer type="index">
<!-- Uses word break rules of the Unicode Text Segmentation algorith when splitting text into words. -->
<tokenizer class="solr.StandardTokenizerFactory"/>
<!-- Removes words found from stopwords.txt file. This filter is case insensitive. -->
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<!-- Transforms text to lower case -->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<!-- Configures the analysis done at the query time -->
<analyzer type="query">
<!-- Uses word break rules of the Unicode Text Segmentation algorith when splitting text into words. -->
<tokenizer class="solr.StandardTokenizerFactory"/>
<!-- Removes words found from stopwords.txt file. This filter is case insensitive. -->
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
<!-- Applies synonyms found from the synonyms.txt file. -->
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<!-- Transforms text to lower case -->
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
通过阅读以下文档,我们可以获得有关分析阶段的更多信息:
配置文档的字段
我们可以通过向schema.xml文件中添加字段元素来向文档中添加新字段。 字段元素具有许多属性,但是在这一点上,我们需要了解以下属性的含义:
- name属性指定字段的名称。
- 索引属性(true / false)指定是否将字段添加到搜索索引中。 只有索引字段是可搜索和可排序的。
- 存储的属性(true / false)指定是否应在搜索结果中返回该字段。
- multiValued (true / false)指定该字段是否可以在文档中多次出现。
- type type属性指定字段的类型。
- 必填项 (是/否)指定是否需要该字段。
为了最大程度地发挥Solr实例的性能,我们必须遵循以下准则:
- 我们不应存储搜索结果中不需要的字段。
- 我们不应该为搜索功能未使用的字段建立索引。
通过阅读以下文档,我们可以获得有关最佳现场配置的更多信息:
现在,我们准备配置架构的实际字段。 让我们先谈谈我们需要在搜索结果页面上显示的信息。 下面描述了此信息:
- 我们需要待办事项条目的ID,用于创建指向视图待办事项条目页面的链接。
- 我们需要待办事项的标题,该标题用作已创建链接的锚文本。
当我们知道我们的应用程序必须能够搜索待办事项条目的标题和描述的内容时,可以按照以下步骤将所需字段添加到我们的模式中:
- 在架构中添加一个名为“ id”的必填字段,并将其类型设置为“ string”。 确保同时索引和存储该字段。 将multiValued属性的值设置为false。
- 在模式中添加一个名为“ title”的必填字段,并将其类型添加至“ text_general”。 将该字段配置为既索引又存储。 将多值属性的值设置为false。
- 添加一个名为“描述”的字段,该模式将其类型设置为“ text_general”。 配置此字段为索引但不存储。 将multiValued属性的值设置为false。
- 添加一个名为“ text”的字段,并将其类型设置为“ text_general”。 配置此字段为索引但不存储。 将其multiValue属性的值设置为true。 该字段是存储所有其他索引文本字段的内容的字段。
- 添加一个名为“ _version_”的字段,并将其类型设置为“ long”。 配置此字段以进行索引和存储。
我们的字段声明如下所示:
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="title" type="text_general" indexed="true" stored="true" required=“true” multiValued="false"/>
<field name="description" type="text_general" indexed="true" stored="false" multiValued="false"/>
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
<field name="_version_" type="long" indexed="true" stored="true"/>
配置复制字段
我们使用复制字段将标题和描述字段的内容复制到文本字段。 我们可以使用copyField元素配置复制字段。 我们可以按照以下步骤创建所需的配置:
- 创建一个复制字段,将“标题”字段的值复制到“文本”字段。
- 创建一个复制字段,将“说明”字段的值复制到“文本”字段。
我们的复制字段的声明如下所示:
<copyField source="title" dest="text"/>
<copyField source="description" dest="text"/>
配置文档的唯一键字段
唯一键是一个字段,该字段对于所有文档都是唯一的。 指定文档的唯一键不是强制性的,但是如果我们决定这样做,则意味着索引不能包含在配置为唯一键的字段中具有相同值的两个文档。
在本例中,我们将字段“ id”用作文档的唯一键。 我们可以通过将以下XML添加到schema.xml文件中来进行此配置:
<uniqueKey>id</uniqueKey>
使用类似REST的HTTP API
Solr提供了类似REST的HTTP API,我们可以使用它来向Solr添加信息并针对其索引执行搜索查询。 下面将描述这两种用例。
注意 :本部分假定我们正在使用我的博客条目“ 运行Solr和Maven”的示例应用程序。
向Solr添加信息
我们可以按照以下步骤向Solr添加新信息:
- 将POST请求发送到url'http:// localhost:8983 / solr / update / json?commit = true'。
- 将请求的内容类型设置为“ application / json”。
- 在请求的正文中以JSON发送添加的信息。
我们的请求正文的内容如下:
[
{
"id":"1",
"title":"Write introduction to Solr",
"description":"This blog entry provides an introduction to Solr search server"
},
{
"id":"2",
"title":"Implement example application",
"description":"This application demonstrates the usage of spring-data-solr."
}
]
现在,我们使用Solr提供的类似REST的API将两个文档添加到Solr索引中。
但是,很高兴知道还有其他选项可以用来向Solr索引添加信息。 以下文档中介绍了这些选项:
从Solr索引中搜索信息
现在,我们准备搜索存储在Solr实例索引中的信息。 我们可以按照以下准则对Solr索引执行搜索查询:
- 通过将GET请求发送到url'http:// localhost:8983 / solr / todo / select'来执行搜索查询。
- 查询字符串必须设置为q request参数的值。
- 查询结果的格式必须设置为wt request参数的值。
让我们继续前进,找出如何列出从索引中找到的所有文档,并对索引数据执行简单的搜索查询。
查找索引的所有文档
我们可以按照以下步骤列出所有JSON格式的文档:
- 将GET请求发送到网址“ http:// localhost:8983 / solr / todo / select”。
- 将q请求参数的值设置为'*。*'
- 将wt request参数的值设置为'json'。
当我们将GET请求发送到url'http:// localhost:8983 / solr / todo / select?q = *%3A *&wt = json'时,我们应该收到以下JSON:
{
"responseHeader": {
"status":0,
"QTime":1,
"params":{
"wt":"json",
"q":"*:*"
}
},
"response":{
"numFound":2,
"start":0,
"docs":[
{
"id":"1",
"title":"Write introduction to Solr",
"_version_":1425949176574771200
},
{
"id":"2",
"title":"Implement example application",
"_version_":1425949176662851584
}
]
}
}
从索引中搜索信息
我们可以按照以下步骤搜索标题或描述中包含“申请”一词的所有文档:
- 将GET请求发送到网址“ http:// localhost:8983 / solr / todo / select”。
- 将q请求参数的值设置为'application'
- 将wt request参数的值设置为'json'。
当我们发送GET请求到URL'http:// localhost:8983 / solr / todo / select?q = application&wt = json'时,我们应该收到以下JSON:
{
"responseHeader":{
"status":0,
"QTime":7,
"params":{
"wt":"json",
"q":"application"
}
},
"response":{
"numFound":1,
"start":0,
"docs":[
{
"id":"2",
"title":"Implement example application",
"_version_":1425949176662851584
}
]
}
}
结束
现在,我们已经获得了理解Spring Data Solr教程的下一部分中描述的概念所需的信息。 这篇博客文章教会了我们三件事:
- 我们了解Solr数据模型的基础。
- 我们知道如何配置Solr实例的架构。
- 我们知道如何使用Solr的HTTP API将文档添加到Solr索引并从中搜索信息。
翻译自: https://www.javacodegeeks.com/2013/05/spring-data-solr-tutorial-introduction-to-solr.html