在本文中,咱们将探讨一个Apache Solr搜索引擎中的基本概念 - 全文搜索。html
Apache Solr是一个开源框架,旨在处理数百万的文档。咱们将经过使用Java库- SolrJ的示例来介绍它的核心功能。git
因为Solr是开源的 - 咱们能够简单地下载二进制文件并在咱们的应用程序中单独启动服务器。github
要与服务器通讯,咱们将为SolrJ客户端定义Maven依赖项:数据库
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>6.4.2</version>
</dependency>复制代码
你将在这儿找到最新的依赖。apache
为了索引和搜索数据,咱们须要建立一个core
以及一个item
来索引数据。缓存
在咱们这样作以前,咱们须要在服务器上为数据创建索引,以便它能够搜索。服务器
咱们能够经过许多不一样的方式为数据创建索引。咱们可使用数据导入处理程序直接从关系数据库导入数据,使用Apache Tika经过Solr Cell上传数据或使用索引处理程序上传XML/ XSLT,JSON和CSV数据。框架
咱们能够经过建立SolrInputDocument将数据索引到核心。首先,咱们须要使用咱们的数据填充文档,而后只调用SolrJ的API为文档创建索引:maven
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更新该文档。ide
SolrJ提供了用于索引Java bean的API。要为bean创建索引,咱们须要使用@Field对其进行注解::
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();复制代码
搜索是Solr最强大的功能。咱们一旦在存储库中创建索引文档,咱们就能够根据关键字,短语,日期范围等进行搜索。结果按相关性(得分)排序。
服务器公开用于搜索操做的API。咱们能够调用/select或/query程序处理请求。
咱们来作一个简单的搜索:
SolrQuery query = new SolrQuery();
query.setQuery("brand1");
query.setStart(0);
query.setRows(10);
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);复制代码
SolrJ将在其对服务器的请求内部使用主查询参数q。返回记录的数量为10,未指定start和rows参数时,从0开始索引。
上面的搜索查询将查找在其任何索引字段中包含完整单词“brand1”的任何文档。请注意,简单搜索不区分大小写。
让咱们看另外一个例子。咱们想要搜索任何包含“rand”的单词,该单词以任意数量的字符开头,而且只以一个字符结尾。咱们能够在查询中使用*和?通配符:
query.setQuery("*rand?");复制代码
Solr查询还支持相似SQL中的布尔操做:
query.setQuery("brand1 AND (Washing OR Refrigerator)");复制代码
全部布尔运算符必须所有大写;查询解析器支持的是AND,OR,NOT,+和 - 。
更重要的是,若是咱们想要搜索特定字段而不是全部索引字段,咱们能够在查询中指定这些字段:
query.setQuery("description:Brand* AND category:*Washing*");复制代码
到目前为止,咱们只用代码在索引字段中查找关键字。咱们还能够对索引字段进行短语搜索:
query.setQuery("Washing Machine");复制代码
当咱们有一个像“Washing Machine”这样的短语时,Solr的标准查询解析器将其解析为“Washing OR Machine”。要搜索整个短语,咱们只能在双引号内添加表达式:
query.setQuery("\"Washing Machine\"");复制代码
咱们可使用邻近搜索来查找特定距离内的单词。若是咱们想要找到至少相距两个单词的短语,咱们可使用如下查询:
query.setQuery("\"Washing equipment\"~2");复制代码
范围查询容许获取其字段在特定范围之间的文档。假设咱们想要找到价格在100到300之间的商品:
query.setQuery("price:[100 TO 300]");复制代码
上面的查询将找到价格在100到300之间的全部元素,包括100和300。咱们可使用“}”和“{”来排除终点:
query.setQuery("price:{100 TO 300]");复制代码
筛选查询可用于限制可返回的结果的超集。过滤查询不会影响排序:
SolrQuery query = new SolrQuery();
query.setQuery("price:[100 TO 300]");
query.addFilterQuery("description:Brand1","category:Home Appliances");复制代码
一般,过滤器查询将包含经常使用查询。因为它们一般是可重用的,所以它们被缓存以使搜索更有效。
Faceting有助于将搜索结果安排到组计数中。咱们可使用字段,查询或范围。
例如,咱们但愿在搜索结果中获取聚合的类别计数。咱们能够在查询中添加类别字段:
query.addFacetField("category");
QueryResponse response = solrClient.query(query);
List<Count> facetResults = response.getFacetField("category").getValues();复制代码
facetResults将包含结果中每一个类别的计数。
当咱们想要返回子查询的计数时,查询切面很是有用:
query.addFacetQuery("Washing OR Refrigerator");
query.addFacetQuery("Brand2");
QueryResponse response = solrClient.query(query);
Map<String,Integer> facetQueryMap = response.getFacetQuery();复制代码
所以,facetQueryMap将具备facet查询的计数。
范围切面用于获取搜索结果中的范围计数。如下查询将返回介于100和251之间的价格范围计数,其间隔为25:
query.addNumericRangeFacet("price", 100, 275, 25);
QueryResponse response = solrClient.query(query);
List<RangeFacet> rangeFacets = response.getFacetRanges().get(0).getCounts();复制代码
除数值范围外,Solr还支持日期范围,区间切面和支点切面。
咱们可能但愿在搜索结果中突出显示搜索查询中的关键字。这对于更好地了解结果很是有帮助。让咱们索引一些文档并定义要突出显示的关键字:
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<String, Map<String, List<String>>> hitHighlightedMap = response.getHighlighting();
Map<String, List<String>> highlightedFieldMap = hitHighlightedMap.get("hm0001");
List<String> highlightedList = highlightedFieldMap.get("category");
String highLightedText = highlightedList.get(0);复制代码
咱们获取到的highLightedText为"Home Appliances
"。请注意,搜索关键字Appliances被标记。 Solr使用的默认突出显示标记是
,但咱们能够经过设置pre和post标记来更改它:
query.setHighlightSimplePre("<strong>");
query.setHighlightSimplePost("</strong>");复制代码
Solr支持的一个重要功能是建议。若是查询中的关键字包含拼写错误,或者咱们建议自动填写搜索关键字,咱们可使用建议功能。
标准搜索处理程序不包括拼写检查组件;它必须手动配置。有三种方法能够作到这一点。您能够在官方wiki page中找到配置详细信息。在咱们的示例中,咱们将使用IndexBasedSpellChecker,它使用索引数据进行关键字拼写检查。
让咱们搜索拼写错误的关键字:
query.setQuery("hme");
query.set("spellcheck", "on");
QueryResponse response = solrClient.query(query);
SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
Suggestion suggestion = spellCheckResponse.getSuggestions().get(0);
List<String> alternatives = suggestion.getAlternatives();
String alternative = alternatives.get(0);复制代码
关键字“hme”的预期替代应该是“home”,由于咱们的索引包含术语“home”。请注意,必须在执行搜索以前激活拼写检查。
咱们可能但愿得到不完整关键字的建议以协助搜索。 Solr的建议组件必须手动配置。您能够在其官方wiki page中找到配置详细信息。
咱们已经配置了一个名为/suggest的请求处理程序来处理建议。让咱们获得关键字“Hom”的建议:
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<String,List<String>> suggestedTerms = suggesterResponse.getSuggestedTerms();
List<String> suggestions = suggestedTerms.get("mySuggester");复制代码
列表建议应包含全部单词和短语。请注意,咱们在配置中配置了名为mySuggester的建议器。
本文简要介绍了搜索引擎的Solr功能和特性。
咱们谈到了许多功能,但这些固然只是表现了咱们可使用高级和成熟的搜索服务器(如Solr)所作的事情。
这里使用的示例能够在GitHub上使用。