今天做了一个搜索的小案例。使用solr服务实现后台的搜索功能,并在前台展示出搜索结果。
下面大体说一下自己的实现方案

1.首先是完成自己solr服务器的配置
进入linux上配置的 solr-tomcat2->solr-home->collection1->conf
用vim 修改里面的schema.xml文件搜索相关域的信息。
在这里我加入了下面的配置
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<field name="stu_usr_name" type="text_ik" indexed="true" stored="true"/>
<field name="stu_email" type="text_ik" indexed="true" stored="true"/>
<field name="stu_phone" type="string" indexed="true" stored="true"/>
<field name="ent_usr_name" type="string" indexed="false" stored="true" />
<field name="ent_phone" type="string" indexed="true" stored="true" />
<field name="cmd_name" type="text_ik" indexed="true" stored="true"/>
<field name="cmd_detail" type="text_ik" indexed="true" stored="true"/>
<field name="cmd_name" type="text_ik" indexed="true" stored="true"/>
<field name="cmd_detail" type="text_ik" indexed="true" stored="true"/>
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="cmd_name" dest="item_keywords"/>
<copyField source="cmd_detail" dest="item_keywords"/>
<copyField source="cmd_type" dest="item_keywords"/>
2.后台封装了搜索结果类SearchResult
package com.ffGarden.pojo;
import java.util.List;
/**
* 搜索返回结果
*
* @author lihuashuo
*
*/
public class SearchResult {
private List<ItgCommodity> itgCommodityList;
private List<Enterprise> enterpriseList;
private List<StuAccount> stuAccountList;
public List<ItgCommodity> getItgCommodityList() {
return itgCommodityList;
}
public void setItgCommodityList(List<ItgCommodity> itgCommodityList) {
this.itgCommodityList = itgCommodityList;
}
public List<Enterprise> getEnterpriseList() {
return enterpriseList;
}
public void setEnterpriseList(List<Enterprise> enterpriseList) {
this.enterpriseList = enterpriseList;
}
public List<StuAccount> getStuAccountList() {
return stuAccountList;
}
public void setStuAccountList(List<StuAccount> stuAccountList) {
this.stuAccountList = stuAccountList;
}
@Override
public String toString() {
return "SearchResult [itgCommodityList=" + itgCommodityList + ", enterpriseList=" + enterpriseList
+ ", stuAccountList=" + stuAccountList + "]";
}
}
3通过SpringBoot的单元测试的方式完成了对索引库 的添加。
这里有坑,如果不采用SpringBootTest,而是只是使用Junit单元测试的方式,你会发现@Autowired的方式自动注入的属性是空值,所以一直报空指针异常。
package com.ffGarden.solr;
import java.io.IOException;
import java.util.List;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RestController;
import com.ffGarden.FfGardenSpringbootApplication;
import com.ffGarden.pojo.Enterprise;
import com.ffGarden.pojo.ItgCommodity;
import com.ffGarden.pojo.StuAccount;
import com.ffGarden.service.EnterpriseService;
import com.ffGarden.service.ItgCommodityService;
import com.ffGarden.service.StuAccountService;
import com.ffGarden.service.impl.ItgCommodityServiceImpl;
@SpringBootTest(classes = FfGardenSpringbootApplication.class,webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class AddDocumet {
@Autowired
private ItgCommodityService itgCommodityServer;
@Autowired
private EnterpriseService enterpriseService;
@Autowired
private StuAccountService stuAccountService;
@Autowired
private SolrServer solrServer;
/**
* 将商品信息记录导入索引库
* @throws Exception
*/
@Test
public void addItgCommodityDocument() throws Exception {
//ItgCommodityService itgCommodityServer = new ItgCommodityServiceImpl();
//SolrServer solrServer = new HttpSolrServer("http://192.168.1.128:8080/solr/collection1");
// 先从数据库中搜索所有记录
List<ItgCommodity> ItgCommoditylist = itgCommodityServer.getAllCommodities();
// 迭代导入索引库
for (ItgCommodity item : ItgCommoditylist) {
// 创建一个文档对象
SolrInputDocument document = new SolrInputDocument();
// 向文档对象中添加域
document.addField("id", "cmd"+item.getItgNumber());
document.addField("cmd_name", item.getCmdName());
document.addField("cmd_detail", item.getCmdDetail());
document.addField("cmd_prise", item.getCmdPrise().intValue());
document.addField("cmd_type", item.getCmdType());
document.addField("cmd_integral", item.getNeedIntegral());
// 写入索引库
solrServer.add(document);
}
// 提交
solrServer.commit();
}
/**
* 将学生账户记录导入索引库
* @throws Exception
*/
@Test
public void addStuAccountDocument() throws Exception {
//先从数据库中搜索所有的学生账户记录
List<StuAccount> stuAccountList = stuAccountService.getAllStuAccounts();
//迭代导入索引库
for(StuAccount item:stuAccountList) {
//创建一个文档对象
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "stu"+item.getStuNumber());
document.addField("stu_phone", item.getStuPhone());
document.addField("stu_usr_name", item.getStuUsrName());
document.addField("stu_email", item.getStuEmail());
//写入索引库
solrServer.add(document);
}
//提交
solrServer.commit();
}
/**
* 将企业账户记录导入索引库
*/
@Test
public void addEnterpriseDocument() throws Exception {
//从数据库中获取企业列表
List<Enterprise> enterpriseList = enterpriseService.getEnterpriseList();
//迭代导入索引库
for(Enterprise item : enterpriseList) {
SolrInputDocument document = new SolrInputDocument();
document.addField("id", "ent"+item.getEntNumber());
document.addField("ent_usr_name", item.getEntUsrName());
document.addField("ent_phone", item.getEntPhone());
document.addField("ent_email", item.getEntEmail());
//写入索引库
solrServer.add(document);
}
//提交
solrServer.commit();
}
}
下面写了三个搜索的方法,完成设置条件的搜索,分别来搜索商品、企业以及学生用户信息。
/**
* 从索引库根据条件查询学生账户
*
* @param query
* @return
* @throws Exception
*/
public List<StuAccount> searchStuAccount(SolrQuery query) throws Exception {
// 根据查询条件查询索引库
QueryResponse queryResponse = solrServer.query(query);
// 取查询结果总记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
// 创建一个学生账户列表对象
List<StuAccount> accountList = new ArrayList<>();
// 取学生列表
// 取高亮后的结果
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
for (SolrDocument solrDocument : solrDocumentList) {
// 取学生账户的信息
StuAccount account = new StuAccount();
// 获取doc 的id 在这里例如是stu1
String docId = (String) solrDocument.get("id");
// 截取id 把前三位的stu 截取掉,这里变成"1"
String stuId = docId.substring(3);
account.setStuNumber(Integer.valueOf(stuId));
account.setStuUsrName((String) solrDocument.get("stu_usr_name"));
account.setStuEmail((String) solrDocument.get("stu_email"));
account.setStuPhone((String) solrDocument.get("stu_phone"));
// 取高亮结果
List<String> list = highlighting.get(solrDocument.get("id")).get("stu_usr_name");
String stuName = "";
if (list != null && list.size() > 0) {
stuName = list.get(0);
} else {
stuName = (String) solrDocument.get("stu_usr_name");
}
account.setStuUsrName(stuName);
// 添加到商品列表
accountList.add(account);
}
return accountList;
}
/**
* 从索引库根据条件查询商品信息
*
* @param query
* @return
* @throws Exception
*/
public List<ItgCommodity> searchItgCommodity(SolrQuery query) throws Exception {
// 根据查询条件查询索引库
QueryResponse queryResponse = solrServer.query(query);
// 取查询结果总记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
// 创建一个商品列表对象
List<ItgCommodity> itemList = new ArrayList<>();
// 取商品列表
// 取高亮后的结果
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
for (SolrDocument solrDocument : solrDocumentList) {
// 取商品的信息
ItgCommodity item = new ItgCommodity();
String docId = (String) solrDocument.get("id");
// 截取id 把前三位的stu 截取掉,这里变成"1"
String cmdId = docId.substring(3);
item.setItgNumber(Integer.valueOf(cmdId));
item.setCmdDetail((String) solrDocument.get("cmd_detail"));
item.setCmdType((String) solrDocument.get("cmd_type"));
item.setCmdPrise(BigDecimal.valueOf((long) solrDocument.get("cmd_prise")));
item.setNeedIntegral((int) (long) solrDocument.get("cmd_integral"));
// 取高亮结果
List<String> list = highlighting.get(solrDocument.get("id")).get("cmd_name");
String cmdName = "";
if (list != null && list.size() > 0) {
cmdName = list.get(0);
} else {
cmdName = (String) solrDocument.get("cmd_name");
}
item.setCmdName(cmdName);
// 添加到商品列表
itemList.add(item);
}
return itemList;
}
/**
* 从索引库根据条件查询企业信息
*
* @param query
* @return
* @throws Exception
*/
public List<Enterprise> searchEnterprise(SolrQuery query) throws Exception {
// 根据查询条件查询索引库
QueryResponse queryResponse = solrServer.query(query);
// 取查询结果总记录数
SolrDocumentList solrDocumentList = queryResponse.getResults();
// 创建一个商品列表对象
List<Enterprise> entList = new ArrayList<>();
// 取商品列表
// 取高亮后的结果
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
for (SolrDocument solrDocument : solrDocumentList) {
// 取企业的信息
Enterprise enterprise = new Enterprise();
// 获取doc 的id 在这里例如是stu1
String docId = (String) solrDocument.get("id");
// 截取id 把前三位的stu 截取掉,这里变成"1"
String entId = docId.substring(3);
enterprise.setEntNumber(Integer.valueOf(entId));
enterprise.setEntEmail((String) solrDocument.get("ent_email"));
enterprise.setEntPhone((String) solrDocument.get("ent_phone"));
// 取高亮结果
List<String> list = highlighting.get(solrDocument.get("id")).get("ent_usr_name");
String cmdName = "";
if (list != null && list.size() > 0) {
cmdName = list.get(0);
} else {
cmdName = (String) solrDocument.get("ent_usr_name");
}
enterprise.setEntUsrName(cmdName);
// 添加到商品列表
entList.add(enterprise);
}
return entList;
}
最后是Controller的代码
@RequestMapping(value = "/searchItems", method = RequestMethod.GET)
@ResponseBody
public EyeJSONResult searchItems(@RequestParam(value = "content", required = true) String content)
throws Exception {
// 创建一个SolrQuery对象
SolrQuery query = new SolrQuery();
// 设置查询条件
query.setQuery(content);
// 设置默认搜索域
query.set("df", "cmd_name");
// 设置高亮显示
query.setHighlight(true);
query.addHighlightField("cmd_name");
query.setHighlightSimplePre("<em style=\"color:red\">");
query.setHighlightSimplePost("</em>");
// 执行查询
List<ItgCommodity> itemList = searchItgCommodity(query);
// 更换搜索域,搜索学生用户
query.set("df", "stu_usr_name");
query.addHighlightField("stu_usr_name");
List<StuAccount> stuAccountList = searchStuAccount(query);
// 更换搜索域,搜索企业用户
query.set("df", "ent_usr_name");
query.addHighlightField("ent_usr_name");
List<Enterprise> enterpriseList = searchEnterprise(query);
// 创建搜索结果对象
SearchResult result = new SearchResult();
result.setStuAccountList(stuAccountList);
result.setItgCommodityList(itemList);
result.setEnterpriseList(enterpriseList);
// 打印查询结果
// System.out.println(itemList.toString());
// System.out.println("1111111111111111111");
// System.out.println(content);
// SolrJUtils.queryIndex(content);
return EyeJSONResult.ok(result);
}
最后看一下前端的几处关键的实现
store 里面的commodity.js
import { default as api } from '../../util/api'
const commodity = {
state:{
cmdNumber: 0,
commodityDetail:{},
orderNumber: -1,
sumPrice: -1,
searchContent: ""
},
mutations: {
DETAIL:(state, commodityDetail) => {
state.cmdNumber = commodityDetail.cmdNumber
state.commodityDetail = commodityDetail
},
ORDERNUMBER:(state, orderNumber) => {
state.orderNumber = orderNumber;
},
SUMPRICE:(state, sumPrice) => {
state.sumPrice = sumPrice;
},
SEARCH:(state,searchContent)=>{
state.searchContent = searchContent
}
},
actions:{
getCommodityDetail({ commit, state }, searchContent) {
return new Promise((resolve, reject) => {
api({
url: "/search/searchItems",
method: "get",
params: {
content: searchContent
}
}).then(res => {
state.commodityDetail = res.data;
resolve(res);
}).catch(err => {
reject(err)
})
})
}
},
}
export default commodity
getter.js
import commodity from "./modules/commodity";
const getters = {
receiptInfo:state => state.enterprise.receiptInfo,
commodityDetail:state => state.commodity.commodityDetail,
cmdNumber:state => state.commodity.cmdNumber,
orderNumber:state => state.commodity.orderNumber,
sumPrice:state => state.commodity.sumPrice,
role:state => state.user.role,
userNumber:state => state.user.userNumber,
searchContent:state => state.commodity.searchContent
}
export default getters
doSearch() {
this.$store.commit("SEARCH",this.searchContent)
this.$router.push("/studentSearch")
}
computed: {
...mapGetters(["searchContent", "commodityDetail"])
},
created() {
this.api({
url: "/search/searchItems",
method: "get",
params: {
content: this.searchContent
}
}).then(res=>{
this.enterpriseList = res.data.enterpriseList;
this.stuAccountList = res.data.stuAccountList;
this.comodityList = res.data.itgCommodityList;
//console.log(res.data)
})
//this.getCommodityList();
}
作者:lhsjohn
网友评论