使用solrJ管理索引库
使用SolrJ可以实现索引库的增删改查操作把solrJ的jar包添加到工程中。
<!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
创建测试方法
添加文档测试
单机版
第一步:创建一个SolrServer,使用HttpSolrServer创建对象。
第二步:创建一个文档对象SolrInputDocument对象。
第三步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
第四步:把文档添加到索引库中。
第五步:提交。
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;
public class TestSolrj {
@Test
public void addDocument() throws Exception{
//创建一个SolrServer对象,创建一个连接, 参数solr服务的url
SolrServer solrServer = new HttpSolrServer("http://192.168.25.3:8180/solr/collection1");
//创建一个文档对象SolrInputDocument
SolrInputDocument document = new SolrInputDocument();
//向文档对象中添加域. 文档中必须包含一个id域,所有的域的名称必须在schema.xml中定义
document.addField("id", "doc01");
document.addField("item_title", "测试商品01");
document.addField("item_price", 1000);
//把文档写入索引库
solrServer.add(document);
//提交
solrServer.commit();
}
}
运行后就添加进去了
集群版
第一步:把solrJ相关的jar包添加到工程中。
第二步:创建一个SolrServer对象,需要使用CloudSolrServer子类。构造方法的参数是zookeeper的地址列表。
第三步:需要设置DefaultCollection属性。
第四步:创建一SolrInputDocument对象。
第五步:向文档对象中添加域
第六步:把文档对象写入索引库。
第七步:提交。
package cn.e3mall.solrj;
import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;
public class TestSolrCloud {
@Test
public void testAddDocument() throws Exception {
//创建一个集群的连接,应该使用CloudSolrServer创建
//zkHost:zookeeper的地址列表
CloudSolrServer solrServer = new CloudSolrServer("192.168.25.3:2181,192.168.25.3:2182,192.168.25.3:2183");
//设置一个defaultCollection属性
solrServer.setDefaultCollection("collection2");
//创建一个文档对象
SolrInputDocument document = new SolrInputDocument();
//像文档中添加域
document.setField("id", "solrcloud01");
document.setField("item_title", "测试商品01");
document.setField("item_price", 1000);
//把文件写入索引库
solrServer.add(document);
//提交
solrServer.commit();
}
}
删除文档测试
第一步:创建一个SolrServer对象。
第二步:调用SolrServer对象的根据id删除的方法。
第三步:提交
@Test
public void deleteDocument() throws Exception{
//创建一个SolrServer对象,创建一个连接, 参数solr服务的url
SolrServer solrServer = new HttpSolrServer("http://192.168.25.3:8180/solr/collection1");
//删除文档
//根据id删除
//solrServer.deleteById("doc01");
//根据查询删除
solrServer.deleteByQuery("id:doc01");
//提交
solrServer.commit();
}
实现商品导入索引库
创建接口
创建接口的实现类
import java.util.List;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.e3mall.common.pojo.SearchItem;
import cn.e3mall.common.util.E3Result;
import cn.e3mall.search.mapper.ItemMapper;
import cn.e3mall.search.service.SearchItemService;
/**
* 索引库维护Service
*
* @author 11501
*
*/
@Service
public class SearchItemServiceImpl implements SearchItemService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private SolrServer solrServer;
@Override
public E3Result importAllItems() {
try {
// 查询商品列表
List<SearchItem> itemList = itemMapper.getItemList();
// 遍历商品列表
for (SearchItem searchItem : itemList) {
// 创建文档对象
SolrInputDocument document = new SolrInputDocument();
// 向文档对象中添加域
document.addField("id", searchItem.getId());
document.addField("item_title", searchItem.getTitle());
document.addField("item_sell_point", searchItem.getSell_point());
document.addField("item_price", searchItem.getPrice());
document.addField("item_image", searchItem.getImage());
document.addField("item_category_name", searchItem.getCategory_name());
// 把文档对象写入索引库
solrServer.add(document);
}
// 提交
solrServer.commit();
// 返回导入成功
return E3Result.ok();
} catch (Exception e) {
e.printStackTrace();
return E3Result.build(500, "数据导入时发生异常");
}
}
}
给solrServer配置 bean
使用哪个就把注释打开, 平时开发的时候一般使用单机版
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 单机版solrj -->
<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg index="0" value="http://192.168.25.3:8081/solr/collection1"></constructor-arg>
</bean>
<!-- 集群版solrj -->
<!-- <bean id="cloudSolrServer" class="org.apache.solr.client.solrj.impl.CloudSolrServer">
value zookeeper的地址列表
<constructor-arg index="0" value="192.168.25.3:2181,192.168.25.3:2182,192.168.25.3:2183"></constructor-arg>
<property name="defaultCollection" value="collection2"></property>
</bean> -->
</beans>
发布服务接收服务
表现层
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.e3mall.common.util.E3Result;
import cn.e3mall.search.service.SearchItemService;
/**
* 导入商品数据到索引库
* @author 11501
*
*/
@Controller
public class SearchItemController {
@Autowired
private SearchItemService searchItemService;
@RequestMapping(value = "/index/item/import", method = RequestMethod.POST)
@ResponseBody
public E3Result importItemList() {
E3Result result = searchItemService.importAllItems();
return result;
}
}
运行后如果抛异常: 无效的绑定语句
接口和实现类不在同一目录下面, 找不到映射文件, 只有接口, 就会抛这个异常
在pom添加, 路径根据你配置文件的位置修改
<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
查询索引库测试
单机版
查询步骤:
第一步:创建一个SolrServer对象
第二步:创建一个SolrQuery对象。
第三步:向SolrQuery中添加查询条件、过滤条件。。。
第四步:执行查询。得到一个Response对象。
第五步:取查询结果。
第六步:遍历结果并打印。
简单查询
package cn.e3mall.solrj;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.junit.Test;
public class TestSolrj {
@Test
public void queryIndex() throws Exception{
//创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.25.3:8180/solr/collection1");
//创建一个SolrQuery对象
SolrQuery query = new SolrQuery();
//设置查询条件
//query.setQuery("*:*");
query.set("q", "*:*");
//执行查询,QueryResponse对象
QueryResponse queryResponse = solrServer.query(query);
//取文档列表, 取查询结果记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println("查询结果记录数" + solrDocumentList.getNumFound());
//遍历文档, 从中取域的内容
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_sell_point"));
System.out.println(solrDocument.get("item_price"));
System.out.println(solrDocument.get("item_image"));
System.out.println(solrDocument.get("item_category_name"));
}
}
}
运行结果参考
复杂查询
package cn.e3mall.solrj;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.junit.Test;
public class TestSolrj {
@Test
public void queryIndexFuza() throws Exception{
//创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.25.3:8180/solr/collection1");
//创建一个SolrQuery对象
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery("手机");
query.setStart(0);
query.setRows(20);
query.set("df", "item_title");
query.setHighlight(true);
query.addHighlightField("item_title");
query.setHighlightSimplePre("<em>");
query.setHighlightSimplePost("</em>");
//执行查询,QueryResponse对象
QueryResponse queryResponse = solrServer.query(query);
//取文档列表, 取查询结果记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println("查询结果记录数" + solrDocumentList.getNumFound());
//遍历文档, 从中取域的内容
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
//取高亮显示
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String title = "";
if (list != null && list.size() > 0) {
title = list.get(0);
} else {
title = (String) solrDocument.get("item_title");
}
System.out.println(title);
System.out.println(solrDocument.get("item_sell_point"));
System.out.println(solrDocument.get("item_price"));
System.out.println(solrDocument.get("item_image"));
System.out.println(solrDocument.get("item_category_name"));
}
}
}
运行结果参考
集群版
创建一个CloudSolrServer对象,其他处理和单机版一致。
package cn.e3mall.solrj;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.junit.Test;
public class TestSolrCloud {
@Test
public void testQueryDocument() throws Exception {
//创建一个CloudSolrServer对象
CloudSolrServer solrServer = new CloudSolrServer("192.168.25.3:2181,192.168.25.3:2182,192.168.25.3:2183");
//设置DefaultCollention
solrServer.setDefaultCollection("collection2");
//创建一个查询对象
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery("*:*");
//执行查询
QueryResponse queryResponse = solrServer.query(query);
//取查询结果
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println("总记录数:" + solrDocumentList.getNumFound());
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_price"));
}
}
}
实现查询索引库
根据前端的需要创建一个包含所有返回结果字段的pojo
我们上面查询的测试方法, 发现创建连接、执行查询、取结果基本上都是一样的, 我们把相同的部分提出来放入一个dao
package cn.e3mall.search.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
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.Repository;
import cn.e3mall.common.pojo.SearchItem;
import cn.e3mall.common.pojo.SearchResult;
/**
* 商品搜索Dao
* @author 11501
*/
@Repository
public class SearchDao {
@Autowired
private SolrServer solrServer;
/**
* 根据查询条件查询索引
*/
public SearchResult search(SolrQuery query) throws Exception {
//根据query查询索引库
QueryResponse queryResponse = solrServer.query(query);
//取查询结果
SolrDocumentList solrDocumentList = queryResponse.getResults();
//取查询结果总记录数
long numFound = solrDocumentList.getNumFound();
SearchResult result = new SearchResult();
result.setRecordCount(numFound);
//取商品列表,需要取高亮显示
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<SearchItem> itemList = new ArrayList<SearchItem>();
for (SolrDocument solrDocument : solrDocumentList) {
SearchItem searchItem = new SearchItem();
searchItem.setId((String) solrDocument.get("id"));
searchItem.setCategory_name((String) solrDocument.get("item_category_name"));
searchItem.setImage((String) solrDocument.get("item_image"));
searchItem.setPrice((long) solrDocument.get("item_price"));
searchItem.setSell_point((String) solrDocument.get("item_sell_point"));
//取高亮显示
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String title = "";
if (list != null && list.size() > 0) {
title = list.get(0);
} else {
title = (String) solrDocument.get("item_title");
}
searchItem.setTitle(title);
//添加到商品列表
itemList.add(searchItem);
}
result.setItemList(itemList);
//返回结果
return result;
}
}
service层接口
接口的实现类
package cn.e3mall.search.service.impl;
import org.apache.solr.client.solrj.SolrQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.e3mall.common.pojo.SearchResult;
import cn.e3mall.search.dao.SearchDao;
import cn.e3mall.search.service.SearchService;
/**
* 商品搜索Service
* @author 11501
*/
@Service
public class SearchServiceImpl implements SearchService {
@Autowired
private SearchDao searchDao;
@Override
public SearchResult search(String keyword, int page, int rows) throws Exception {
//创建SolrQuery对象
SolrQuery solrQuery = new SolrQuery();
//设置查询条件
solrQuery.setQuery(keyword);
//设置分页条件
if (page <= 0) page = 1;
solrQuery.setStart((page - 1) * rows);
solrQuery.setRows(rows);
//设置默认搜索域
solrQuery.set("df", "item_title");
//开启高亮显示
solrQuery.setHighlight(true);
solrQuery.addHighlightField("item_title");
solrQuery.setHighlightSimplePre("<em style=\"color:red\">");
solrQuery.setHighlightSimplePost("</em>");
//调用dao执行查询
SearchResult searchResult = searchDao.search(solrQuery);
//计算总页数
long recordCount = searchResult.getRecordCount();
int totalPage = (int) (recordCount/rows);
if (recordCount % rows > 0) {
totalPage++;
}
//添加到返回结果
searchResult.setTotalPages(totalPage);
//返回结果
return searchResult;
}
}
发布服务接收服务
表现层
package cn.e3mall.search.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import cn.e3mall.common.pojo.SearchResult;
import cn.e3mall.search.service.SearchService;
/**
* 商品搜索controller
*/
@Controller
public class SearchController {
@Autowired
private SearchService searchService;
@Value("${SEARCH_RESULT_ROWS}")
private Integer SEARCH_RESULT_ROWS;
@RequestMapping("/search")
public String searchItemList(String keyword,
@RequestParam(defaultValue = "1") Integer page, Model model) throws Exception {
keyword = new String(keyword.getBytes("iso-8859-1"), "utf-8");
//查询商品列表
SearchResult searchResult = searchService.search(keyword, page, SEARCH_RESULT_ROWS);
//把结果传递给页面
model.addAttribute("query", keyword);
model.addAttribute("totalPages", searchResult.getTotalPages());
model.addAttribute("page", page);
model.addAttribute("recordCount", searchResult.getRecordCount());
model.addAttribute("itemList", searchResult.getItemList());
//异常测试
//int a = 1/0;
//返回逻辑视图
return "search";
}
}