产品搜索有两种可供选择的解决方案:1>数据库索引 2>全文索引查询(lucene)
这里使用的是基于lucene的全文索引compass(面向对象)查询,全文索引查询支持复杂的查询语句,lucene对数据进行关键字的索引,索引性能也比数据库索引高,全文索引查询还有一个好处就是它可以将查询匹配度高的记录排在前面
1. 建立索引
① 定义映射元数据[xml/注解]
在商品信息实体Bean中,使用注解@Searchable定义ProductInfo跟lucene中的document进行映射,如果@Searchable的root值为false,则表示这个类不是一个单独的搜索类(不是主体);@SearchableId定义搜索实体bean的标示属性(必须);@SearchableProperty默认跟lucene中document中的field进行映射,可以指定field的name,boost设置搜索的优先级(权重值高的排在最前面,默认为1);对于复合类型使用注解@SearchableComponent进行标注;@SearchableReference标注所引用的类是主体类
② 添加索引
Compass能够方便地实现增量索引,lucene实现增量索引比较难,使用lucene常应用于把索引文件删除,重新生成索引,这样索引更新时就会导致用户访问不了,实时性不强。
Compass添加索引:
1) 获取Compass对象(类似于Hibernate的SessionFactory)
Compass compass = new CompassAnnotationsConfiguration()
.setSetting(CompassEnvironment.CONNECTION, "file://indexfile")
//.setSetting(CompassEnvironment.CONNECTION, "ram://index")//内存
.setSetting("compass.engine.highlighter.default.formatter.simple.pre","<font color='red'>")
.setSetting("compass.engine.highlighter.default.formatter.simple.post","</font>")
.addScan("cn.itcast.bean").buildCompass();
2) 增加/删除/更新索引(原始Compass的API)
CompassSession session = compass.openSession();
CompassTransaction tx = session.beginTransaction();
Product p1 = new Product(12,"c瑜珈球","非常好的瑜珈球",15f, "www");
session.create(p1);
//session.delete(p1); //删除索引
Product p3 = new Product(8,"a蓝球","蓝球小子",125f, "ppp");
session.create(p3);
//session.delete(p3);
//session.save(p3); //更新索引
tx.commit();
注:Compass里面有一个名为SingleCompassGps的类可以自动完成添加/更新/删除操作,使用时只需要在Spring配置文件中做相应的配置就可以了;为了保证Compass的事务和JPA/Hibernate的事务是同一个,我们需要将Compass的事务交由Spring来管理
3) 查询索引
① 用@Resource注解将Compass对象传入ProductSearchBean中,new一个CompassTemplate对象出来,调用其execute方法获取查询数据(传入Callback回调函数)
② Callback回调函数实现CompassCallback接口,重写doInCompass方法获得查询结果QueryResult<ProductInfo>
CompassHits hits = session.find(key);
QueryResult<ProductInfo> qr = new QueryResult<ProductInfo>();
qr.setTotalrecord(hits.length());//得到匹配记录的总数 1
int length = firstResult+ maxResult;
if(length>hits.length()) length = hits.length();
List<ProductInfo> products = new ArrayList<ProductInfo>();
for(int i=firstResult; i<length; i++){
ProductInfo product = (ProductInfo)hits.data(i);
if(hits.highlighter(i).fragment("productName")!=null){//处理高亮显示
product.setName(hits.highlighter(i).fragment("productName"));
}
if(hits.highlighter(i).fragment("description")!=null){//处理高亮显示
product.setDescription(hits.highlighter(i).fragment("description"));
}
products.add(product);
}
qr.setResultlist(products);
return qr;
总结一下今天使用Compass完成搜索的步骤:
1. 建立映射元数据
2. 把compass集成到spring中,并且配置GPS自动完成索引的建立及更新
3. 查询索引