黑马程序员技术交流社区
标题: 【广州校区】+【原创】solr [打印本页]
作者: 余大麻 时间: 2018-12-6 11:10
标题: 【广州校区】+【原创】solr
1.solr概要A.solr简介- Solr是Apache下的一个顶级开源项目,底层是由lucene实现的全文搜索服务
- solr已经把lucene封装成一个web项目,我们用的时候只需要安装和配置
- 安装比较简单(直接解压war包)
- 配置比较麻烦(从自带的netty服务器迁移到tomcat服务器)
- solr作用
- 使用solr实现站内搜索功能
- 使用传统的数据库查询方式实现搜索无法满足一些高级的搜索需求
- solr操作流程
B.solr和lucene区别- lucene是一个全文搜索的工具包,让开发人员自己扩展
- solr是封装了lucene的全文搜索服务
2.solr安装(解压war包-->补全jar包-->配置solrHome)A.解压war包- 创建一个空文件夹solrService
- 解压一个新的tomcat7.0以上版本到当前文件夹
- 解压solr的压缩包到当前文件夹
- 创建一个文件夹:solrHome
B.把war包拷贝到tomcat的webapp下- 发布solr工程
- 在solr文件夹--->example--->webapps--->solr.war
- 复制到tomcat--->webapps--->粘贴
- 解压war包在当前目录,完成后删除war包
- 因为需要往项目里配置依赖包,
- 不然每次启动tomcat都会解压一次solr.war
C.补全迁移中缺少的jar包- solr官方把工程整合到netty中
- 项目需要的jar包没有完全放到solr.war中
- 有一部分在netty服务器里
- 我们需要把缺少的jar包补全
- tomcat有两处存放jar包的地方
- 在刚刚拷贝war的上级目录--->lib--->ext--->5个jar包--->复制
- 粘贴到tomcat项目下的solr的WEB-INF的lib中
D.配置solr的家(索引库)- 原生solr工程的索引库在netty工程里的,我们要迁移出来
- 在tomcat同级目录创建solrHome目录,用于存储索引(便于集群的时候可以统一存放目录)
- 把solr解压包中--->example---solr目录下的所有文件拷贝到刚刚的目录下(soleHome)
E.配置家目录- 在tomcat中的solr项目中,在WEB-INF中 * web.xml是tomcat的配置文件 * weblogic.xml是weblogic服务器的配置文件
- 打开web.xml文件,在第40行: <env-entry>把注释去掉,value值改成我们刚刚创建的家目录: solrData
F.启动tomcat--->ok提示:solrHome中有关配置- 刚拷贝得到的solrHome是solr存放索引的位置,其中collection1文件夹是其中一个solrcore
- 我们需要关注这个文件夹下的collection1-->conf--->schema.xml,用于定义项目中用到的file名称
2.索引的操作A.添加索引库- 在solr工程页面添加索引库会报错
- 我们的工程迁移不完整
- 我们可以手动在solrHome目录手动添加
- 我们可以拷贝一份solrHome里的collection1,改个名字
- 但是拷贝后要修改core.properties文件里的配置跟文件夹名一致
- 添加完毕后重启服务器
- solr后台界面(localhost:8080/solr),然后就可以看到我们刚手动添加的索引库了
5.中文分析器配- 每个核中有很多配置文件,我们只需关注2个
- schema.xml---->用于配置域
- 之前我们用lucene时是手动写field的,使用solr把域写好在配置文件中使用
- solrconfig.xml---->用于自定义Filed域
A.Schema.xml- schema.xml,在SolrCore的conf目录下,不同的collection有不同的shema.xml,它是solr数据表的配置文件
- FieldType域类型定义
- 定义File的类型,定义这个类型的file是否需要分析,索引,保存和定义是否什么分析器
- Field定义
- 我们自己定义的file名称,需要基于FileType来确定是否分析,索引,保存,使用分析器类型等
- uniqueKey
- Solr中默认定义唯一主键key为id域,如下:
- <uniqueKey>id</uniqueKey>
- Solr在删除、更新索引时使用id域进行判断,也可以自定义唯一主,注意在创建索引时必须指定唯一约束
- copyField复制域
- copyField复制域,可以将多个Field复制到一个Field中,以便进行统一的检索
- 如我们的document使用的cat,name,manu中的一个或者多个
- 分别保存索引后,后台会主动将使用过的file整合到一个叫text的域中
- 便于我们以后使用搜索的时候用,text域内包含了cat,name,manu的内容合并
[XML] 纯文本查看 复制代码
<copyField source="cat" dest="text"/>
<copyField source="name" dest="text"/>
<copyField source="manu" dest="text"/>
dynamicField(动态域)
- 动态字段就是不用指定具体的名称,只要定义字段名称的规则
[XML] 纯文本查看 复制代码
<dynamicField name="*_i" type="int" indexed="true" stored="true"/>
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
B.安装中文分词器- 把IKAnalyzer2012FF_u1.jar添加到solr/WEB-INF/lib目录下
- 复制IKAnalyzer的配置文件和自定义词典和停用词词典到solr的classpath下
- 在schema.xml中添加一个自定义的fieldType,使用中文分析器
[XML] 纯文本查看 复制代码
<!-- IKAnalyzer-->
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
- 定义field,指定field的type属性为text_ik
[XML] 纯文本查看 复制代码
<!--IKAnalyzer Field-->
<field name="title_ik" type="text_ik" indexed="true" stored="true" />
<field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/>
C.设置业务系统Field- 如果不使用Solr提供的Field可以针对具体的业务需要自定义一套Field,如下是商品信息Field
[XML] 纯文本查看 复制代码
<!--product-->
<field name="product_name" type="text_ik" indexed="true" stored="true"/>
<field name="product_price" type="float" indexed="true" stored="true"/>
<field name="product_description" type="text_ik" indexed="true" stored="false" />
<field name="product_picture" type="string" indexed="false" stored="true" />
<field name="product_catalog_name" type="string" indexed="true" stored="true" />
<field name="product_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="product_name" dest="product_keywords"/>
<copyField source="product_description" dest="product_keywords"/>
6.Solr管理索引库A.添加/更新文档B.批量导入数据- 把dataimport插件依赖的jar包添加到solrcore(collection1\lib)中
- dist文件夹下:
- solr-dataimporthandler-4.10.3.jar
- solr-dataimporthandler-extras-4.10.jar
- 没有lib包要创建lib包
- 加入mysql的数据库驱动到lib文件夹里
- 配置solrconfig.xml文件,添加一个requestHandler
- collection-->conf-->solrconfig.xml
[XML] 纯文本查看 复制代码
<requestHandler name="/dataimport"
class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
- 创建一个data-config.xml,保存到collection1\conf\目录下
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/lucene"
user="root"
password="root"/>
<document>
<entity name="product" query="SELECT pid,name,catalog_name,price,description,picture FROM products ">
<field column="pid" name="id"/>
<field column="name" name="product_name"/>
<field column="catalog_name" name="product_catalog_name"/>
<field column="price" name="product_price"/>
<field column="description" name="product_description"/>
<field column="picture" name="product_picture"/>
</entity>
</document>
</dataConfig>
C.删除文档[XML] 纯文本查看 复制代码
<delete>
<id>8</id>
</delete>
<commit/>
[XML] 纯文本查看 复制代码
<delete>
<query>product_catalog_name:幽默杂货</query>
</delete>
<commit/>
[XML] 纯文本查看 复制代码
<delete>
<query>*:*</query>
</delete>
<commit/>
7.查询索引- 通过/select搜索索引,Solr制定一些参数完成不同需求的搜索
A.使用SolrJ管理索引库- solrj是访问Solr服务的java客户端,提供索引和搜索的请求方法,SolrJ通常在嵌入在业务系统中
- 依赖jar包
- solrj-lib文件夹
- solr-solrj-4.10.3.jar
- 还需要solr-4.10.3--->example--->lib--->ext下的jar包
B.添加索引- 创建工程
- 导入jar包
- 使用HttpSolrServer对象建立连接
- 创建一个SolrInputDocument对象,然后添加域
- 将SolrInputDocument添加到索引库
- 提交
[Java] 纯文本查看 复制代码
public void addDocument() throws Exception {
"和solr服务器创建连接"
"参数:solr服务器的地址"
SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
"创建一个文档对象"
SolrInputDocument document = new SolrInputDocument();
"向文档中添加域"
"第一个参数:域的名称,域的名称必须是在schema.xml中定义的"
"第二个参数:域的值"
document.addField("id", "c0001");
document.addField("title_ik", "使用solrJ添加的文档");
document.addField("content_ik", "文档的内容");
document.addField("product_name", "商品名称");
"把document对象添加到索引库中"
solrServer.add(document);
"提交修改"
solrServer.commit();
}
C.删除文档(根据id删除)
[Java] 纯文本查看 复制代码
public void deleteDocumentByid() throws Exception {
"创建连接"
SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
"根据id删除文档"
solrServer.deleteById("c0001");
"提交修改"
solrServer.commit();
}
D.根据查询删除
[Java] 纯文本查看 复制代码
public void deleteDocumentByQuery() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
solrServer.deleteByQuery("*:*");
solrServer.commit();
}
E.修改文档- 在solrJ中修改没有对应的update方法,只有add方法,只需要添加一条新的文档,和被修改的文档id一致就,可以修改了,本质上就是先删除后添加
8.查询文档A.简单查询[Java] 纯文本查看 复制代码
public void queryIndex() throws Exception {
//创建连接
SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
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("product_name"));
System.out.println(solrDocument.get("product_price"));
System.out.println(solrDocument.get("product_catalog_name"));
System.out.println(solrDocument.get("product_picture"));
}
}
B.复杂查询[Java] 纯文本查看 复制代码
public void queryIndex2() throws Exception {
//创建连接
SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr");
//创建一个query对象
SolrQuery query = new SolrQuery();
//设置查询条件
query.setQuery("钻石");
//过滤条件
query.setFilterQueries("product_catalog_name:幽默杂货");
//排序条件
query.setSort("product_price", ORDER.asc);
//分页处理
query.setStart(0);
query.setRows(10);
//结果中域的列表
query.setFields("id","product_name","product_price","product_catalog_name","product_picture");
//设置默认搜索域
query.set("df", "product_keywords");
//高亮显示
query.setHighlight(true);
//高亮显示的域
query.addHighlightField("product_name");
//高亮显示的前缀
query.setHighlightSimplePre("<em>");
//高亮显示的后缀
query.setHighlightSimplePost("</em>");
//执行查询
QueryResponse queryResponse = solrServer.query(query);
//取查询结果
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println("共查询到商品数量:" + solrDocumentList.getNumFound());
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
"取高亮显示"
String productName = "";
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("product_name");
"判断是否有高亮内容"
if (null != list) {
productName = list.get(0);
} else {
productName = (String) solrDocument.get("product_name");
}
System.out.println(productName);
System.out.println(solrDocument.get("product_price"));
System.out.println(solrDocument.get("product_catalog_name"));
System.out.println(solrDocument.get("product_picture"));
}
}
9.案例实现(JD商城)- springmvc的相关jar包
- solrJ的jar包
- Example\lib\ext下的jar包
[XML] 纯文本查看 复制代码
"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: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://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.itheima.jd"/>
<!-- 配置注解驱动,如果配置此标签可以不用配置处理器映射器和适配器 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- SolrServer的配置 -->
<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg index="0" value="http://localhost:8080/solr"/>
</bean>
</beans>
[XML] 纯文本查看 复制代码
"web.xml"
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--
指定springmvc配置文件的路径
如果不指定默认为:/WEB-INF/${servlet-name}-servlet.xml
-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</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>
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |