solr搭建和搜索功能实现

2023-10-12 14:14:06 浏览数 (1)

前言: solr与Lucene的区别 :Lucene是api 需要写代码开发 ,solr是服务器,是一套基于lucence开发的全文检索框架,用就完事了。

1.1. Solr的环境

Solr是java开发。

需要安装jdk。

安装环境Linux。

需要安装Tomcat。

1.2. 搭建步骤

第一步:把solr 的压缩包上传到Linux系统

第二步:解压solr。

第三步:安装Tomcat,解压缩即可。

第四步:把solr部署到Tomcat下。

第五步:解压缩war包。启动Tomcat解压。

第六步:把/root/solr-4.10.3/example/lib/ext目录下的所有的jar包,添加到solr工程中。

代码语言:javascript复制
[root@localhost ext]# pwd

/root/solr-4.10.3/example/lib/ext

[root@localhost ext]# cp */usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/

第七步:创建一个solrhome。/example/solr目录就是一个solrhome。复制此目录到/usr/local/solr/solrhome

代码语言:javascript复制
[root@localhost example]# pwd

/root/solr-4.10.3/example

[root@localhost example]# cp -r solr/usr/local/solr/solrhome

[root@localhost example]# 

第八步:关联solr及solrhome。需要修改solr工程的web.xml文件。

第九步:启动Tomcat

http://192.168.25.154:8080/solr/

和windows下的配置完全一样。

solr客户端的一些基本操作: 清空索引:

代码语言:javascript复制
<delete>
<query>*:*</query>
</delete>

1.3. 配置业务域

创建对应的业务域。需要制定中文分析器。

创建步骤:

第一步:把中文分析器添加到工程中。

1、把IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下 D:softwareapache-tomcat-7.0.86ForSolrwebappssolrWEB-INFlib

2、把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下。

第二步:配置一个FieldType,制定使用IKAnalyzer E:softwareapache-tomcat-7.0.47ForSolrsolrhomecollection1conf 修改schema.xml文件

修改Solr的schema.xml文件,添加FieldType:

代码语言:javascript复制
<fieldType name="text_ik" class="solr.TextField">
  <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

第三步:配置业务域,type制定使用自定义的FieldType。

代码语言:javascript复制
<!--使用ik分词器-->
<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
<field name="item_price"  type="long" indexed="true" stored="true"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_category_name" type="string" indexed="true" stored="true" />

<!--三个业务域复制到item_keywords中 方便搜索-->
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_sell_point" dest="item_keywords"/>
<copyField source="item_category_name" dest="item_keywords"/>

设置业务系统Field

第四步:重启tomcat

1.1.1. solrJ添加索引库

1、把solrJ的jar包添加到工程。

2、创建一个SolrServer对象。创建一个和sorl服务的连接。HttpSolrServer。

3、创建一个文档对象。SolrInputDocument。

4、向文档对象中添加域。必须有一个id域。而且文档中使用的域必须在schema.xml中定义。

5、把文档添加到索引库

6、Commit。

代码语言:javascript复制
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.SolrServerException;
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.apache.solr.common.SolrInputDocument;
import org.junit.Test;

public class TestSolrJ {
	/**
	 *  添加文档
	 * <p>Title: addDocument</p>
	 * <p>Description: </p>
	 * @throws Exception
	 */
	@Test
	public void addDocument() throws Exception {
		//创建一个SolrServer对象 创建连接 参数solr服务的url
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/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();
	}
	
	/**
	 * 删除文档
	 * <p>Title: deleteDocument</p>
	 * <p>Description: </p>
	 * @throws Exception
	 */
	@Test
	public void deleteDocument() throws Exception{
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
		//删除文档
//		solrServer.deleteById("doc01");
		//根据id删除
		solrServer.deleteByQuery("id:doc01");
		solrServer.commit();
	}
	/**
	 * 简答查询测试
	 * <p>Title: queryIndex</p>
	 * <p>Description: </p>
	 * @throws Exception 
	 */
	@Test
	public void queryIndex() throws Exception {
		SolrServer solrServer =new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
		SolrQuery solrQuery = new SolrQuery();
		//设置执行查询
		solrQuery.setQuery("*:*");
		//执行查询
		QueryResponse queryResponse = solrServer.query(solrQuery);
		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"));
		}
	}
	
	/**
	 * 复杂搜索
	 * @throws Exception 
	 */
	@Test
	public void queryIndexComplex() throws Exception {
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
		SolrQuery solrQuery = new SolrQuery();
		solrQuery.setQuery("手机");
		solrQuery.setStart(0);//从第几条开始
		solrQuery.setRows(20);//条数
		solrQuery.set("df", "item_title");
		solrQuery.setHighlight(true);
		//设置高亮域
		solrQuery.addHighlightField("item_title");
		solrQuery.setHighlightSimplePre("<em>");
		solrQuery.setHighlightSimplePost("</em>");
		QueryResponse queryResponse = solrServer.query(solrQuery);
		SolrDocumentList solrDocumentList = queryResponse.getResults();
		System.out.println(solrDocumentList.getNumFound());
		Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
		for (SolrDocument solrDocument : solrDocumentList) {
			System.out.println(solrDocument.get("id"));
			//取高亮显示
			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"));
		}
	}
}

商品索引导入

代码语言:javascript复制
/**
 * 将商品数据导入索引库
 * <p>Title: SearchItemServiceImpl</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Service
public class SearchItemServiceImpl implements SearchItemService {

	@Autowired
	private ItemMapper itemMapper;
	@Autowired
	private SolrServer solrServer;
	
	@Override
	public E3Result importItmes() {
		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, "商品导入失败");
		}
	}
	
}
1.1.1. SolrServer的配置
代码语言:javascript复制
<?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">

	<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
		<constructor-arg index="0" value="http://192.168.25.154:8080/solr"/>
	</bean>

</beans>

1.1. 解决Mapper映射文件不存在异常

代码语言:javascript复制
<!-- 如果不添加此节点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>

1. 搜索功能实现

跟据查询条件查询索引库,返回对应的结果。

dao层:

代码语言:javascript复制
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
 * <p>Title: SearchDao</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Repository
public class SearchDao {
	
	@Autowired
	private SolrServer solrServer;
	
	public SearchResult search(SolrQuery solrQuery) throws Exception {
		QueryResponse queryResponse = solrServer.query(solrQuery);
		SolrDocumentList solrDocumentList = queryResponse.getResults();
		long numFound = solrDocumentList.getNumFound();
		SearchResult searchResult = new SearchResult();
		searchResult.setRecordCount(numFound);
		//取商品列表 高亮显示
		Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
		List<SearchItem> itemList = new ArrayList<>();
		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);
		}
		searchResult.setItemList(itemList);
		return searchResult;
	}
	
}

service层

代码语言:javascript复制
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
public class SearchServiceImpl implements SearchService {
	@Autowired
	private SearchDao searchDao;
	
	@Override
	public SearchResult search(String keyword, int page, int rows) throws Exception {
		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;
	}

}

service发布服务 表现层引用服务 在e3-search-web中添加接口依赖

表现层:

代码语言:javascript复制
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;

/**
 * 商品搜索
 * <p>Title: SearchController</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@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("recourdCount", searchResult.getRecordCount());
		model.addAttribute("itemList", searchResult.getItemList());
		//异常测试
//		int a =1/0;
		return "search";
	}
	
}

0 人点赞