全文检索技术—Solr
前言:
solr是一个现成的全文检索引擎系统, 放入tomcat下可以独立运行, 对外通过http协议提供全文检索服务(就是对索引和文档的增删改查服务),企业中可以通过solrJ(solr的客户端的jar包)来调用solr服务。
Solr与Lucene的区别:
lucene是一个全文检索引擎工具包, 就是一堆jar包, 它放入tomcat下不能独立运行, 但是我们可以使用lucene来构建全文检索引擎系统;
solr底层是用lucene来开发的一个全文检索引擎系统, 放入tomcat下就可以独立运行, 对外通过http的形式,提供全文检索服务(索引和文档的增删改查服务).
一、Solr安装及配置:
Solr官方网站(http://lucene.apache.org/solr/ )下载Solr4.10.3,Linux下需要下载lucene-4.10.3.tgz,windows下需要下载lucene-4.10.3.zip。
整合步骤
Solr域的类型:
基本类型:string, long, double等等
动态域(dynamicField): 因为域要先定义后使用,对于没有定义的域,使用是会报错的, 所以可以使用动态域模糊匹配域名.
主键域(uniquekey): 主键域只有一个, 唯一
复制域(copyField): 将多个域中的内容复制到目标域, 从目标域中查询就相当于从多个域中进行查询
集成IK中文分词器:
schema.xml设置Field
数据导入到solr
1、把dataimport插件依赖的jar包添加到solrcore(solrHome\collection1\lib)中
2、配置solrconfig.mxl文件,添加一个requestHandler。
3、创建一个data-config.xml,保存到collection1\conf\目录下
4、重启tomcat
二、使用Solr管理索引库
1、solr中索引和文档的增加和删除
首先根据id来查询,如果在现有的文档库和索引库中查不到则,将这条数据添加进索引库和文档库;若根据id查找到了,则把查找到的删除, 然后将新的数据添加到索引库和文档库。
2、删除索引格式如下:
三、使用SolrJ管理索引库
SolrJ是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常在嵌入在业务系统中,通过SolrJ的API接口操作Solr服务.
代码实现
增删改
public class IndexManagerTest { //solr中没有专门的修改方法, 先是根据id查询,查找到了则先边原来的删掉,再将新的增加, 如果没查询到,则直接增加新的 @Test public void testIndexCreate() throws Exception{ //指定solr默认服务的url, 如果想连接其他实例可以 http://localhost:8080/solr/collection2 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //创建solr文档对象, 域一定要先定义后使用,在solr服务端中的schema.xml中定义 //一定要有id域 SolrInputDocument doc = new SolrInputDocument(); doc.addField("id", "a001"); doc.addField("title_ik", "国人"); doc.addField("content_ik", "我是中国人"); solrServer.add(doc); //提交 solrServer.commit(); } @Test public void testDelIndex() throws Exception{ //连接默认实例, collection1 SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //根据id删除 //solrServer.deleteById("a001"); //删除所有 solrServer.deleteByQuery("*:*"); //提交 solrServer.commit(); }
查
public class IndexSearchTest { @Test public void testIndexSearchSample() throws Exception{ SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //创建查询条件对象 SolrQuery solrQuery = new SolrQuery(); //查询所有 solrQuery.setQuery("*:*"); //查询并返回响应 QueryResponse queryResponse = solrServer.query(solrQuery); //从响应中获取查询结果集 SolrDocumentList results = queryResponse.getResults(); //查询到的数据的总数 System.out.println("=====count=====" + results.getNumFound()); //遍历结果集 for(SolrDocument doc : results){ //根据域名取出数据 System.out.println(doc.get("id")); System.out.println(doc.get("product_name")); System.out.println(doc.get("product_price")); System.out.println(doc.get("product_picture")); System.out.println("========================="); } } @Test public void testIndexSearch() throws Exception{ SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr"); //创建查询条件对象 SolrQuery solrQuery = new SolrQuery(); //设置查询条件 solrQuery.setQuery("台灯"); //设置过滤条件 solrQuery.addFilterQuery("product_price:[1 TO 100]"); //设置按照价格排序, 这里是升序 solrQuery.setSort("product_price", ORDER.asc); //设置分页 //从第几条开始查询 solrQuery.setStart(0); //查询多少条 solrQuery.setRows(10); //设置查询到后显示哪些域 solrQuery.addField("id,product_name,product_price,product_catalog_name,product_picture"); //设置默认搜索域, df代表默认搜索域, 后面的是域名 solrQuery.set("df", "product_keywords"); //设置高亮显示: 高亮默认是关闭的, 需要开启 solrQuery.setHighlight(true); //设置需要高亮显示的域名 solrQuery.addHighlightField("product_name"); //设置高亮前缀 solrQuery.setHighlightSimplePre("<span style=\"color:red\">"); //设置高亮后缀 solrQuery.setHighlightSimplePost("</span>"); //查询并返回响应 QueryResponse queryResponse = solrServer.query(solrQuery); //从响应中获取查询结果集 SolrDocumentList results = queryResponse.getResults(); //查询到的数据的总数 System.out.println("=====count=====" + results.getNumFound()); //遍历结果集 for(SolrDocument doc : results){ //根据域名取出数据 System.out.println(doc.get("id")); //获取高亮显示结果 Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting(); if(highlighting != null){ List<String> list = highlighting.get(doc.get("id")).get("product_name"); if(list != null && list.size() > 0){ System.out.println("==hlighting==" + list.get(0)); } } System.out.println(doc.get("product_name")); System.out.println(doc.get("product_price")); System.out.println(doc.get("product_picture")); System.out.println("==================="); } }
四、案例实现
1、流程图
2、创建一个web工程导入jar包(springmvc的相关jar包+solrJ的jar包+Example\lib\ext下的jar包)
3、配置SpringMvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 配置@Controller注解扫描 --> <context:component-scan base-package="cn.itcast"></context:component-scan> <!-- 注解驱动: 相当于显示的配置了最新版的注解形式的处理器映射器和处理器适配器 --> <mvc:annotation-driven/> <!-- 视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- SolrServer的配置 --> <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer"> <constructor-arg index="0" value="http://localhost:8080/solr"/> </bean> </beans>
4、配置Web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>solrjd0608</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置springMvc前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:SpringMvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <!-- 处理Post乱码 --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
5、实体类
5、Controller
6、Service
@Service public class ProductServiceImpl implements ProductService { //设置每页显示条数 private final static Integer PAGE_SIZE = 60; @Autowired private ProductDao productDao; @Override public ResultModel querySolr(String queryString, String catalog_name, String price, Integer page, String sort) throws Exception{ //创建查询条件对象 SolrQuery solrQuery = new SolrQuery(); //设置默认搜索域 solrQuery.set("df", "product_keywords"); //设置查询条件 if(queryString != null && !"".equals(queryString)){ solrQuery.setQuery(queryString); } else { solrQuery.setQuery("*:*"); } //设置过滤条件按照分类查询 if(catalog_name != null && !"".equals(catalog_name)){ solrQuery.addFilterQuery("product_catalog_name:" + catalog_name); } //设置过滤条件 按照价格区间进行查询 if(price != null && !"".equals(price)){ String[] split = price.split("-"); if(split != null && split.length > 1){ solrQuery.addFilterQuery("product_price:["+split[0]+" TO "+split[1]+"]"); } } //按照价格进行排序 if("0".equals(sort)){ solrQuery.setSort("product_price", ORDER.asc); } else { solrQuery.setSort("product_price", ORDER.desc); } //设置起始页 if(page == null){ page = 1; } //设置从第几条开始查 Integer start = (page - 1) * PAGE_SIZE; solrQuery.setStart(start); //设置每页显示条数 solrQuery.setRows(PAGE_SIZE); //设置高亮显示 //开启高亮显示 solrQuery.setHighlight(true); //设置高亮显示的域 solrQuery.addHighlightField("product_name"); //设置高亮显示前缀 solrQuery.setHighlightSimplePre("<span style=\"color:red\">"); //设置高亮显示后缀 solrQuery.setHighlightSimplePost("</span>"); //调用dao查询,并返回结果 ResultModel resultModel = productDao.query(solrQuery); //设置当前页 resultModel.setCurPage(page); //计算总页数 Long pageCount = resultModel.getRecordCount() / PAGE_SIZE; if(resultModel.getRecordCount() % PAGE_SIZE > 0){ pageCount++; } resultModel.setPageCount(pageCount); return resultModel; } }
7、Dao
@Repository public class ProductDaoImpl implements ProductDao { @Autowired private SolrServer solrServer; @Override public ResultModel query(SolrQuery solrQuery) throws Exception { //通过solr服务端查询,并返回响应 QueryResponse queryResponse = solrServer.query(solrQuery); //返回的数据对象 ResultModel resultModel = new ResultModel(); List<ProductModel> productList = new ArrayList<ProductModel>(); //从响应中获取结果集 SolrDocumentList results = queryResponse.getResults(); if(results != null){ //获取查询到的总记录数 resultModel.setRecordCount(results.getNumFound()); //遍历结果集 for(SolrDocument doc : results){ ProductModel product = new ProductModel(); product.setPid(String.valueOf(doc.get("id"))); //获取高亮数据 Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting(); if(highlighting != null){ List<String> list = highlighting.get(doc.get("id")).get("product_name"); if(list != null && list.size() > 0){ product.setName(list.get(0)); } else { product.setName(String.valueOf(doc.get("product_name"))); } } else { product.setName(String.valueOf(doc.get("product_name"))); } if(doc.get("product_price") != null && !"".equals(doc.get("product_price"))){ product.setPrice(Float.valueOf(String.valueOf(doc.get("product_price")))); } product.setCatalog_name(String.valueOf(doc.get("product_catalog_name"))); product.setPicture(String.valueOf(doc.get("product_picture"))); //将单个的ProductModel对象放入集合中 productList.add(product); } //将封装后的结果集放入返回对象中 resultModel.setProductList(productList); } return resultModel; } }
更多java、大数据学习面试资料,请扫码关注我的公众号: