- solr是一个开源搜索平台 它是基于Lucene的全文搜索服务器
- 特点 比关系型数据库搜索速度要快 关系型数据库只能进行模糊查询 低效 数据库压力大 所以用solr做搜索功能
- solr本身是在tomcat环境下运行
- solr下的 /example/solr目录就是solr的家 将solr改名为solrhome
- 关联solr和solrhome 需要修改 solr工程的web.xml 设置solrhome的路径位置
-
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>d:\solrhome</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry> - 输入http://IP:8080/solr/就可以访问solr了
- IK Analyzer 中文分词工具包
- 在solr工程的lib中添加分词器的jar包
- solr工程中创建 WEB-INF/calsses文件夹 放上1扩展词典 以.dic结尾 2 停用词典 以.dic结尾, 配置文件(设置1,2的位置)
- 修改solrhome中的schema.xml文件配置一个fieldType 使用Ik分词器
-
<fieldType name="text_ik" class="solr.TextField"> <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType>
-
配置域 域相当于数据库中的表字段
-
域常用属性
-
name 指定域名称
-
type指定域类型 (可以设置成中文分词器filedType的名字 text_ik)就可以进行中文分词效果了
-
indexed是否进行索引 即根据这个字段查询
-
stored是否进行存储
-
required是否必须
-
multiValue是否多值
-
修改solrhome的schema.xml 文件 设置业务系统 Field
-
<field name="item_goodsid" type="long" indexed="true" stored="true"/> <field name="item_title" type="text_ik" indexed="true" stored="true"/> <field name="item_price" type="double" indexed="true" stored="true"/> <field name="item_image" type="string" indexed="false" stored="true" /> <field name="item_category" type="string" indexed="true" stored="true" /> <field name="item_seller" type="text_ik" indexed="true" stored="true" /> <field name="item_brand" type="string" indexed="true" stored="true" />
- 动态域
- <dynamicField name="item_spec_*" type="string" indexed="true" stored="true" />
- 复制域 source原目标域, dest 复制域的名称 当需要进行多条件查询时不确定是按那个条件查询就可以设置复制域
-
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/> 商品标题
<copyField source="item_category" dest="item_keywords"/>商品分类
<copyField source="item_brand" dest="item_keywords"/>商品品牌 - 在src/main/resources下创建 applicationContext-solr.xml 配置 solr服务器地址 和 solrTemplate模板,使用solr模板可对索引库进行CRUD的操作
- 如果 pojo实体类中的属性名称和solr配置域中名称不相同则应在pojo属性上加@Field(“item_id”)指定对应的域名称
- 保存数据到solr中可以添加注解
@Autowired private SolrTemplate solrTemplate solrTemplate.saveBean(User) solrTemplate.commit()
- 按主键查询 User user=solrTemplate.getById(id值,User.class)
- 按主键删除 solr.deleteById("id值")
- 条件查询 Query query =new SimpleQuery("*:*")
- 开始索引 query.setOffset(20) solr默认是从0开始
- 每页记录数query.setRows(20)
- 分页查询 ScoredPage page= solrTemplate.queryForPage(query,User.class)
- 获得总记录数 page.getTotalElements()
- 获取查询内容 page.getContent()
Query query=new SimpleQuery("*:*");
query.setOffset(20);//开始索引(默认0)
query.setRows(20);//每页记录数(默认10)
ScoredPage<TbItem> page = solrTemplate.queryForPage(query, TbItem.class);
System.out.println("总记录数:"+page.getTotalElements());
List<TbItem> list = page.getContent();
- 条件查询 solr自带的 Criteria criteria =new Criteria("tb_username").is("张三") 查询用户名就是张三的
- 继续查询密码包含aa的 criteria.and("tb_password").contains("aa")
控制层调用服务层时避免超时 应加@Reference(timeout=5000)
项目中在后端服务层使用Map接收数据 返回键名为rows 的数据
@Override
public Map<String, Object> search(Map searchMap) {
Map<String,Object> map=new HashMap<>();
Query query=new SimpleQuery();
//添加查询条件
Criteria criteria=new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
ScoredPage<TbItem> page = solrTemplate.queryForPage(query, TbItem.class);
map.put("rows", page.getContent());
return map;
}
}
pinyougou-search-web工程searchController.js
app.controller('searchController',function($scope,searchService){
//搜索
$scope.search=function(){
searchService.search( $scope.searchMap ).success(
function(response){
$scope.resultMap=response;//搜索返回的结果
}
);
}
});
前端页面
ng-model="searchMap.keywords" 传给后端的map中的key叫keywords 值为页面输入的值
ng-repeat="aa in resultMap.rows" 循环后端传回来的数据键名rows 就可以取出数据
- 高亮显示 后端service层
- HighlightQuery query =new SimpleHighlightQuery();
- 添加高亮选项HighlightOptions options=new HighlightOptions().addField("item_title")
- 添加前缀 options.setSimplePrefix() 后缀 options.setSimplePostfix()
- solrTemplate.queryForHighlightPage(query,TbItem.class)
-
/** * 根据关键字搜索列表 * @param keywords * @return */ private Map searchList(Map searchMap){ Map map=new HashMap(); HighlightQuery query=new SimpleHighlightQuery(); HighlightOptions highlightOptions=new HighlightOptions().addField("item_title");//设置高亮的域 highlightOptions.setSimplePrefix("<em style='color:red'>");//高亮前缀 highlightOptions.setSimplePostfix("</em>");//高亮后缀 query.setHighlightOptions(highlightOptions);//设置高亮选项 //按照关键字查询 Criteria criteria=new Criteria("item_keywords").is(searchMap.get("keywords")); query.addCriteria(criteria); HighlightPage<TbItem> page = solrTemplate.queryForHighlightPage(query, TbItem.class); for(HighlightEntry<TbItem> h: page.getHighlighted()){//循环高亮入口集合 TbItem item = h.getEntity();//获取原实体类 if(h.getHighlights().size()>0 && h.getHighlights().get(0).getSnipplets().size()>0){ item.setTitle(h.getHighlights().get(0).getSnipplets().get(0));//设置高亮的结果 } } map.put("rows",page.getContent()); return map; }
js中设置消除安全机制设置过滤器 中添加 $sce.trustAsHtml(data)
/*$sce服务写成过滤器*/
app.filter('aa',['$sce',function($sce){
return function(data){
return $sce.trustAsHtml(data);
}
}]);
html页面 ng-bind-html用于显示html内容 在此显示color标签
| 代表调用过滤器aa
<div class="attr" ng-bind-html="item.title | aa"></div> |
- 按价格区间过滤
- 前端key='price" value为价格值
- 后端 根据price键获取值 String [] price=aa.get("price").split("-")
- FilterQuery query=new SimpleFilterQuery()
- Criteria filterCriteria=new Criteria("item-price").graterThanEqual(price[0])
- 价格排序 后端根据前端点击 判断
- 升序 Sort sort =new Sort(Sort.Direction.ASC,"item_price")
- 降序 Sort sort =new Sort(Sort.Direction.DESC,"item_price")
- query.add(sort)
- @Field 注解匹配实体类和solr数据库中名称不同 是solrj包下的
- 搜索项目分析
- 通过search方法 参数是map类型 参数返回值是map类型,添加条件通过solr配置域中复制域来查询
- Criteria criteria =new Criteria("item_keywords").is(map.get("key"));
- ===========================
- 商品分类 通过 solrTemplate.queryForGroupPage() 进行分组查询
- 通过商品分类到商品分类表中查找对应的品牌
- 关联表 品牌表 商品表 商品分类表
- 商品分类表 item_cate 中有品牌表的id
- 整体思路 前台搜索框中点击事件根据关键字进行搜索的时候 通过复制域可以查询带有关键字的商品标题,商品品牌,商品分类的高亮数据 并通过solrTemplate的分组查询,根据商品分类域查询出商品分类,。通过根据商品分类查询出对应的品牌,显示商品分类 和品牌的数据供用户进行筛选,用户选择条件时则 ,当用户选择商品分类或者品牌时,根据solrTemplate的过滤查询查询出对应的结果
- 根据关键字查询以商品分类为分组的数据
- 使用 GroupOptions.addGroupByField("商品分类域名")即在qurey条件上加addGroupByField()
- SolrTemplate.queryForGroupPage()
- 以价格进行查询在前端有searchMap对象用于封装搜索条件
- 从首页跳转到搜索页 使用 #?
- 在搜索页进行接收 先在前端controller上加$location