solr是基于Lucene的企业级的搜索服务器,将其war包部署在web容器中便可以直接运行
java操作solr使用solrJ(solr的java客户端),spring data solr框架(封装了solrJ)提供了solrTemplate简化搜索服务的开发
我们通过搜索引擎能搜索出来的内容都是储存在索引库中的,所以搜索之后可以看到存储的内容,所以这些都必须创建域(field),而存储的内容不一定都要进行索引,可能只是展示,如图片,存储的就是一个图片的url,不会有人搜索这个url也不会对url进行排序等操作,所以图片这个域只存储不建立索引
搜索的过程可以简化一下,原始化的理解一下,就是从数据库查询我想要的sku数据,此过程不受数据库搜索的限制,我们可以想从哪方面搜就从哪方面搜,并且是同时多个条件的.所出来的东西肯定不是一个具体的,而是一个相对具体的,包含了品牌价格区间规格型号等的东西,我们点击进去才能更加具体的去选择.
这样就明白了,要设置哪些域
其中id这个域solr已经定义好,它是唯一的,我们就不定义了,但是在JavaBean中注解的时候还是需要在id上加上@Field注解,如果传入的bean中没有id是会报错的
标题(搜索及显示)
品牌(搜索及显示)
价格(搜索(比如根据价格区间搜索)及显示)
图片(显示)
品牌分类(搜索及显示)
卖家(搜索(品牌和卖家不一定相同,如华为即是卖家又是品牌,但荣耀是华为这个卖家的品牌,搜华为的话华为的多个品牌都会搜到)及显示)
spuid(虽然不显示给用户,但获得了,并根据它进入商品详情页)
复制域就是把其他域的值复制到此域,复制域就不再存储了,因为其他的域已经存储了,复制域是多值的,因为就复制一个域是没意义的.
比如我创建一个叫keywords的复制域,把标题,品牌,卖家,分类域的内容都复制过来,那么我在搜索框输入一个关键字,那么它就可以从多个域中搜索结果了
动态域就是不断变化的域,比如规格, 有很多,如 网络:5G 颜色:红色
这样用一个域就代表了各种可能,动态的调整
使用spring-data-solr首先导入spring-data-solr的jar包 然后创建solr的spring配置文件(定义两个bean) 里面配置了solrTemplate 以及它依赖的solrServer
在修改了schema配置文件以后,solr服务器重启才会生效. 另外增删改的操作必须提交才能生效
solrTemplate.saveBean(object) 新增或修改数据
solrTemplate.getById(1, TbItem.class) 根据id查询
solrTemplate.deleteById(“1”); 根据主键删除
solrTemplate.saveBeans(list) 保存集合,集合中存放对象
solrTemplate.queryForPage(query, TbItem.class); 分页查询
query是查询条件对象 Query query=new SimpleQuery(":"); 查询所有 query.setOffset(20);//开始索引(默认0) query.setRows(20);//每页记录数(默认10)
Criteria criteria =new Criteria (“item_title”)contains(“2”); 创建一个查询条件对象 query.addCriteria(criteria);将查询条件对象加入到查询条件中
Query query=new SimpleQuery(":"); solrTemplate.delete(query); 根据查询对象删除
当我们在搜索中对部分域进行关键字高亮显示后,发现前端页面会原样显示html内容,这是因为Angularjs为防止html攻击而采取的安全措施,我们可以使用
s
c
e
服
务
中
的
t
r
u
s
t
A
S
h
t
m
l
(
d
a
t
a
)
方
法
来
对
此
h
t
m
l
进
行
放
行
但
是
考
虑
到
此
功
能
是
一
个
通
用
的
功
能
,
所
以
直
接
将
它
定
义
到
一
个
过
滤
器
中
a
p
p
.
f
i
l
t
e
(
′
过
滤
器
的
名
字
′
,
[
′
sce服务中的trustAShtml(data)方法来对此html进行放行 但是考虑到此功能是一个通用的功能,所以直接将它定义到一个过滤器中 app.filte('过滤器的名字',['
sce服务中的trustAShtml(data)方法来对此html进行放行但是考虑到此功能是一个通用的功能,所以直接将它定义到一个过滤器中app.filte(′过滤器的名字′,[′sce’,function($sce){
return function(data){
return $sce.trustAsHtml(data);
}
}])
在页面使用ng-bind-html=“item.title | 过滤器的名字” 调用过滤器
service层也可以调用service层,但是被调用的要先启动,判断redis中是否有某个key可以用hasKey来判断
根据关键字搜索出来了要显示的内容,以及加高亮,这是一个最基础的搜索. 我们想要显示搜索的内容的分类,搜索出的内容是有分类这个字段的,那么我们单独对分类这个字段进行分组查询,然后获取到分组的值将其放到一个分类集合中,分类集合及高亮集合都是我们resultMap的一个值,以后要显示品牌,规格我们都加到resultMap中就可以了.
获取到商品分类后根据分类可以找到模板id,根据模板id又可以找到品牌和规格的信息,经过处理就得到了我们想要的数据,放到resultMap中.
因为模板id的查询,品牌规格的查询量太大,我们将其存放于redis中,然后从redis中获取数据,以减轻数据库的访问压力(注意redis存放的问题,保证redis中数据都是最新的,和数据库同步,所以增删改的时候需要重新往人第三种进行存放,我们可以将重新往redis存储的代码写在查询全部中,发生增删改后就查询一次,可以保证每次更新redis中数据都是最新的)
redis-server.exe redis.windows.conf windows中redis的加载配置文件的启动命令,一定要在管理员权限下登陆的cmd中执行
在进行solr查询的时候,每一个查询条件对象query都需要有一个criteria条件对象,但是只能有一个.每一种查询都只有一个主query对象,再有都属于过滤查询对象(它也有一个自己的criteria对象),都需要加在主查询对象里面
在搜索页面进行查询的时候,商品分类的显示只根据关键字查询就可以了,不用考虑后来的条件,我默认显示第一个分类的规格和品牌,如果传了分类,就按照传的分类来,高亮部分的代码才是我们的主题显示代码,需要在这里添加过滤条件
solr调用完毕后记得提交 solrtemplate.commit(); 服务的调用要明确分工,统一由controller调用服务层,各个服务层就是负责自己的业务,不要互相混杂在一起