Solr

1.1 需求

1.2 实现方式

在一些大型门户网站、电子商务网站等都需要站内搜索功能,使用传统的数据库查询方式实现搜索无法满足一些高级的搜索需求,比如:搜索速度要快、搜索结果按相关度排序、搜索内容格式不固定等,这里就需要使用全文检索技术实现搜索功能。

1.2.1使用Lucene实现

单独使用Lucene实现站内搜索需要开发的工作量较大,主要表现在:索引维护、索引性能优化、搜索性能优化等,因此不建议采用。

1.2.2使用Solr实现

  基于Solr实现站内搜索扩展性较好并且可以减少程序员的工作量,因为Solr提供了较为完备的搜索引擎解决方案,因此在门户、论坛等系统中常用此方案。

 

 

 

 

 

 

 

 

 

2 solr简介

2.1 Solr基本概况

 

SolrSearch On Lucene Replication Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。

Solr可以独立运行,运行在JettyTomcat等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引 。Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xmljson等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。

官方网站:http://lucene.apache.org/solr/features.html

 

 

2.2 Solr的历史

l 2004CNET 开发 Solar,为 CNET 提供站内搜索服务

l 20061月捐献给 Apache ,成为 Apache 的孵化项目

一年后 Solr 孵化成熟,发布了1.2版,并成为 Lucene 的子项目

l 20106月,solr 发布了的1.4.1版,这是1.4bugfix 版本,1.4.1solr使用的lucene2.9版本的

l solr 1.4.x版本以后,为了保持和lucene同步的版本,solr直接进入3.0版本。

2.3 Solr运行结构图

Solr的目标是打造一款企业级的搜索引擎系统,它是一个搜索引擎服务,可以独立运行,通过Solr可以非常快速的构建企业的搜索引擎,通过Solr也可以高效的完成站内搜索功能。

 

3.Solr的环境准备

3.1 Solr的下载

Solr官方网站(http://lucene.apache.org/solr/)下载Solr4.10.3,根据Solr的运行环境,Linux下需要下载solr-4.10.3.tgzwindows下需要下载solr-4.10.3.zip

Solr使用指南可参考:https://wiki.apache.org/solr/FrontPage

 

 

 

 

3.2 Solr开发包的目录结构

 

binsolr的运行脚本

contribsolr的一些扩展jar包,用于增强solr的功能。

dist:该目录包含build过程中产生的warjar文件,以及相关的依赖文件。

docssolrAPI文档

examplesolr工程的例子目录:

example/solr

该目录是一个标准的SolrHome,它包含一个默认的SolrCore

example/multicore

该目录包含了在Solrmulticore中设置的多个Core目录。

example/webapps

    该目录中包括一个solr.war,该war可作为solr的运行实例工程。

licensessolr相关的一些许可信息

3.3 Solr的运行环境

solr 需要运行在一个Servlet容器中,Solr4.10.3要求jdk使用1.7以上,Solr默认提供Jettyjava写的Servlet容器),本教程使用Tocmat作为Servlet容器,相关环境如下:

l Solr4.10.3

l Jdk环境1.7.0_72solr4.10 不能使用jdk1.7以下

l Web服务器(servlet容器):Tomcat 7X

l Mysql5X

 

4 安装和配置

4.1 安装

第一步:安装tomcat

 

第二步:将以下的war包,拷贝到tomcat的webapps目录下

 

第三步:解压缩war包,解压缩之后,将war包删掉

 

第四步:添加solr的扩展服务包

 

将以上jar包,添加到以下目录

 

第五步:添加log4j.properties 将以下目录的文件进行拷贝

 

复制到以下目录

 

 

第六步:在web.xml中指定solrhome的目录

 

 

4.2 solrhome

SolrHome是Solr运行的主目录,该目录中包括了多个SolrCore目录。SolrCore目录中包含了运行Solr实例所有的配置文件和数据文件,Solr实例就是SolrCore

一个SolrHome可以包括多个SolrCore(Solr实例),每个SolrCore提供单独的搜索和索引服务。(类似于MySQL数据库服务器可以创建多个数据库)

 

4.2.1 solrhome的目录结构

 

把内容拷贝到自己创建的solrhome目录中

 

 

SolrCore目录:

 

SolrCore创建成功。

 

 

 

 

5 启动和访问

  • 启动TomCat

 

 

Solr本地安装成功!

 

 

5.1 管理界面介绍

 

Dashboard

 

