1、搜索工程的搭建
要实现搜索功能,需要搭建solr服务
、搜索服务工程
、搜索系统(表现层的工程)
1.1、Solr服务搭建
1.1.1、solr的环境
solr是java开发的。
solr的安装文件。
推荐在Linux环境下使用Solr,需要安装环境Linux。
需要安装jdk。参考链接:https://www.cnblogs.com/chenmingjun/p/9931593.html
需要安装tomcat。
1.1.2、solr的搭建步骤
第一步:使用SecureCRT的SFTP功能,把solr-4.10.3.tgz.tgz
的压缩包上传到Linux系统。
第二步:解压缩solr
后,删除该安装包。
[root@itheima ~]# tar -zxvf solr-4.10.3.tgz.tgz
......
......
[root@itheima ~]# ll
总用量 146496
drwxr-xr-x. 8 root root 218 11月 20 17:07 solr-4.10.3
-rw-r--r--. 1 root root 150010621 9月 26 23:16 solr-4.10.3.tgz.tgz
[root@itheima ~]# rm -rf solr-4.10.3.tgz.tgz
[root@itheima ~]# ll
总用量 0
drwxr-xr-x. 8 root root 218 11月 20 17:07 solr-4.10.3
[root@itheima ~]#
第三步:使用SecureCRT的SFTP功能,把apache-tomcat-7.0.47.tar.gz
的压缩包上传到Linux系统,解压后删除安装包。
[root@itheima ~]# tar -zxvf apache-tomcat-7.0.47.tar.gz
[root@itheima ~]# # rm -rf apache-tomcat-7.0.47.tar.gz
第四步:创建solr存放的目录
,复制apache-tomcat-7.0.47目录
到/usr/local/solr/tomcat目录
下
[root@itheima ~]# mkdir /usr/local/solr
[root@itheima ~]# cp -r apache-tomcat-7.0.47/ /usr/local/solr/tomcat
第五步:把solr-4.10.3/dist/solr-4.10.3.war文件
部署(复制)到tomcat
目录下,并重命名为solr.war
。
[root@itheima ~]# cp solr-4.10.3/dist/solr-4.10.3.war /usr/local/solr/tomcat/webapps/solr.war
注意:复制目录(文件夹)的时候需要加-r
,复制文件的时候不需要加-r
。
第六步:解压缩solr.war包
。启动tomcat即可自动解压war包
,并查看tomcat启动日志
。
[root@itheima ~]# cd /usr/local/solr/tomcat/bin/
[root@itheima bin]# ./startup.sh
Using CATALINA_BASE: /usr/local/solr/tomcat
Using CATALINA_HOME: /usr/local/solr/tomcat
Using CATALINA_TMPDIR: /usr/local/solr/tomcat/temp
Using JRE_HOME: /usr/local/java/jdk1.7.0_80/jre
Using CLASSPATH: /usr/local/solr/tomcat/bin/bootstrap.jar:/usr/local/solr/tomcat/bin/tomcat-juli.jar
[root@itheima bin]# cd ..
[root@itheima tomcat]# tail -f logs/catalina.out
十一月 20, 2018 5:23:24 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory /usr/local/solr/tomcat/webapps/host-manager
十一月 20, 2018 5:23:25 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory /usr/local/solr/tomcat/webapps/manager
十一月 20, 2018 5:23:25 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-bio-8080"]
十一月 20, 2018 5:23:25 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["ajp-bio-8009"]
十一月 20, 2018 5:23:25 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 11144 ms
第六步:关闭tomcat后,删除掉没用的solr.war包
。原则:没用的东西及时删掉。
注意:要是想删掉没用的solr.war
包,必须在关闭tomcat的情况
下,否则解压缩后的solr包也会一并删除掉。
[root@itheima tomcat]# bin/shutdown.sh
Using CATALINA_BASE: /usr/local/solr/tomcat
Using CATALINA_HOME: /usr/local/solr/tomcat
Using CATALINA_TMPDIR: /usr/local/solr/tomcat/temp
Using JRE_HOME: /usr/local/java/jdk1.7.0_80/jre
Using CLASSPATH: /usr/local/solr/tomcat/bin/bootstrap.jar:/usr/local/solr/tomcat/bin/tomcat-juli.jar
[root@itheima tomcat]# rm -rf webapps/solr.war
第七步:想要启动solr工程
,还需要添加solr的扩展服务包
。
把/root/solr-4.10.3/example/lib/ext
目录下的所有的jar包,添加到solr工程
中。
[root@itheima ext]# pwd
/root/solr-4.10.3/example/lib/ext
[root@itheima ext]# cp * /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/
第八步:创建一个solrhome
目录。
我们知道:/root/solr-4.10.3/example/solr
目录就是一个solrhome
目录。
复制此目录中所有内容到/usr/local/solr/solrhome
目录下
[root@itheima example]# pwd
/root/solr-4.10.3/example
[root@itheima example]# cp -r solr /usr/local/solr/solrhome
第九步:关联solr工程
及solrhome
。需要修改solr工程
的web.xml
文件。
[root@itheima ~]# cd /usr/local/solr/tomcat/webapps/solr/WEB-INF/
[root@itheima WEB-INF]# vim web.xml
修改如下图所示:
第九步:再次启动tomcat
[root@itheima ~]# cd /usr/local/solr/tomcat/
[root@itheima tomcat]# bin/startup.sh
第十步:修改防火墙配置
CentOS 7.X 默认的防火墙不是iptables,而是firewalld。我们可以试一下systemctl stop firewalld关闭防火墙,但是不推荐该方式。
CentOS 6.X 是iptables,可以使用vim /etc/sysconfig/iptables
修改配置即可。
本博主的是CentOS7,防火墙使用的是firewalld,我们使用命令的方式来添加端口(修改后需要重启firewalld服务):
[root@itheima ~]# cd /etc/firewalld/zones/
[root@itheima zones]# firewall-cmd --permanent --add-port=8080/tcp
success
[root@itheima zones]# service firewalld restart
Redirecting to /bin/systemctl restart firewalld.service
[root@itheima zones]#
第十一步:测试连接
访问地址:http://192.168.25.154:8080/solr/
其实和在windows下的配置完全一样。
浏览器界面如下:
点击按钮“collection1”
1.1.3、solr的使用
添加文档时必须有id域
,其他域必须在solr的schema.xml
中进行定义。
1.2、配置业务域
1.2.1、在schema.xml中需要定义以下字段
1、商品id(根据id查询商品描述页)
2、商品标题title
3、商品卖点sell_point
4、商品价格price
5、商品图片image
6、分类名称category_name(不是分类id,我们一般不会根据商品分类id去查询商品,而是根据商品分类名称去查)
7、商品描述item_desc(实际开发中不需要搜索商品描述)
一共涉及到三张表:tb_item、item_cat、item_desc。
创建对应的业务域。同时需要指定中文分析器。
1.2.2、创建业务域步骤
第一步:把中文分析器添加到solr工程中。
0、把文件夹IK Analyzer 2012FF_hf1
上传至linux中。
1、把IKAnalyzer2012FF_u1.jar
拷贝到solr工程的lib目录
下。
2、把扩展词词典
、停用词字典
、配置文件
拷贝到solr工程的WEB-INF/classes
目录下。(没有classes目录就先创建该目录)
[root@itheima IK Analyzer 2012FF_hf1]# pwd
/root/IK Analyzer 2012FF_hf1
[root@itheima IK Analyzer 2012FF_hf1]# cp IKAnalyzer2012FF_u1.jar /usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/
[root@itheima IK Analyzer 2012FF_hf1]# mkdir /usr/local/solr/tomcat/webapps/solr/WEB-INF/classes
[root@itheima IK Analyzer 2012FF_hf1]# cp mydict.dic ext_stopword.dic IKAnalyzer.cfg.xml /usr/local/solr/tomcat/webapps/solr/WEB-INF/classes
[root@itheima IK Analyzer 2012FF_hf1]# ll /usr/local/solr/tomcat/webapps/solr/WEB-INF/classes
总用量 12
-rw-r--r--. 1 root root 168 11月 20 19:29 ext_stopword.dic
-rw-r--r--. 1 root root 419 11月 20 19:29 IKAnalyzer.cfg.xml
-rw-r--r--. 1 root root 34 11月 20 19:29 mydict.dic
[root@itheima IK Analyzer 2012FF_hf1]#
第二步:配置一个自定义的fieldType
,使用指定的中文分词器IKAnalyzer
。
修改solr工程下的schema.xml
文件,在文件末尾添加一个自定义的fieldType
,注意:要在标签<schema></schema>
里面添加。
[root@itheima conf]# pwd
/usr/local/solr/solrhome/collection1/conf
[root@itheima conf]# vim schema.xml
添加内容如下:
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
第三步:配置业务域,type指定使用自定义的fieldType。
设置业务系统的field
<schema>
......
......
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
<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"/>
<field name="item_desc" type="text_ik" indexed="true" stored="false"/>
<!-- 复制域 -->
<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"/>
<copyField source="item_desc" dest="item_keywords"/>
</schema>
注意:分类名称是不分词只建立索引。商品描述是分词但是不存储。
第四步:重启tomcat,测试我们自定义的业务域是否好使。
测试结果如下:
1.3、搜索服务层工程的搭建
1.3.1、搜索服务工程的创建可以参考taotao-content的创建
taotao-search(聚合工程pom)
|--taotao-search-interface(jar)
|--taotao-search-Service(war)
这里不再赘图了。
目录结构如下:
1.3.2、pom.xml的配置可以参考taotao-content的配置
/taotao-search/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-search</artifactId>
<packaging>pom</packaging>
<modules>
<module>taotao-search-interface</module>
<module>taotao-search-service</module>
</modules>
<dependencies>
<!-- 配置对common的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8085</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
/taotao-search-interface/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-search-interface</artifactId>
<dependencies>
<!-- 配置对pojo的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-pojo</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
/taotao-search-service/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taotao</groupId>
<artifactId>taotao-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>taotao-search-service</artifactId>
<packaging>war</packaging>
<dependencies>
<!-- 配置对dao的依赖 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-manager-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置对interface的依赖:服务层发布服务要通过该接口 -->
<dependency>
<groupId>com.taotao</groupId>
<artifactId>taotao-search-interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- 配置对spring的依赖 -->
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- 配置对dubbo的依赖 -->
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<!-- 排除对低版本jar包的依赖 -->
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>netty</artifactId>
<groupId>org.jboss.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
</dependency>
</dependencies>
</project>
1.3.3、框架整合的配置文件可以参考taotao-content-service的配置
由于搜索的数据涉及到3张表,所以需要自己定义mapper。
而mapper的使用,只在搜索服务工程中,所以mapper接口及映射文件需要放在taotao-search-service工程中。
applicationContext-dao.xml:
<?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">
<!-- 配置数据库连接池 -->
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:properties/*.properties" />
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="driverClassName" value="${jdbc.driver}" />
<property name="maxActive" value="10" />
<property name="minIdle" value="5" />
</bean>
<!-- 配置让spring管理sqlsessionfactory,使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean>
<!-- 配置Mapper映射文件的包扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.mapper" />
</bean>
</beans>
其他配置文件,参考taotao-content-service的配置。
2、测试使用solrJ管理索引库
使用solrJ可以实现索引库的增删改查操作。
2.1、通过SolrJ向索引库中添加/更新索引
第一步:把solrJ的jar包添加到工程中。在Maven工程中则是添加依赖。
在/taotao-search-service/pom.xml添加对solrj客户端的依赖,如下:
<!-- 配置对solrj客户端的依赖 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
第二步:创建一个SolrServer对象(抽象类),使用HttpSolrServer创建对象(连接单机版solr),使用CloudSolrServer创建对象(连接集群版solr)。
第三步:创建一个文档对象SolrInputDocument对象。
第四步:向文档中添加域。必须有id域,且域的名称必须在schema.xml中定义。
第五步:把文档对象添加到索引库中。
第六步:提交。
测试代码如下:
/**
* 向索引库中添加索引
* @throws Exception
*/
@Test
public void addDocumentTest() throws Exception {
// 第一步:把solrJ的jar包添加到工程中。在Maven工程中则是添加依赖。
// 第二步:创建一个SolrServer对象(抽象类),使用HttpSolrServer创建连接对象(连接单机版solr),使用CloudSolrServer创建连接对象(连接集群版solr)。
SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr/collection1"); // 默认是collection1,可写可不写
// 第三步:创建一个文档对象SolrInputDocument对象。
SolrInputDocument document = new SolrInputDocument();
// 第四步:向文档中添加域。必须有id域,且域的名称必须在schema.xml中定义。
document.addField("id", "test001"); // 注意:id是字符串类型,如果是数值类型,会自动转为字符串
document.addField("item_title", "测试商品");
document.addField("item_price", 1999);
// 第五步:把文档对象添加到索引库中。
solrServer.add(document);
// 第六步:提交。
solrServer.commit();
}
2.2、通过SolrJ从索引库中删除索引
(1)根据指定ID来删除索引
/**
* 根据指定ID来删除索引
* @throws Exception
*/
@Test
public void deleteIndexByIdTest() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://192.168.25.154:8080/solr/collection1"); // 参数:是solr服务器的访问地址
// 2、根据指定ID来删除索引
server.deleteById("test001");
// 3、提交。
server.commit();
}
(2)根据指定条件删除索引
/**
* 根据指定条件来删除索引
* @throws Exception
*/
@Test
public void deleteIndexByConditionTest() throws Exception {
// 1、创建HttpSolrServer对象,通过它和solr服务器建立连接。
HttpSolrServer server = new HttpSolrServer("http://192.168.25.154:8080/solr/collection1"); // 参数:是solr服务器的访问地址
// 2、根据指定条件来删除索引
server.deleteByQuery("id:test002");
// 删除全部(慎用)
// server.deleteByQuery("*:*");
// 3、提交。
server.commit();
}
2.3、通过SolrJ从索引库中查询索引
2.3.1、简单查询
/**
* 简单查询
* @throws Exception
*/
@Test
public void queryIndexTest01() throws Exception {
// 1、创建SolrServer对象,通过它和solr服务器建立连接。
SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr/collection1"); // 参数:是solr服务器的访问地址
// 2、创建SolrQuery对象
SolrQuery query = new SolrQuery();
// 设置查询条件,名称"q"是固定的且必须的!
// query.set("q", "item_category_name:手机"); // 等价于 query.setQuery("item_category_name:手机");
query.setQuery("item_category_name:手机");
// 3、调用solrServer的查询方法,查询索引库
QueryResponse response = solrServer.query(query);
// 4、获取查询结果
SolrDocumentList results = response.getResults();
// 5、处理查询结果
System.out.println("查询结果总数为:" + results.getNumFound());
// 6、遍历结果并打印,示例只打印2个字段
for (SolrDocument solrDocument : results) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_price"));
System.out.println("--------------------");
}
}
2.3.2、复杂查询
/**
* 复杂查询
* @throws Exception
*/
@Test
public void queryIndexTest02() throws Exception {
// 1、创建SolrServer对象,通过它和solr服务器建立连接。
SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr/collection1"); // 参数:是solr服务器的访问地址
// 2、创建SolrQuery对象
SolrQuery query = new SolrQuery();
// 设置查询条件
// query.set("q", "item_category_name:手机");
query.setQuery("item_category_name:手机");
// 设置过滤条件,如果设置多个过滤条件的话,需要使用query.addFilterQuery(fq);
// query.setFilterQueries("item_price:[1 TO 20]");
// 设置排序
query.setSort("item_price", ORDER.desc);
// 设置分页信息(使用默认的)
query.setStart(0);
query.setRows(10);
// 设置显示的field的域集合
query.setFields("id,item_title,item_sell_point,item_price,item_image,item_category_name");
// 设置默认搜素域
query.set("df", "item_keywords");
// 设置高亮信息
query.setHighlight(true);
query.addHighlightField("item_title");
query.setHighlightSimplePre("<span color='red'>");
query.setHighlightSimplePost("</span>");
// 3、调用solrServer的查询方法,查询索引库
QueryResponse response = solrServer.query(query);
// 4、获取查询结果
SolrDocumentList results = response.getResults();
// 5、处理查询结果
System.out.println("查询结果总数为:" + results.getNumFound());
// 获取高亮列表
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
// 遍历结果并打印,示例打印所有的字段
for (SolrDocument solrDocument : results) {
System.out.println(solrDocument.get("id"));
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String itemTitle = null;
if (list != null && list.size() > 0) {
itemTitle = list.get(0);
} else {
itemTitle = (String) solrDocument.get("item_title");
}
System.out.println(itemTitle);
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"));
System.out.println("--------------------");
}
}
3、把商品数据导入到索引库中(后台功能)
3.1、功能分析
在schema.xml中定义以下业务域(已经定义好):
1、商品id(根据id查询商品描述页)
2、商品标题title
3、商品卖点sell_point
4、商品价格price
5、商品图片image
6、分类名称category_name(不是分类id,我们一般不会根据商品分类id去查询商品,而是根据商品分类名称去查)
7、商品描述item_desc(实际开发中不需要搜索商品描述)
需要从 tb_item、tb_item_cat、tb_item_desc表中查询数据。
我们先创建对应的业务域(已经创建好了)。同时需要指定中文分析器。
solr服务我们已经搭建好了,自定义的业务域我们也配置好了,现在我们要实现商品搜素功能,那么就需要有数据,需要把数据从数据库中导入进来,之前我们可以使用dataimportHandler插件
,该插件可以将数据库中指定的sql语句的结果导入到solr索引库中
。现在我们需要通过我们网站后台来管理索引库
,而不是通过dataimportHandler插件了,而且我们要做solr集群
的话,插件dataimportHandler会有干扰。所以我们现在不推荐使用dataimportHandler插件。
所以我们在测试环境
下可以使用dataimportHandler插件,但是生产环境
下需要我们手工导入数据。
插件dataimportHandler,使用参考链接:https://www.cnblogs.com/chenmingjun/p/9887696.html#_label2_3
我们使用手工导入数据,需要我们先从数据库中把我们分析出来的业务域取出来,取出来之后,循环插入索引库中去,由于涉及到3张表的查询,所以不能在使用逆向工程生成的Mapper代码了。需要我们手写Mapper代码。我们先把SQL语句写出来,如下:
SQL1:
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b. NAME AS category_name,
c.item_desc
FROM
tb_item a
LEFT JOIN tb_item_cat b ON a.cid = b.id
LEFT JOIN tb_item_desc c ON a.id = c.item_id
WHERE
a.`status` = 1
SQL2:
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b. NAME AS category_name,
c.item_desc
FROM
tb_item a,
tb_item_cat b,
tb_item_desc c
WHERE
a.cid = b.id
AND a.id = c.item_id
AND a.`status` = 1;
3.2、Dao层
3.2.1、创建POJO
创建以下POJO用于存放从数据库中查询到的商品数据
和用于存放从索引库中搜索到的商品数据
,并放入taotao-common中。
/**
* 搜索商品数据使用的POJO,用于存放“从数据库中查询到的商品数据”和用于存放“从索引库中搜索到的商品数据”
* @author chenmingjun
* @date 2018年11月21日上午1:05:12
* @version 1.0
*/
public class SearchItem implements Serializable {
private static final long serialVersionUID = 1L;
private String id; // 商品的id,我们使用文档的id域作为商品的id,文档的id域默认定义的是String类型
private String title; // 商品的标题
private String sell_point; // 商品的卖点
private Long price; // 商品的价格
private String image; // 商品的图片路径
private String category_name; // 商品的分类名称
private String item_desc; // 商品的描述
// getter和setter方法
}
注意:在我们schema.xml文件中,我们使用文档的id域作为商品的id,而文档的id域默认定义的是String类型,索引库会自动转换将数值类型转换为字符串进行存储,我们从索引库中取出数据,我们也使用字符串进行接收。
3.2.2、定义Mapper接口
SearchItemMapper.java
/**
* 搜索商品的Mapper
* @author chenmingjun
* @date 2018年11月21日上午11:23:28
* @version 1.0
*/
public interface SearchItemMapper {
/**
* 查询所有商品数据。(注意:是从3张表中查,此商品非彼商品)
* @return
*/
List<SearchItem> getSearchItemList();
}
3.2.3、编写Mapper映射文件
SearchItemMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.taotao.search.mapper.SearchItemMapper" >
<select id="getSearchItemList" resultType="com.taotao.common.pojo.SearchItem">
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b. NAME AS category_name,
c.item_desc
FROM
tb_item a
LEFT JOIN tb_item_cat b ON a.cid = b.id
LEFT JOIN tb_item_desc c ON a.id = c.item_id
WHERE
a.`status` = 1
</select>
</mapper>
3.3、Service层
参数:无
业务逻辑:
1、查询所有商品数据。
2、创建一个SolrServer对象(抽象类),使用HttpSolrServer创建连接对象(连接单机版solr),使用CloudSolrServer创建连接对象(连接集群版solr)。
3、为每个商品创建一个文档对象SolrInputDocument对象。
4、为文档添加域。必须有id域,且域的名称必须在schema.xml中定义。
5、把文档对象添加到索引库中。
6、提交修改。
7、返回TaotaoResult。
3.3.1、配置单机版solr的连接:HttpSolrServer
SolrServer我们使用spring容器生成后注入进来,需要在配置文件进行配置:
applicationContext-solr.xml
<?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">
<!-- 配置单机版solr的连接:HttpSolrServer-->
<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg name="baseURL" value="http://192.168.25.154:8080/solr/collection1"></constructor-arg>
</bean>
</beans>
3.3.2、定义service接口
接口放在taotao-search-interface中
/**
* 从数据库中查询到数据导入索引库
* @author chenmingjun
* @date 2018年11月21日下午2:38:41
* @version 1.0
*/
public interface SearchItemService {
/**
* 导入搜索的商品数据到索引库中
* @return
* @throws Exception
*/
TaotaoResult importSearchItemsToIndex() throws Exception;
}
3.3.3、定义service实现类
要想注入SearchItemMapper成功,需要在taotao-search-service
的applicationContext-dao.xml
文件中进行配置Mapper映射文件的包扫描器
:
有两种配置方式:
方式一:
<!-- 配置Mapper映射文件的包扫描器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.mapper" />
</bean>
<!-- 配置只用于搜索功能的Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.search.mapper" />
</bean>
方式二:
<!-- 配置Mapper映射文件的包扫描器,扫描多个包,使用逗号进行分割 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.mapper,com.taotao.search.mapper" />
</bean>
本案例中我们使用方式二。
实现类代码如下:
/**
* 从数据库中查询到数据导入索引库
* @author chenmingjun
* @date 2018年11月21日下午2:42:11
* @version 1.0
*/
@Service
public class SearchItemServiceImpl implements SearchItemService {
// 注入SearchItemMapper
@Autowired
private SearchItemMapper searchItemMapper;
// 注入SolrServer
@Autowired
private SolrServer solrServer;
@Override
public TaotaoResult importSearchItemsToIndex() throws Exception {
// 1、查询所有商品数据。
List<SearchItem> searchItemList = searchItemMapper.getSearchItemList();
// 2、创建一个SolrServer对象(抽象类),使用HttpSolrServer创建连接对象(连接单机版solr),使用CloudSolrServer创建连接对象(连接集群版solr)。
// SolrServer我们使用spring容器生成后注入进来
for (SearchItem searchItem : searchItemList) {
// 3、为每个商品创建一个文档对象SolrInputDocument对象。
SolrInputDocument document = new SolrInputDocument();
// 4、为文档添加域。必须有id域,且域的名称必须在schema.xml中定义。
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());
document.addField("item_desc", searchItem.getItem_desc());
// 5、把文档对象添加到索引库中。
solrServer.add(document);
}
// 6、提交修改。
solrServer.commit();
// 7、返回TaotaoResult。
return TaotaoResult.ok();
}
}
3.3.4、在taotao-search-service中发布服务
特别注意:
由于我们的dubbo和zooKeeper是安装在虚拟机CentOS 7.5 上的,CentOS 7.X 默认的防火墙不是iptables,而是firewalld。我们可以试一下systemctl stop firewalld关闭防火墙,但是不推荐该方式。CentOS 6.X 是iptables,可以使用vim /etc/sysconfig/iptables
修改配置即可。
本博主的是CentOS7,防火墙使用的是firewalld,我们使用命令的方式来添加端口20882(修改后需要重启firewalld服务):
[root@itheima ~]# cd /etc/firewalld/zones/
[root@itheima zones]# firewall-cmd --permanent --add-port=20882/tcp
success
[root@itheima zones]# service firewalld restart
Redirecting to /bin/systemctl restart firewalld.service
[root@itheima zones]#
3.4、表现层
3.4.1、引用服务
由于把从数据库中查询到的新的商品数据导入到索引库中
属于后台功能
,所以我们在taotao-manager-web中引用服务。
在/taotao-manager-web/src/main/resources/spring/springmvc.xml中引用服务:
3.4.2、添加对taotao-search-interface的依赖
在taotao-manager-web工程中的pom.xml中添加如下: