开始之前本文是Compass的入门指引,通过实例介绍了Compass与iBatis、Spring的整合,适合不了解Compass的读者,但要求读者了解Lucene、Spring和iBatis,写过一些简单的应用。
什么是CompassCompass是一个Java搜索框架。它封装了Lucene,增加了一些Lucene不支持的特性(例如实时更新索引),支持各种数据(Java对象、xml、json)到索引的映射,支持各种数据源(JDBC, Hibernate, iBatis)。
图解(看得烦的直接跳过看下面的例子吧):
与Spring、iBatis的整合建索引1、假设Spring + iBatis的框架已经搭建好。 @Searchable(alias="user") public class User { @SearchableId private int id; @SearchableProperty(index=Index.ANALYZED, store=Store.YES) private String name; // 姓名 @SearchableProperty(index=Index.NOT_ANALYZED, store=Store.YES) private String gender; // 性别 @SearchableProperty(index=Index.NOT_ANALYZED, store=Store.YES) private int age; // 年龄 public User() { } public User(String name, String gender, int age) { setName(name); setGender(gender); setAge(age); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
其实就是加几个Annotation而已。看到Index.ANALYZED、Store.YES这些东西,用过Lucene的应该大概都明白了吧。
3、建立LocalCompassBean,配置索引文件存放路径和进行映射的domain。 <bean id="compass" class="org.compass.spring.LocalCompassBean"> <property name="compassSettings"> <props> <!-- 索引文件保存路径 --> <prop key="compass.engine.connection">/home/index/compasstest</prop> </props> </property> <property name="classMappings"> <!-- 进行映射的domain --> <list> <value>ren.domain.User</value> <value>ren.domain.Book</value> </list> </property> </bean>
4、建立SqlMapClientGpsDevice,配置iBatis的sqlMapClient和获取数据进行索引的SQL语句id。 <bean id="ibatisGpsDevice" class="org.compass.gps.device.ibatis.SqlMapClientGpsDevice"> <property name="name" value="ibatis" /> <property name="sqlMapClient"> <ref bean="sqlMapClient" /> <!-- 引用项目中已经定义的ibatis的sqlMapClient --> </property> <property name="selectStatementsIds"> <!-- 对这些SQL查询的结果进行索引 --> <list> <value>user.getAllUsers</value> <value>book.getAllBooks</value> </list> </property> </bean>
5、建立CompassGps(SingleCompassGps或DualCompassGps),引用前面的compass和device。 <bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps" init-method="start" destroy-method="stop"> <property name="compass" ref="compass" /> <property name="gpsDevices"> <list> <ref local="ibatisGpsDevice"/> </list> </property> </bean>
@Component @Qualifier("indexBuilder") public class IndexBuilder { @Autowired @Qualifier("compassGps") private CompassGps compassGps; public void buildIndex() { compassGps.index(); // 一行代码搞定 } }
查索引1、建立CompassTemplate,引用LocalCompassBean。 <bean id="compassTemplate" class="org.compass.core.CompassTemplate"> <property name="compass"> <ref bean="compass" /> </property> </bean>
2、使用CompassTemplate.execute(CompassCallback<T>)进行查询。 @Component @Qualifier("indexSearcher") public class IndexSearcher { @Autowired @Qualifier("compassTemplate") private CompassTemplate compassTemplate; /** * 搜索用户 */ public List<User> searchUser(final String name, final String gender, final int age) { return compassTemplate.execute(new CompassCallback<List<User>>() { public List<User> doInCompass(CompassSession session) throws CompassException { CompassQueryBuilder builder = session.queryBuilder(); String queryString = ""; if (!StringUtils.isBlank(name)) { queryString += "and user.name:" + name; } if (!StringUtils.isBlank(gender)) { queryString += "and user.gender:" + gender; } if (age > 0) { queryString += "and user.age:" + age; } CompassQuery query = builder.queryString(queryString).toQuery(); query.addSort("user.age", SortPropertyType.INT, SortDirection.REVERSE); CompassHits hits = query.hits(); List<User> list = new ArrayList<User>(); for (CompassHit hit : hits) { list.add((User)hit.data()); } return list; } }); } }
拼查询字符串这里写得比较累赘,小朋友不要学~
与Lucene的比较1、Compass有比Lucene更易用的API(废话,封装了Lucene嘛),例如支持直接更新记录(因为resource类似数据库记录,含有主键)。像上面的建索引过程,如果用Lucene,肯定得写很多Java代码。 Compass比Lucene慢了大约25%,当然这个测试十分粗略,结果仅供参考。
经验总结1、对多个表建索引后进行搜索,在添加排序条件时,如果不指定SortPropertyType,那么在没有指定converter的字段上排序时会抛Exception:
2、最好自己封装排序字段和分页。
3、总结,Compass比较适用于逻辑不太复杂的应用,会比Lucene少写很多代码。但如果需要一些较为特殊的需求,或者对效率要求比较高,还是用Lucene吧。
相关资源Compass入门指南:http://www./2008/03/23/compass-%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/
全文检索的基本原理:http://blog.csdn.net/forfuture1978/archive/2009/10/22/4711308.aspx
大型网站的Lucene应用:http://www./blog/archives/605.html
写在后面这篇文章是根据自己的一次演讲整理出来的,主要就是PPT内容 + 代码。演讲和写文章确实很不同,感觉很多地方还说不清楚,因为内容太多了吧,看来自己的书面组织能力还有待提高啊~ |
|
来自: 浮石 > 《ReadList》