e3mall项目第七天——关于solr服务的搭建以及使用

本文详细介绍了如何搭建Solr搜索服务,包括使用SolrJ进行索引库的增删改查操作,以及如何将商品数据导入索引库。此外,还深入探讨了搜索功能的实现,涵盖复杂查询、高亮显示、分页和结果处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今日内容一:Solr服务搭建

Solr服务器的搭建

今日内容二:使用solrJ管理索引库

使用SolrJ可以实现索引库的增删改查操作。
添加文档:
第一步:把solrJ的jar包添加到工程中。
第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
第三步:创建一个文档对象SolrInputDocument对象。
第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
第五步:把文档添加到索引库中。
第六步:提交。
代码的实现:

     /*
	 * 添加文档
	 */
	@Test
	public void testSolrJ() throws SolrServerException, IOException{
		//创建一个SolrServer对象,创建一个链接,参数solr服务的url
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.129:8080/solr/collection1");
		//创建一个文档对象SolrInputDocument
		SolrInputDocument document = new SolrInputDocument();
		//向文档对象中添加域,文档中必须包含一个id域,所有的域的名称必须在schema.xml中定义。
		document.addField("id", "test001");
		document.addField("item_title", "测试商品");
		document.addField("item_price", "199");
		//把文档写入索引库
		solrServer.add(document);
		//提交
		solrServer.commit();
	}

删除文档:
实现代码:

     /*
	 * 通过id将文档删除
	 */
	@Test
	public void testSolr03() throws SolrServerException, IOException{
		//创建一个SolrServer对象,创建一个链接,参数solr服务的url
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.129:8080/solr/collection1");
		solrServer.deleteById("test001");
		solrServer.commit();
		
	}
/*
	 * 根据查询删除
	 */
	@Test
	public void testSolr02() throws SolrServerException, IOException{
		//创建一个SolrServer对象,创建一个链接,参数solr服务的url
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.129:8080/solr/collection1");
		solrServer.deleteByQuery("title:change.me");
		solrServer.commit();
		
	}

查询索引库

/**
	 * 使用sorlJ 简单查询索引库
	 * @throws SolrServerException 
	 */
	@Test
	public void queryIndex() throws Exception {
		//创建一个SolrServer对象。
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.163:8080/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"));
		}
	}
//复杂查询
	@Test
	public void queryIndexFuza() throws Exception {
		SolrServer solrServer = new HttpSolrServer("http://192.168.25.163:8080/solr/collection1");
		//创建一个查询对象
		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 = solrServer.query(query);
		//取文档列表。取查询结果的总记录数
		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"));
		}
	}

今日内容三:把商品数据导入到索引库中

注意事项:所写的接口以及类需要发布到服务上,安装到本地仓库中,pojo需要实现序列化接口。需要将mapper.java类通过扫描包的形式,注入到spring容器中
<!-- 配置包扫描器 --> <context:component-scan base-package="cn.e3mall.search"/>

Dao层:sql语句

  	    SELECT
			a.id,
			a.title,
			a.sell_point,
			a.price,
			a.image,
			b. NAME category_name
		FROM
			tb_item a
		LEFT JOIN tb_item_cat b ON a.cid = b.id
		WHERE
			a.`status` = 1

.创建对应数据集的pojo在commo中

public class SearchItem implements Serializable{
	private String id;
	private String title;
	private String sell_point;
	private long price;
	private String image;
	private String category_name;

需要实现序列化接口,以及get,set方法。

接口定义

public interface ItemMapper {

	List<SearchItem> getItemList();
}

.Mapper映射文件

<mapper namespace="cn.e3mall.search.mapper.ItemMapper" >
  <select id="getItemList" resultType="cn.e3mall.common.pojo.SearchItem">
  	    SELECT
			a.id,
			a.title,
			a.sell_point,
			a.price,
			a.image,
			b. NAME category_name
		FROM
			tb_item a
		LEFT JOIN tb_item_cat b ON a.cid = b.id
		WHERE
			a.`status` = 1
  </select>
</mapper>

Service层:
SolrServer在applicationContext-solr的配置:

    <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
		<constructor-arg index="0" value="http://192.168.25.129:8080/solr/collection1"/>
	</bean>
/**
 * 索引库维护Service
 * <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 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, "数据导入时发生异常");
					
		}
	}

}

controller层:

/**
 * 导入商品数据到索引库
 * <p>Title: SearchItemController</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Controller
public class SearchItemController {
	
	@Autowired
	private SearchItemService searchItemService;

	@RequestMapping("/index/item/import")
	@ResponseBody
	public E3Result importItemList() {
		E3Result e3Result = searchItemService.importAllItems();
		return e3Result;
		
	}
}

注意:解决Mapper映射文件不存在异常
在e3-search-service的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>

今日内容四:搜索功能实现

注意事项:
1.需要早common准备一个pojo,实现序列化接口

public class SearchResult implements Serializable{
	private long recordCount;
	private int totalPages;
	private List<SearchItem> itemList;
	}

2.需要一个配置文件resource.properties,用于展示一页显示多少条数据,加载配置文件

SEARCH_RESULT_ROWS=60
<!-- 加载配置文件 -->
	<context:property-placeholder location="classpath:conf/resource.properties" />

3.将接口和实现类发布服务:

<!-- 声明需要暴露的服务接口 -->
	<dubbo:service interface="cn.e3mall.search.service.SearchItemService" ref="searchItemServiceImpl" timeout="600000"/>
	<dubbo:service interface="cn.e3mall.search.service.SearchService" ref="searchServiceImpl" timeout="600000"/>

4.将solrServer对象交给spring容器管理applicationContext-solr.xml

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

dao层:
跟据查询条件查询索引库,返回对应的结果。
参数:SolrQuery
返回结果: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 query) throws SolrServerException {
		// 根据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<>();
		for (SolrDocument solrDocument : solrDocumentList) {
			SearchItem item = new SearchItem();
			item.setId((String) solrDocument.get("id"));
			item.setCategory_name((String) solrDocument.get("item_category_name"));
			item.setImage((String) solrDocument.get("item_image"));
			item.setPrice((long) solrDocument.get("item_price"));
			item.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");
			}
			item.setTitle(title);
			// 添加到商品列表
			itemList.add(item);
		}
		result.setItemList(itemList);
		// 返回结果
		return result;
	}
}

interface:

public interface SearchService {
	SearchResult search(String keyword,int page,int rows) throws Exception;
}

service;
需要有一个接口一个实现类,需要对外发布服务。
参数:String keyWord
int page
int rows
返回值:SearchResult
业务逻辑:
1)根据参数创建一个查询条件对象。需要指定默认搜索域,还需要配置高亮显示。
2)调用dao查询。得到一个SearchResult对象
3)计算查询总页数,每页显示记录数就是rows参数。

代码实现:

/**
 * 商品的搜索service
 * <p>Title: SearchServiceImpl</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Service
public class SearchServiceImpl implements SearchService {

	@Autowired
	private SearchDao searchDao;

	@Override
	public SearchResult search(String keyword, int page, int rows) throws Exception {
		// 创建一个SolrQuery对象
		SolrQuery query = new SolrQuery();
		// 设置查询条件
		query.setQuery(keyword);
		// 设置分页条件
		if (page <= 0) page = 1;
		query.setStart((page - 1) * rows);
		query.setRows(rows);
		// 设置默认搜索域
		query.set("df", "item_title");
		// 开启高亮显示
		query.setHighlight(true);
		query.addHighlightField("item_title");
		query.setHighlightSimplePre("<em style=\"color:red\">");
		query.setHighlightSimplePost("</em>");
		// 调用dao执行查询
		SearchResult searchResult = searchDao.search(query);
		// 计算总页数
		long recordCount = searchResult.getRecordCount();
		int totalPage = (int) (recordCount / rows);
		if (recordCount % rows > 0)
			totalPage++;
		// 添加到返回结果
		searchResult.setTotalPages(totalPage);
		// 返回结果
		return searchResult;
	}
}

controller层:
请求的url:/search
请求的方法:GET
参数:
keyword:查询条件
Page:页码。如果没有此参数,需要给默认值1。
返回的结果:
使用jsp展示,返回逻辑视图。

代码实现:

/**
 * 商品搜索的controller层
 * <p>Title: SearchConreoller</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Controller
public class SearchConreoller {
	@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());
		
		//返回逻辑视图
		return "search";
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值