仪表盘,显示了该Solr实例开始启动运行的时间、版本、系统资源、jvm等信息。

 

Logging

 

Solr运行日志信息

 

Cloud

 

CloudSolrCloud,即Solr云(集群),当使用Solr Cloud模式运行时会显示此菜单.

 

Core Admin

 

Solr Core的管理界面。在这里可以添加SolrCore实例。

 

java properties

 

SolrJVM 运行环境中的属性信息,包括类路径、文件编码、jvm内存设置等信息。

 

Tread Dump

显示Solr Server中当前活跃线程信息,同时也可以跟踪线程运行栈信息。

 

 

 

5.2 Core selector(重点)

选择一个SolrCore进行详细操作,如下:

 

5.2.1 Analysis

 

通过此界面可以测试索引分析器和搜索分析器的执行情况。

注:solr中,分析器是绑定在域的类型中的。在schame.xml可以进行配置。

5.2.2 Dataimport

可以定义数据导入处理器,从关系数据库将数据导入到Solr索引库中。

默认没有配置,需要手工配置。(不用了)

5.2.3 Document

通过/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新

通过此菜单可以创建索引、更新索引、删除索引等操作,界面如下:

 

 

 

 

l overwrite="true" : solr在做索引的时候,如果文档已经存在,就用xml中的文档进行替换

l commitWithin="1000" : solr 在做索引的时候,每个1000(1秒)毫秒,做一次文档提交。为了方便测试也可以在Document中立即提交, </doc>后添加“<commit/>”

5.2.4 Query

通过/select执行搜索索引,必须指定“q”查询条件方可搜索。

 

 

 

 

查询结果视图

 

5.3 SolrCorecollection的配置

5.3.1 好处

  1. 一个solr工程对外通过SorlCore 提供服务,每个SolrCore相当于一个数据库,这个功能就相当于一个mysql可以运行多个数据库。
  2. 将索引数据分SolrCore存储,方便对索引数据管理维护。
  3. SolrCloud集群需要使用多core。
  4. 在进行solrcloud的时候,必须配置多solrcore
  5. 每个solrcore之间是独立的,都可以单独对外提供服务。不同的业务模块可以使用不同的solrcore来提供搜索和索引服务。

5.3.2 步骤

复制原来的core目录为collection2,目录结构如下:

 

第二步:修改solrcore目录下的core.properties

 

 

这样多solrcore就配置完成了,在Web显示可以验证

 

5.4 配置中文分词器

选用ikanalyzer进行中文分词

第一步ikanalyzerjar包拷贝到以下目录

 

第二步:将ikanalyzer的扩展词库的配置文件拷贝到目录

 

第三步:在schema.xml中添加一个自定义的fieldType,使用中文分析器。(solrcore)

 

  

<!-- IKAnalyzer-->

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

      <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>

    </fieldType>

 

第四步:定义field,指定fieldtype属性为text_ik

 

 

<!--IKAnalyzer Field-->

<field name="content_ik" type="text_ik" indexed="true" stored="true" />

 

第五步重启tomcat, 测试中文分词奏效.

 

 

 

6 solr基础使用

 

