## 1. 概述

在本文中,我们将探讨一个[Apache Solr](http://lucene.apache.org/solr/)搜索引擎中的基本概念 - 全文搜索。

Apache Solr是一个开源框架,旨在处理数百万的文档。我们将通过使用Java库- [SolrJ](https://wiki.apache.org/solr/Solrj)的示例来介绍它的核心功能。

## 2. maven配置

由于Solr是开源的 - 我们可以简单地下载二进制文件并在我们的应用程序中单独启动服务器。

要与服务器通信,我们将为SolrJ客户端定义Maven依赖项:

```java

org.apache.solr
solr-solrj
6.4.2

```

你将在[这儿](https://search.maven.org/classic/#search|ga|1|g%3A"org.apache.solr" AND a%3A"solr-solrj")找到最新的依赖。

## 3. 索引数据

为了索引和搜索数据,我们需要创建一个`core`以及一个`item`来索引数据。

在我们这样做之前,我们需要在服务器上为数据建立索引,以便它可以搜索。

我们可以通过许多不同的方式为数据建立索引。我们可以使用数据导入处理程序直接从关系数据库导入数据,使用Apache Tika通过Solr Cell上传数据或使用索引处理程序上传XML/ XSLT,JSON和CSV数据。

### 3.1 索引Solr文档

我们可以通过创建SolrInputDocument将数据索引到核心。首先,我们需要使用我们的数据填充文档,然后只调用SolrJ的API为文档建立索引:

```java
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", id);
doc.addField("description", description);
doc.addField("category", category);
doc.addField("price", price);
solrClient.add(doc);
solrClient.commit();
```

请注意,id对于不同的item应该是唯一的。已建立索引的文档根据ID更新该文档。

### 3.2 索引 Beans

SolrJ提供了用于索引Java bean的API。要为bean建立索引,我们需要使用@Field对其进行注解::

```java
public class Item {

@Field
private String id;

@Field
private String description;

@Field
private String category;

@Field
private float price;
}
```

一旦我们添加bean,索引就已经建立好:

```
solrClient.addBean(item);
solrClient.commit();
```

## 4. Solr查询

搜索是Solr最强大的功能。我们一旦在存储库中建立索引文档,我们就可以根据关键字,短语,日期范围等进行搜索。结果按相关性(得分)排序。

### 4.1 基本查询

服务器公开用于搜索操作的API。我们可以调用/select或/query程序处理请求。

我们来做一个简单的搜索:

```java
SolrQuery query = new SolrQuery();
query.setQuery("brand1");
query.setStart(0);
query.setRows(10);

QueryResponse response = solrClient.query(query);
List items = response.getBeans(Item.class);
```

SolrJ将在其对服务器的请求内部使用主查询参数q。返回记录的数量为10,未指定start和rows参数时,从0开始索引。

上面的搜索查询将查找在其任何索引字段中包含完整单词“brand1”的任何文档。请注意,简单搜索不区分大小写。

让我们看另一个例子。我们想要搜索任何包含“rand”的单词,该单词以任意数量的字符开头,并且只以一个字符结尾。我们可以在查询中使用*和?通配符:

```java
query.setQuery("*rand?");
```

Solr查询还支持类似SQL中的布尔操作:

```java
query.setQuery("brand1 AND (Washing OR Refrigerator)");
```

所有布尔运算符必须全部大写;查询解析器支持的是AND,OR,NOT,+和 - 。

更重要的是,如果我们想要搜索特定字段而不是所有索引字段,我们可以在查询中指定这些字段:

```java
query.setQuery("description:Brand* AND category:*Washing*");
```

### 4.2 短语查询

到目前为止,我们只用代码在索引字段中查找关键字。我们还可以对索引字段进行短语搜索:

```java
query.setQuery("Washing Machine");
```

当我们有一个像“Washing Machine”这样的短语时,Solr的标准查询解析器将其解析为“Washing OR Machine”。要搜索整个短语,我们只能在双引号内添加表达式:

```java
query.setQuery("\"Washing Machine\"");
```

我们可以使用邻近搜索来查找特定距离内的单词。如果我们想要找到至少相距两个单词的短语,我们可以使用以下查询:

```java
query.setQuery("\"Washing equipment\"~2");
```

### 4.3 范围查询

范围查询允许获取其字段在特定范围之间的文档。
假设我们想要找到价格在100到300之间的商品:

```java
query.setQuery("price:[100 TO 300]");
```

上面的查询将找到价格在100到300之间的所有元素,包括100和300。我们可以使用“}”和“{”来排除终点:

```java
query.setQuery("price:{100 TO 300]");
```

### 4.4 过滤查询

筛选查询可用于限制可返回的结果的超集。过滤查询不会影响排序:

```java
SolrQuery query = new SolrQuery();
query.setQuery("price:[100 TO 300]");
query.addFilterQuery("description:Brand1","category:Home Appliances");
```

通常,过滤器查询将包含常用查询。由于它们通常是可重用的,因此它们被缓存以使搜索更有效。

## 5. 分面搜索

Faceting有助于将搜索结果安排到组计数中。我们可以使用字段,查询或范围。

### 5.1. Field 切面

例如,我们希望在搜索结果中获取聚合的类别计数。我们可以在查询中添加类别字段:

```java
query.addFacetField("category");

QueryResponse response = solrClient.query(query);
List facetResults = response.getFacetField("category").getValues();
```

facetResults将包含结果中每个类别的计数。

### 5.2. 切面查询

当我们想要返回子查询的计数时,查询切面非常有用:

```java
query.addFacetQuery("Washing OR Refrigerator");
query.addFacetQuery("Brand2");

QueryResponse response = solrClient.query(query);
Map facetQueryMap = response.getFacetQuery();
```

因此,facetQueryMap将具有facet查询的计数。

### 5.3. 范围切面

范围切面用于获取搜索结果中的范围计数。以下查询将返回介于100和251之间的价格范围计数,其间隔为25:

```java
query.addNumericRangeFacet("price", 100, 275, 25);

QueryResponse response = solrClient.query(query);
List rangeFacets = response.getFacetRanges().get(0).getCounts();
```

除数值范围外,Solr还支持日期范围,区间切面和支点切面。

## 6. 突出显示

我们可能希望在搜索结果中突出显示搜索查询中的关键字。这对于更好地了解结果非常有帮助。让我们索引一些文档并定义要突出显示的关键字:

```java
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f);

SolrQuery query = new SolrQuery();
query.setQuery("Appliances");
query.setHighlight(true);
query.addHighlightField("category");
QueryResponse response = solrClient.query(query);

Map>> hitHighlightedMap = response.getHighlighting();
Map> highlightedFieldMap = hitHighlightedMap.get("hm0001");
List highlightedList = highlightedFieldMap.get("category");
String highLightedText = highlightedList.get(0);
```

我们获取到的highLightedText为"`Home Appliances `"。请注意,搜索关键字Appliances被``标记。 Solr使用的默认突出显示标记是``,但我们可以通过设置pre和post标记来更改它:

```java
query.setHighlightSimplePre("");
query.setHighlightSimplePost("
");
```

## 7. 搜索建议

Solr支持的一个重要功能是建议。如果查询中的关键字包含拼写错误,或者我们建议自动填写搜索关键字,我们可以使用建议功能。

### 7.1. 拼写检查

标准搜索处理程序不包括拼写检查组件;它必须手动配置。有三种方法可以做到这一点。您可以在官方[wiki page](https://lucene.apache.org/solr/guide/6_6/spell-checking.html)中找到配置详细信息。在我们的示例中,我们将使用IndexBasedSpellChecker,它使用索引数据进行关键字拼写检查。

让我们搜索拼写错误的关键字:

```java
query.setQuery("hme");
query.set("spellcheck", "on");
QueryResponse response = solrClient.query(query);

SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
Suggestion suggestion = spellCheckResponse.getSuggestions().get(0);
List alternatives = suggestion.getAlternatives();
String alternative = alternatives.get(0);
```

关键字“hme”的预期替代应该是“home”,因为我们的索引包含术语“home”。请注意,必须在执行搜索之前激活拼写检查。

### 7.2. 自动建议条件

我们可能希望获得不完整关键字的建议以协助搜索。 Solr的建议组件必须手动配置。您可以在其官方[wiki page](https://cwiki.apache.org/confluence/display/solr/Suggester)中找到配置详细信息。

我们已经配置了一个名为/suggest的请求处理程序来处理建议。让我们得到关键字“Hom”的建议:

```java
SolrQuery query = new SolrQuery();
query.setRequestHandler("/suggest");
query.set("suggest", "true");
query.set("suggest.build", "true");
query.set("suggest.dictionary", "mySuggester");
query.set("suggest.q", "Hom");
QueryResponse response = solrClient.query(query);

SuggesterResponse suggesterResponse = response.getSuggesterResponse();
Map> suggestedTerms = suggesterResponse.getSuggestedTerms();
List suggestions = suggestedTerms.get("mySuggester");
```

列表建议应包含所有单词和短语。请注意,我们在配置中配置了名为mySuggester的建议器。

## 8. 结束语

本文简要介绍了搜索引擎的Solr功能和特性。

我们谈到了许多功能,但这些当然只是表现了我们可以使用高级和成熟的搜索服务器(如Solr)所做的事情。

这里使用的示例可以在[GitHub](https://github.com/eugenp/tutorials/tree/master/persistence-modules/solr)上使用。

Solr 全文搜索的更多相关文章

  1. 项目之solr全文搜索工具之创建项目索引库

    以创建项目baotao core为例 1.  在example目录下创建baotao-solr文件夹: 2.  将./solr下的solr.xml拷贝到baotao-solr目录下: 3.  在bao ...

  2. 项目之solr全文搜索工具的安装

    1. Solr简介 Solr是一个基于Lucene的Java搜索引擎服务器.Solr 提供了层面搜索.命中醒目显示并且支持多种输出格式(包括 XML/XSLT 和 JSON 格式).它易于安装和配置, ...

  3. Apache Solr采用Java开发、基于Lucene的全文搜索服务器

    http://docs.spring.io/spring-data/solr/ 首先介绍一下solr: Apache Solr (读音: SOLer) 是一个开源.高性能.采用Java开发.基于Luc ...

  4. 全文搜索技术—Solr

    1.   学习计划 1. Solr的安装及配置 a)    Solr整合tomcat b)    Solr后台管理功能介绍 c)    配置中文分析器 2. 使用Solr的后台管理索引库 a)     ...

  5. Solr实现全文搜索

    1.1 Solr是什么? Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器.Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置.可扩展 ...

  6. lucene全文搜索之一:lucene的主要功能和基本结构(基于lucene5.5.3)

    前言:lucene并不是像solr或elastic那样提供现成的.直接部署可用的系统,而是一套jar包,提供了一些常见语言分词.构建索引和创建搜索器等等功能的API,我们常用到的也就是分词器.索引目录 ...

  7. Postgres全文搜索功能

    当构建一个Web应用时,经常被要求加上搜索功能.其实有时候我们也不知道我要搜索个啥,反正就是要有这个功能.搜索确实很重要的特性,这也是为什么像Elasticsearch和Solr这样基于Lucene的 ...

  8. SpringBoot实现全文搜索

    • 全文搜索  • solr安装  • solr中文分词  • solr数据库导入  • solr数据查询  • solrj接口调用     1:

  9. SQL Server 全文搜索

    SQL Server 的全文搜索(Full-Text Search)是基于分词的文本检索功能,依赖于全文索引.全文索引不同于传统的平衡树(B-Tree)索引和列存储索引,它是由数据表构成的,称作倒转索 ...

随机推荐

  1. 创建hexo风格的markdown页面

    最近在用 nodejs 搭建一个个人博客,博客当然要有编辑文章的功能啦.个人比较偏爱 hexo 风格的 markdown 格式,所以想自己的博客也是这样的风格.尝试了几个库,发现 marked 的转换 ...

  2. SQLServer 远程服务器不存在,未被指定为有效的发布服务器,或您无权查看可用的发布服务器

    原文:SQLServer 远程服务器不存在,未被指定为有效的发布服务器,或您无权查看可用的发布服务器 创建了事务发布,在初始化时出现错误,查看相关代理信息如下: 日志读取器代理错误: 状态: 0,代码 ...

  3. Android 9.0 Dialog不显示

    Tester报了一个bug,大概如下: 页面:Activity1 dialog1(半透明遮罩样式) Activity2 dialog2 场景:Activity1弹出dialog1,dialog1弹出a ...

  4. 使用ArcGIS Server发布我们的数据

    原文:使用ArcGIS Server发布我们的数据 引言 上一篇我们已经安装好了ArcGIS体系的服务软件,这一篇将介绍如何把我们自己的数据通过ArcGIS Server发布出去,并且能够通过Web页 ...

  5. Android零基础入门第54节:视图切换组件ViewSwitcher

    原文:Android零基础入门第54节:视图切换组件ViewSwitcher 前面三期学习了ProgressBar系列组件,那本期开始一起来学习ViewAnimator组件. 一.ViewAnimat ...

  6. UWP入门(七)--SplitView详解与页面跳转

    原文:UWP入门(七)--SplitView详解与页面跳转 官方文档,逼着自己用英文看,UWP开发离不开官方文档 1. SplitView 拆分视图控件 拆分视图控件具有一个可展开/可折叠的窗格和一个 ...

  7. linux下编译qt5.6.0静态库(使用./configure --help来看看都有哪些参数。超详细,有每一个模块的说明。如果改变了安装的目录,需要到安装目录下的bin目录下创建文件qt.conf)(乌合之众)good

    linux下编译qt5.6.0静态库 linux下编译qt5.6.0静态库 configure生成makefile 安装选项 Configure选项 第三方库: 附加选项: QNX/Blackberr ...

  8. Notepad2(C语言+Windows消息写的,24592行代码)

    C语言+Windows消息写的,24592行代码 http://www.flos-freeware.ch/

  9. SPOJ130_Rent your airplane and make money_单调队列DP实现

    题意比较简单,状态转移方程也比较容易得出: f[i]=max{ f [ j ] }+p[i],(j的结束时间在i开始时间之前) 若i开始之前没有结束的j,则f[i]=p[i]; 因数据量太大(n< ...

  10. python中的内置函数(2)

    一.lambda匿名函数定义:为了解决一些简单的需求而设计的一句话函数例子:计算n的n次方 def func(n):#正常的写法 return n**2 f=lambda n:n**2 这里的lamb ...