一、Solr概述
Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务。Solr自带服务器功能,可以通过命令方式直接启动solr服务。也可以把solr部署到Jetty、Tomcat等其他Servlet容器中运行。
- Solr与lucene的关系
Lucene是一个开放源代码的全文检索引擎工具包,它不是一个完整的全文检索应用。Lucene仅提供了完整的查询引擎和索引引擎,目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者以Lucene为基础构建全文检索应用。Solr的目标是打造一款企业级的搜索引擎系统,它是基于Lucene一个搜索引擎服务,可以独立运行,通过Solr可以非常快速的构建企业的搜索引擎,通过Solr也可以高效的完成站内搜索功能。
二、Solv安装配置
2.1 下载Solr
下载地址:http://archive.apache.org/dist/lucene/solr/
如果是Windows版本,那么下载完成后直接解压缩到指定目录即可。目录结果如下图所示:
bin:solr的运行脚本;
contrib:solr相关的第三方扩展jar包;
dist:该目录包含build过程中产生的war和jar文件,以及相关的依赖文件;
docs:api文档;
example:solr工程的示例;
licenses:各种许可和协议;
server:solr自带的服务器目录。其中有两个比较重要的目录:
|- solr:运行Solr的配置文件都保存在这里。其中,它包含一个子文件夹configsets,该文件夹存放了solr的示例配置文件
|- solr-webapp:solr后台管理系统所在目录
2.2 启动自带solr服务
第一步:在命令行进入solr/bin目录,然后执行solr start命令即可。
solr服务默认监听8983端口。启动成功后,在浏览器上输入localhost:8983/solr即可打开solr管理界面。
2.3 创建solr core
一个solr core就是一个索引库。一个solr服务器上可以有多个solr core。
第一步:进入%solr_home%/server/solr目录,新建一个目录,该目录作为一个索引库目录存放我们创建的索引。
第二步:将%solr_home%\server\solr\configsets\sample_techproducts_configs目录下的conf文件夹拷贝到solrtest目录中。
第三步:重启solr服务。
solr restart -p 8983
例如:
启动成功后,重新访问solr管理界面。
第四步:点击左边Core Admin菜单,然后点击Add Core,在name和InstanceDir输入框中输入solr core文件夹的名称,输入完后点击蓝色的Add Core按钮。
这时候在左边core selector中可以看到我们创建的solr core。
2.4 管理界面介绍
(1)DashBoard
仪表盘,显示了该Solr实例开始启动运行的时间、版本、系统资源、jvm等信息。
(2)Logging
Solr运行日志信息。
(3)Core Admin
Solr Core管理界面,在这里可以添加SolrCore实例。
(4)Java Properties
Solr在JVM 运行环境中的属性信息,包括类路径、文件编码、jvm内存设置等信息。
(5)Thread Dump
显示Solr Server中当前活跃线程信息,同时也可以跟踪线程运行栈信息。
(6)Core Selector
选择一个SolrCore进行详细操作。具体操作如下所示:
其中有几个比较常用的功能:
Analysis:通过此界面可以测试索引分析器和搜索分析器的执行情况。
Dataimport:定义数据导入处理器,可以从关系数据库将数据导入到Solr索引库中。默认没有配置,需要手工配置;
Documents:通过/update表示更新索引,solr默认根据id(唯一约束)域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作,如果找到则更新;
Query:通过/select执行搜索索引,必须指定“q”查询条件方可搜索。
q: 查询关键字;
fq: (filter query)过滤查询,在q查询结果中再把符合fq的内容筛选出来;
sort:排序,desc代表降序,asc代表升序;
start: 分页显示使用,开始记录下标,从0开始;
rows:指定返回结果最多有多少条记录,配合start来实现分页;
fl: (Field List)指定返回那些字段内容,用逗号或空格分隔多个;
df:(Default Field)指定默认搜索Field;
wt: (writer type)指定输出格式,可以有xml、json等格式;
hl: 是否高亮 ,设置高亮Field,设置格式前缀和后缀;
三、Solrj的使用
3.1 什么是solrj
solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法。
3.2 环境搭建
搭建Maven工程,并引入solrj相关坐标;
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>8.2.0</version>
</dependency>
3.3 添加或修改索引
public class CreateIndexTest {
// 设置solr服务接口
String baseURL = "http://127.0.0.1:8983/solr/solrtest";
SolrClient solrClient;
@Before
public void init() {
// 创建SolrServer对象
solrClient = new HttpSolrClient.Builder(baseURL).build();
}
// 添加和更新索引
@Test
public void testCreateIndex() throws Exception {
// 创建SolrInputDocument对象
SolrInputDocument document = new SolrInputDocument();
// 添加Field
document.addField("id", "103");
document.addField("content_ik", "中华人民共和国");
// 把SolrInputDocument对象添加到索引库中
solrClient.add(document);
// 提交
solrClient.commit();
}
}
上面solrClient.add(document)方法会根据id域来更新Document的内容,如果根据id值搜索不到id域则会执行添加操作。
3.4 删除索引
// 根据条件删除
solrClient.deleteByQuery("*:*");
// 提交
solrClient.commit();
*注意:*:代表删除所有索引,需要慎用。
3.5 查询索引
@Test
public void testSearchIndex() throws Exception {
// 创建搜索对象
SolrQuery query = new SolrQuery();
// 设置搜索条件
query.setQuery("*:*");
// 发起搜索请求
QueryResponse response = solrClient.query(query);
// 处理搜索结果
SolrDocumentList results = response.getResults();
System.out.println("搜索到的结果总数:" + results.getNumFound());
// 遍历搜索结果
for (SolrDocument solrDocument : results) {
System.out.println("----------------------------------------------------");
System.out.println("id:" + solrDocument.get("id"));
System.out.println("content" + solrDocument.get("content"));
}
}
3.6 复杂查询
@Test
public void testSearchIndex2() throws Exception {
// 创建搜索对象
SolrQuery solrQuery = new SolrQuery();
// 设置查询条件
solrQuery.setQuery("搜索引擎");
// 设置过滤条件
solrQuery.setFilterQueries("bookName:lucene", "bookPrice:[49 TO 99]");
// 设置排序
solrQuery.setSort("bookPrice", ORDER.desc);
// 设置分页
solrQuery.setStart(0);
solrQuery.setRows(10);
// 设置显示Field域
solrQuery.setFields("id, bookName, bookPrice, bookPic, bookRemark");
// 设置默认搜索Field域
solrQuery.set("df", "bookName");
// 设置高亮
solrQuery.setHighlight(true);
solrQuery.addHighlightField("bookName");
solrQuery.setHighlightSimplePre("<font color=\"red\">");
solrQuery.setHighlightSimplePost("</font>");
// 查询数据
QueryResponse response = solrClient.query(solrQuery);
// 获取查询结果的记录数
SolrDocumentList results = response.getResults();
System.out.println("搜索到的数据总条数:" + results.getNumFound());
Map<String, Map<String, List<String>>> map = response.getHighlighting();
// 解析查询结果
for (SolrDocument solrDocument : results) {
System.out.println("----------------------------------------------------");
// 显示高亮
List<String> list = map.get(solrDocument.get("id")).get("bookName");
System.out.println("编号:" + solrDocument.get("id"));
if (list != null && list.size() > 0) {
System.out.println("书名:" + list.get(0));
} else {
System.out.println("书名:" + solrDocument.get("bookName"));
}
System.out.println("价格:" + solrDocument.get("bookPrice"));
System.out.println("图片:" + solrDocument.get("bookPic"));
System.out.println("描述:" + solrDocument.get("bookRemark"));
}
}
四、配置中文分词器
第一步:下载ikanalyzer。
下载地址:https://mvnrepository.com/artifact/com.jianggujin/IKAnalyzer-lucene/8.0.0
第二步:把下载好的jar包复制到%solr_home%\server\solr-webapp\webapp\WEB-INF\lib目录下。
第三步:把下面三个文件复制到%solr_home%\server\solr-webapp\webapp\WEB-INF\classes目录下。这三个文件可以从ikanalyzer.jar文件中获得。
第四步:修改%solr_home%\server\solr\solrtest\conf\managed-schema文件,配置中文分词器。
<!-- ik分词器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<field name="content_ik" type="text_ik" indexed="true" stored="true" />
修改完成后重启solr服务,进入analysis页面,在Field Value中输入要分词的内容,然后再选择FieldType为content_ik,最后点击蓝色按钮即可。效果如下图所示:
下面没有使用ikanalyzer分词器的效果(供大家参考):
五、导入数据
需求:使用solr后台导入数据库中book表的数据到solr中。
功能分析:
1.需要在solr的schema.xml文件定义要存储的商品Field。
2.需要把MySQL的数据导入到solr索引库中
3.开发搜索功能
5.1 引入jar包
复制%solr_home%/dist目录下的solr-dataimporthandler包到%solr_home%/contrib/dataimporthandler/lib目录下。
准备mysql驱动包,然后添加到%solr_home%\contrib\db\lib目录下。如果没有lib目录,则自己创建。
修改%solr_home%\server\solr\solrtest\conf目录下的sqlrconfig.xml文件。修改内容如下:
<lib dir="${solr.install.dir:../..}/contrib/dataimporthandler/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../..}/contrib/db/lib" regex=".*\.jar" />
5.2 配置数据源
在%solr_home%\server\solr\solrtest\conf目录下新建data-config.xml文件,该文件配置了Document中每个Field与数据库表的对应关系。配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<!-- 数据库信息 -->
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/solr"
user="root" password="root"/>
<document>
<!-- document实体 -->
<entity name="book" query="SELECT * FROM book">
<!-- 数据库字段映射solr字段 -->
<field column="id" name="id"/>
<field column="name" name="bookName"/>
<field column="price" name="bookPrice"/>
<field column="pic" name="bookPic"/>
<field column="remark" name="bookRemark"/>
</entity>
</document>
</dataConfig>
修改%solr_home%\server\solr\solrtest\conf目录下的sqlrconfig.xml文件:
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
5.3 配置Field
修改%solr_home%\server\solr\solrtest\conf目录下的managed-schema文件,在最后面加入下面内容:
<field name="bookName" type="text_ik" indexed="true" stored="true" />
<field name="bookPrice" type="pint" indexed="true" stored="true" />
<field name="bookPic" type="string" indexed="false" stored="true" />
<field name="bookRemark" type="text_ik" indexed="true" stored="false" />
<field name="book_keywords" type="text_ik" indexed="true" stored="true" multiValued="true"/>
<copyField source="bookName" dest="book_keywords"/>
<copyField source="bookRemark" dest="book_keywords"/>
copyField:将多个Field复制到一个Field中,以便进行统一的检索。当创建索引时,solr服务器会自动的将source域的内容复制到dest目标域中。如果指定dest目标域为默认搜索域,可以提高查询效率。
配置完成后,重启solr服务。
5.4 后台导入操作
点击Dataimport菜单,选择Entity,然后点击Execute按钮执行导入。导入成功后界面如下所示:
在Overview中可以看到索引库的信息。
六、SpringBoot整合solr
第一步:创建springboot项目,引入相关坐标。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
第二步:创建实体类。
package solrjtest.beans;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String name;
private Integer price;
private String pic;
private String remark;
}
第三步:创建Service接口,该接口定义一个方法,用于从solr中查询索引,并返回结果。
public interface IBookService {
List<Book> searchBook() throws Exception;
}
第四步:创建Service实现类。
package solrjtest.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import solrjtest.beans.Book;
import solrjtest.service.IBookService;
@Service
public class BookServiceImpl implements IBookService {
@Autowired
private SolrClient solrClient;
@Override
public List<Book> searchBook() throws Exception {
// 创建搜索对象
SolrQuery solrQuery = new SolrQuery();
// 设置查询条件
solrQuery.setQuery("搜索引擎");
// 设置过滤条件
solrQuery.setFilterQueries("bookName:lucene", "bookPrice:[49 TO 99]");
// 设置排序
solrQuery.setSort("bookPrice", ORDER.desc);
// 设置分页
solrQuery.setStart(0);
solrQuery.setRows(10);
// 设置显示Field域
solrQuery.setFields("id, bookName, bookPrice, bookPic, bookRemark");
// 设置默认搜索Field域
solrQuery.set("df", "bookName");
// 设置高亮
solrQuery.setHighlight(true);
solrQuery.addHighlightField("bookName");
solrQuery.setHighlightSimplePre("<font color=\"red\">");
solrQuery.setHighlightSimplePost("</font>");
// 查询数据
QueryResponse response = solrClient.query(solrQuery);
// 获取查询结果的记录数
SolrDocumentList results = response.getResults();
System.out.println("搜索到的数据总条数:" + results.getNumFound());
Map<String, Map<String, List<String>>> map = response.getHighlighting();
List<Book> books = new ArrayList<Book>();
// 解析查询结果
for (SolrDocument solrDocument : results) {
// 显示高亮
List<String> list = map.get(solrDocument.get("id")).get("bookName");
// 获取Field的值
String id = (String) solrDocument.get("id");
String bookName = "";
if (list != null && list.size() > 0) {
bookName = list.get(0);
} else {
bookName = (String) solrDocument.get("bookName");
}
int bookPrice = (int) solrDocument.get("bookPrice");
String bookPic = (String) solrDocument.get("bookPic");
String bookRemark = (String) solrDocument.get("bookRemark");
// 把获取到Field的值封装成Book对象
Book book = new Book();
book.setId(Integer.parseInt(id));
book.setName(bookName);
book.setPrice(bookPrice);
book.setPic(bookPic);
book.setRemark(bookRemark);
books.add(book);
}
return books;
}
}
第五步:创建控制器。
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
private IBookService bookService;
@RequestMapping(path="/list", produces={"application/json;charset=utf-8"})
@ResponseBody
public List<Book> list() {
try {
return bookService.searchBook();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
第六步:配置solr。
spring:
data:
solr:
host: http://192.168.31.20:8983/solr/solrtest
第七步:创建启动类。
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
最终在浏览器上看到的效果如下图所示: