①Spring Data Solr简介
虽然支持任何编程语言的能力具有很大的市场价值,你可能感兴趣的问题是:我如何将Solr的应用集成到Spring中?可以,Spring Data Solr就是为了方便Solr的开发所研制的一个框架,其底层是对SolrJ(官方API)的封装。
②使用
导入maven依赖
org.springframework.data
spring-data-solr
1.5.5.RELEASE
添加配置文件
对实体进行@Field注解
publicclassTbItemimplements Serializable{
@Field
private Long id;
@Field("item_title")
private String title;
通过Spring Data Solr实现增删查改
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext-solr.xml")
publicclass TestTemplate {
@Autowired
private SolrTemplate solrTemplate;
-----------添加-----------
@Test
publicvoid testAdd(){
TbItem item=new TbItem();
item.setId(1L);
item.setBrand("华为");
item.setCategory("手机");
item.setGoodsId(1L);
item.setSeller("华为2号专卖店");
item.setTitle("华为Mate9");
item.setPrice(new BigDecimal(2000));
solrTemplate.saveBean(item);
solrTemplate.commit();
}
-----------查询-----------
@Test
publicvoid testFindOne(){
TbItem item = solrTemplate.getById(1, TbItem.class);
System.out.println(item.getTitle());
}
-----------删除-----------
@Test
publicvoid testDelete(){
solrTemplate.deleteById("1");
solrTemplate.commit();
}
-----------分页添加数据-----------
@Test
publicvoid testAddList(){
Listlist=new ArrayList();
for(inti=0;i<100;i++){
TbItem item=new TbItem();
item.setId(i+1L);
item.setBrand("华为");
item.setCategory("手机");
item.setGoodsId(1L);
item.setSeller("华为2号专卖店");
item.setTitle("华为Mate"+i);
item.setPrice(new BigDecimal(2000+i));
list.add(item);
}
solrTemplate.saveBeans(list);
solrTemplate.commit();
}
-----------分页查询-----------
@Test
publicvoidtestPageQuery(){
Query query=new SimpleQuery("*:*");
query.setOffset(20);//开始索引(默认0)
query.setRows(20);//每页记录数(默认10)
ScoredPagepage = solrTemplate.queryForPage(query, TbItem.class);
System.out.println("总记录数:"+page.getTotalElements());
Listlist = page.getContent();
showList(list);//show code ignore
}
-----------条件查询-----------
@Test
publicvoid testPageQueryMutil(){
Query query=new SimpleQuery("*:*");
Criteria criteria=new Criteria("item_title").contains("2");
criteria=criteria.and("item_title").contains("5");
query.addCriteria(criteria);
//query.setOffset(20);//开始索引(默认0)
//query.setRows(20);//每页记录数(默认10)
ScoredPage page = solrTemplate.queryForPage(query, TbItem.class);
System.out.println("总记录数:"+page.getTotalElements());
Listlist = page.getContent();
showList(list);
}
-----------删除全部-----------
@Test
publicvoidtestDeleteAll(){
Query query=new SimpleQuery("*:*");
solrTemplate.delete(query);
solrTemplate.commit();
}
}
批量导入数据
注:这里导入的时候使用了动态域
@Dynamic
@Field("item_spec_*")
private Map
@Component
public class SolrUtil {
@Autowired
private TbItemMapper itemMapper;
@Autowired
private SolrTemplate solrTemplate;
public void importItemData(){
TbItemExample example=new TbItemExample();
Criteria criteria = example.createCriteria();
criteria.andStatusEqualTo("1");//审核通过的才导入的
List itemList = itemMapper.selectByExample(example);
System.out.println("---商品列表---");
int count=0;
for(TbItem item:itemList){
System.out.println(item.getId()+" "+ item.getTitle()+ " "+item.getPrice()+(++count));
Map specMap = JSON.parseObject(item.getSpec(), Map.class);//从数据库中提取规格json字符串转换为map
item.setSpecMap(specMap);
}
solrTemplate.saveBeans(itemList);
solrTemplate.commit();
System.out.println("---结束---");
}
public void execute(){
ApplicationContext context=new ClassPathXmlApplicationContext("classpath*:spring/applicationContext*.xml");
SolrUtil solrUtil= (SolrUtil) context.getBean("solrUtil");
solrUtil.importItemData();
}
}
关键字查询
@Service(timeout=3000)
publicclass ItemSearchServiceImpl implements ItemSearchService{
@Autowired
private SolrTemplate solrTemplate;
@Override
public Map search(MapsearchMap) {
Mapmap=new HashMap<>();
Query query=new SimpleQuery();
//添加查询条件
Criteria criteria=new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
ScoredPagepage = solrTemplate.queryForPage(query, TbItem.class);
map.put("rows", page.getContent());
returnmap;
}
}
关键字高亮显示
/**
* 根据关键字搜索列表
* @param keywords
* @return
*/
privateMap searchList(MapsearchMap){
Mapmap=newHashMap();
HighlightQuery query=new SimpleHighlightQuery();
HighlightOptions highlightOptions=new HighlightOptions().addField("item_title");//设置高亮的域
highlightOptions.setSimplePrefix("");//高亮前缀
highlightOptions.setSimplePostfix("");//高亮后缀
query.setHighlightOptions(highlightOptions);//设置高亮选项
//按照关键字查询
Criteria criteria=new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
HighlightPagepage = solrTemplate.queryForHighlightPage(query, TbItem.class);
for(HighlightEntryh: 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());
returnmap;
}
注:我们测试后发现高亮显示的html代码原样输出,这是angularJS为了防止html攻击采取的安全机制。我们如何在页面上显示html的结果呢?我们会用到$sce服务的trustAsHtml方法来实现转换。
// 定义模块: var app = angular.module("pinyougou",[]); /*$sce服务写成过滤器*/ app.filter('trustHtml',['$sce',function($sce){ return function(data){ return $sce.trustAsHtml(data); } }]); |
2.使用过滤器
ng-bind-html指令用于显示html内容
竖线 |用于调用过滤器
<divclass="attr"ng-bind-html="item.title | trustHtml">div> |
分组查询:返回一个List
/**
* 查询分类列表
* @param searchMap
* @return
*/
import org.springframework.data.domain.Page;
privateList searchCategoryList(MapsearchMap){
Listlist=new ArrayList();
Query query=new SimpleQuery();
//按照关键字查询
Criteria criteria=new Criteria("item_keywords").is(searchMap.get("keywords"));
query.addCriteria(criteria);
//设置分组选项
GroupOptions groupOptions=new GroupOptions().addGroupByField("item_category");
query.setGroupOptions(groupOptions);
//得到分组页
GroupPagepage = solrTemplate.queryForGroupPage(query, TbItem.class);
//根据列得到分组结果集
GroupResultgroupResult = page.getGroupResult("item_category");
//得到分组结果入口页
Page>groupEntries = groupResult.getGroupEntries();
//得到分组入口集合
List>content = groupEntries.getContent();
for(GroupEntryentry:content){
list.add(entry.getGroupValue());//将分组结果的名称封装到返回值中
}
return list;
}
过滤查询
/**
* 根据关键字搜索列表
* @param keywords
* @return
*/
privateMap searchList(Map searchMap){
.......
//1.1关键字查询......
//1.2按分类筛选
if(!"".equals(searchMap.get("category"))){
Criteria filterCriteria=new Criteria("item_category").is(searchMap.get("category"));
FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
query.addFilterQuery(filterQuery);
}
//高亮显示处理.....
}
价格区间过滤
/**
* 根据关键字搜索列表
* @param keywords
* @return
*/
privateMap searchList(Map searchMap){
......
//1.1关键字查询.....
//1.2按分类筛选.....
//1.3按品牌筛选.....
//1.4过滤规格 ......
//1.5按价格筛选.....
if(!"".equals(searchMap.get("price"))){
String[] price = ((String) searchMap.get("price")).split("-");
if(!price[0].equals("0")){//如果区间起点不等于0
Criteria filterCriteria=new Criteria("item_price").greaterThanEqual(price[0]);
FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
query.addFilterQuery(filterQuery);
}
if(!price[1].equals("*")){//如果区间终点不等于*
Criteria filterCriteria=new Criteria("item_price").lessThanEqual(price[1]);
FilterQuery filterQuery=new SimpleFilterQuery(filterCriteria);
query.addFilterQuery(filterQuery);
}
}
//高亮显示处理 .....
}
分页查询
/**
* 根据关键字搜索列表
* @param keywords
* @return
*/
privateMap searchList(MapsearchMap){
.....
//1.1关键字查询
.....
//1.2按分类筛选
.....
//1.3按品牌筛选
.....
//1.4过滤规格
.....
//1.5按价格筛选
......
//1.6 分页查询
Integer pageNo= (Integer) searchMap.get("pageNo");//提取页码
if(pageNo==null){
pageNo=1;//默认第一页
}
Integer pageSize=(Integer) searchMap.get("pageSize");//每页记录数
if(pageSize==null){
pageSize=20;//默认20
}
query.setOffset((pageNo-1)*pageSize);//从第几条记录查询
query.setRows(pageSize);
//高亮显示处理
......
Map map=new HashMap<>();
map.put("rows", page.getContent());
map.put("totalPages", page.getTotalPages());//返回总页数
map.put("total", page.getTotalElements());//返回总记录数
return map;
}
排序
/**
* 根据关键字搜索列表
* @param keywords
* @return
*/
privateMap searchList(Map searchMap){
........
//1.7排序
String sortValue= (String) searchMap.get("sort");//ASC DESC
String sortField= (String) searchMap.get("sortField");//排序字段
if(sortValue!=null&& !sortValue.equals("")){
if(sortValue.equals("ASC")){
Sort sort=new Sort(Sort.Direction.ASC, "item_"+sortField);
query.addSort(sort);
}
if(sortValue.equals("DESC")){
Sort sort=new Sort(Sort.Direction.DESC, "item_"+sortField);
query.addSort(sort);
}
}
//高亮显示处理
......
return map;
}
SpringDataSolr连接SolrCloud
在SolrJ中提供一个叫做CloudSolrServer的类,它是SolrServer的子类,用于连接solrCloud
它的构造参数就是zookeeper的地址列表,另外它要求要指定defaultCollection属性(默认的 collection名称)
我们现在修改springDataSolrDemo工程的配置文件 ,把原来的solr-server注销,替换为CloudSolrServer .指定构造参数为地址列表,设置默认 collection名称