6.3 配置域(field

案例中的products表的数据进行索引所以需要先定义对应的Field

要使用solr实现电商网站中商品搜索。电商中商品信息在mysql数据库中存储了,将mysql数据库中数据在solr中创建索引。需要在solrschema.xml文件定义商品Field

 

    schame.xml中配置域

 

定义Field域

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />

l Name:域的名称

l Type:域的类型

l Indexed:是否索引

l Stored:是否存储

l Required:是否必须

l multiValued:是否是多值,存储多个值时设置为true,solr允许一个Field存储多个值,比如存储一个用户的好友id(多个),商品的图片(多个,大图和小图)

 

先确定定义的商品document的field有哪些?

可以根据mysql数据库中商品表的字段来确定:

 

  • Products表的结构:

 

需要往索引库添加的字段有

pid、name、catalog、catalog_namepricedescriptionpicture

 

  • FieldType

经分析,由于中文分词器已经配置完FieldType,所以目前FieldType已经满足需要,无需配置。

  • Field

Pid:

由于pid在products表中是唯一键,而且在solr的shema.xml中已有一个id的唯一键配置,所以不需要再重新定义pid域。

<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />

 

Name:

<!-- 商品名称 -->

<field name="product_name" type="text_ik" indexed="true" stored="true"/>

此处 <field>标签中name属性值的配置,并不是数据库表中的字段值,而是在data-config.xml中配置的对应。

 

 

 

Catalog、catalog_name:

<!-- 商品分类ID -->

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

<!-- 商品分类名称 -->

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

 

Price:

<!-- 商品价格 -->

<field name="product_price" type="float" indexed="true" stored="true"/>

 

Description:

<!-- 商品描述 -->

<field name="product_description" type="text_ik" indexed="true" stored="false"/>

 

Picture:

<!-- 商品图片地址 -->

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

 

<!--product-->

   <!-- 商品名称 -->

   <field name="product_name" type="text_ik" indexed="true" stored="true"/>

   <!-- 商品分类ID -->

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

   <!-- 商品分类名称 -->

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

   <!-- 商品价格 -->

   <field name="product_price" type="float" indexed="true" stored="true"/>

   <!-- 商品描述 -->

   <field name="product_description" type="text_ik" indexed="true" stored="false"/>

   <!-- 商品图片地址 -->

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

 

<!-- 目标域 -->

   <field name="product_keywords" type="text_ik" indexed="true" stored="true" multiValued="true"/>

   

   <!--将商品名称添加到目标域 -->

   <copyField source="product_name" dest="product_keywords"/>

   

   <!--将商品描述添加到目标域 -->

   <copyField source="product_description" dest="product_keywords"/>

 

注意:其实应该在配置完域后,再把数据库的中的数据导入到索引库!!!(重启tomcat,执行导入操作)

导入完成后,执行查询,将会看到数据库中的全部数据都被导入到了索引库中。

 

 

而且,在

 

中,可以看到如此界面。

7 solrj的使用

7.1 什么是solrj

solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常在嵌入在业务系统中,通过SolrJAPI接口操作Solr服务,如下图:

 

 Solrj和图形界面操作的区别就类似于数据库中你使用jdbcmysql客户端的区别一样

 

7.2 solrj的环境准备

l Solr4.10.3

l Jdk环境1.7.0_72solr4.10 不能使用jdk1.7以下

l Ide环境:eclipse (MyEclipse)

 

7.3 solrj环境搭建

 

7.3.1 新建Java工程

 

7.3.2 导入Solr所需要的Jar包

l Solrj的依赖包和核心包

 

 

l Solr服务的依赖包

 

 

 

 

7.4 代码实现

7.4.1 添加\修改索引

核心步骤:

1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

2、 创建SolrInputDocument对象,然后通过它来添加域。

3、 通过HttpSolrServer对象将SolrInputDocument添加到索引库。

4、 提交。

 

  • 代码实现:

 

@Test

public void addDocument() throws Exception {

// 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

// 参数:solr服务器的访问地址

HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/");

// 2、 创建SolrInputDocument对象,然后通过它来添加域。

SolrInputDocument document = new SolrInputDocument();

// 第一个参数:域的名称,域的名称必须是在schema.xml中定义的

// 第二个参数:域的值

// 注意:id的域不能少

document.addField("id", " ");

document.addField("name", "使用solrJ添加的文档,这是一个测试。");

document.addField("description", "文档的内容,这是一个测试。");

// 3、 通过HttpSolrServer对象将SolrInputDocument添加到索引库。

server.add(document);

// 4、 提交

server.commit();

System.out.println("索引添加或者更新完成!");

}

 

  • 测试查询:

 

   

7.4.2 删除索引

7.4.2.1 根据ID删除

  • 代码实现:

@Test

public void deleteDocument() throws Exception {

// 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

// 参数:solr服务器的访问地址

HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/");

// 根据ID删除

server.deleteById("c0001");

// 提交

server.commit();

System.out.println("索引删除成功!");

}

 

  • 测试删除:

   

7.4.2.2 根据其他条件删除

  • 代码实现:

   

@Test

public void deleteDocumentByQuery() throws Exception {

// 1、 创建HttpSolrServer对象,通过它和Solr服务器建立连接。

// 参数:solr服务器的访问地址

HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr/");

// 根据ID删除

server.deleteByQuery("name:使用solrJ添加的文档,这是一个测试。");

// 全部删除

// server.deleteByQuery("*:*");

// 提交

server.commit();

System.out.println("索引删除成功!");

}

7.4.3 查询索引

7.4.3.1 简单查询

@Test

public void search01() throws Exception {

// 创建HttpSolrServer

HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");

// 创建SolrQuery对象

SolrQuery query = new SolrQuery();

// 输入查询条件

query.setQuery("product_name:笔记本");

// 执行查询并返回结果

QueryResponse response = server.query(query);

// 获取匹配的所有结果

SolrDocumentList list = response.getResults();

// 匹配结果总数

long count = list.getNumFound();

System.out.println("匹配结果总数:" + count);

for (SolrDocument doc : list) {

System.out.println(doc.get("id"));

System.out.println(doc.get("product_name"));

System.out.println(doc.get("product_catalog"));

System.out.println(doc.get("product_price"));

System.out.println(doc.get("product_picture"));

System.out.println("=====================");

}

}

 

7.4.3.2 复杂查询

7.4.3.2.1  Solr查询语法
  1. q - 查询关键字,必须的,如果查询所有使用*:*

请求的q是字符串

 

  1. fq - filter query)过虑查询,作用:在q查询符合结果中同时是fq查询符合的,例如::

请求fq是一个数组(多个值)

 

也可以使用*”表示无限,例如:

20以上:product_price:[20 TO *]

20以下:product_price:[* TO 20]

[] 表示包含首位,{}表示不包含首位。

  1. sort - 排序,格式:sort=<field name>+<desc|asc>[,<field name>+<desc|asc>]… 。示例:

 

  1. start - 分页显示使用,开始记录下标,从0开始
  2. rows - 指定返回结果最多有多少条记录,配合start来实现分页。

实际开发时,知道当前页码和每页显示的个数最后求出开始下标。

 

  1. fl - 指定返回那些字段内容,用逗号或空格分隔多个。

显示商品图片、商品名称、商品价格

 

  1. df-指定一个搜索Field   *******

也可以在SolrCore目录 中conf/solrconfig.xml文件中指定默认搜索Field,指定后就可以直接在“q”查询条件中输入关键字。

 

 

  1. wt - (writer type)指定输出格式,可以有 xml, json, php, phps, 后面 solr 1.3增加的,要用通知我们,因为默认没有打开。

 

  1. hl 是否高亮 ,设置高亮Field,设置格式前缀和后缀。

 

7.4.3.2.2  Solr复杂查询代码实现

@Test

public void search02() throws Exception {

// 创建HttpSolrServer

HttpSolrServer server = new HttpSolrServer("http://localhost:8080/solr");

// 创建SolrQuery对象

SolrQuery query = new SolrQuery();

 

// 输入查询条件

query.setQuery("product_name:小黄人");

// query.set("q", "product_name:小黄人");

 

// 设置过滤条件

// 如果设置多个过滤条件的话,需要使用query.addFilterQuery(fq)

query.setFilterQueries("product_price:[1 TO 10]");

 

// 设置排序

query.setSort("product_price", ORDER.asc);

// 设置分页信息(使用默认的)

query.setStart(0);

query.setRows(10);

 

// 设置显示的Field的域集合

query.setFields("id,product_name,product_catalog,product_price,product_picture");

 

// 设置默认域

query.set("df", "product_keywords");

 

// 设置高亮信息

query.setHighlight(true);

query.addHighlightField("product_name");

query.setHighlightSimplePre("<span style=color:red>");

query.setHighlightSimplePost("</span>");

 

// 执行查询并返回结果

QueryResponse response = server.query(query);

// 获取匹配的所有结果

SolrDocumentList list = response.getResults();

// 匹配结果总数

long count = list.getNumFound();

System.out.println("匹配结果总数:" + count);

 

// 获取高亮显示信息

Map<String, Map<String, List<String>>> highlighting = response

.getHighlighting();

for (SolrDocument doc : list) {

System.out.println(doc.get("id"));

 

List<String> list2 = highlighting.get(doc.get("id")).get(

"product_name");

if (list2 != null)

System.out.println("高亮显示的商品名称:" + list2.get(0));

else {

System.out.println(doc.get("product_name"));

}

 

System.out.println(doc.get("product_catalog"));

System.out.println(doc.get("product_price"));

System.out.println(doc.get("product_picture"));

System.out.println("=====================");

}

}

 

 

 

 

相关文章:

  • 2021-10-09
  • 2021-05-14
  • 2021-11-30
  • 2022-12-23
  • 2022-12-23
  • 2021-08-02
  • 2021-09-29
  • 2022-12-23
猜你喜欢
  • 2021-10-08
  • 2021-12-05
  • 2021-09-03
  • 2021-06-22
  • 2021-09-22
  • 2021-11-28
  • 2022-02-10
相关资源
相似解决方案