查看文章 |
使用领域模型(domain object)来进行索引、搜索
2007/05/16 14:45
对于讲domain object 映射到关系型数据库中,hibernate等持久性框架做了很多的工作,使得业务逻辑只需要和hibernate等持久层进行交互,而不需要直接和具体的数据库进行交互。 这给程序员带来了很大的方便,在业务逻辑处理上,只要针对domain object就可以。 使用Lucene进行索引、搜索开发的的时候,最经常碰到的概念就是Document 和Field,在程序中一个不得不去做的事情,就是将领域对象的属性映射到document的field中去,在搜索的时候,还要根据document和field来构建DTOs(Data transfor object)来返回给web层。这点和EJB的一个缺点很类似,返回给web层的不能是实体Bean,而是对实体Bean进行封装了的DTO。 我们希望的是有类似POJO的技术带来的便利一样,持久化的是domain object,返回给web层的也是也是domain object。 我们在对domain object进行索引和搜索的时候,也希望能够直接在domain object的层面进行操作,而不是直接去和document和field打交道。而我们利用compass框架就可以做到这样。 Compass是使用了Lucene的搜索引擎框架,它提供了一套开源的、高性能的、可以灵活配置的搜索框架,可以为用户的应用程序提供搜索功能。它还能与Spring、Hibernate等已有的框架进行整合。 Comapss的API结构和hibernate非常的相似,如果使用过hibernate的程序员使用comapass,基本上对API就很得心应手。 我们来看一个例子 CompassConfiguration config = new CompassConfiguration().configure(); Compass compass = config.buildComapss(); CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); Book book = new Book(); book.setName("C++编程思想"); book.setAuthor(”Bruce Eckel“); session.save(book); tx.commit(); }catch(Exception e) { if(tx!=null) { tx.rollback(); } }finally { session.close(); } Hiberanete的程序员对上面的代码应该是非常的熟悉吧,compass完全让你远离了Lucene的API,让你的代码更专注与业务逻辑,而把索引和搜索的事情都交给compass吧。这点还带来了一个优点,就是利用compass很容易的给已有的系统增加搜索的功能。 那么如何让domain object被compass使用呢,当然和hibernate一样,只要完成一些domai object的配置文件就可以了,具体的可以阅读compass附带的example。 索引是简单了,那么搜索呢?? CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); CompassHits hits = session.find("Bruce Eckel"); tx.commit(); CompassHit hit = hits.hit(0); if(hit.getAlias().equals("book"); Book book = (Book) hit.getDate(); }catch(Exception e) { if(tx!=null) { tx.rollback(); } }finally { session.close(); } 这样就完成了搜索,只要使用session的find(String)方法,CompassHits是对lucene中的Hits的一个封装。find方法默认会在所有字段中进行该关键字的查找,如果你希望有自己的方式来查找,compass也提供了Lucene语法的查找,eg: session.find("keyword:key*"); 如果你对这些事务处理的代码比较反感的话,compass也提供了Template and Callback 这样就不需要担心session和transaction的处理了。 CompassConfiguration conf = new CompassConfiguration().configure().addClass(Author.class); Compass compass = conf.buildCompass(); CompassTemplate template = new CompassTemplate(compass); template.save(author); // open a session, transaction, and closes both Author a = (Author) template.execute(new CompassCallback() { public Object doInCompass(CompassSession session) { // all the actions here are within the same session // and transaction session.save(author); CompassHits hits = session.find("london"); ... return session.load(id); } }); 最后说的就是compass虽然很大的程度上借鉴了hibernate的一些设计思想,但是目前版本的compass还没有完成一些hibernate中比较有用的功能。 1、Compass不支持级联(Casscading) 因为同样是针对domain object的操作,支持级联(Cascading)是必须的,但是compass目前的版本是需要程序员对每个对象都来save的。 2、compass目前还不支持lazy loading 当用户搜索并得到一个对象的时候,所有和这个对象相关联的对象也会被同时加载到内存中。 呵呵,compass还有很多吸引人的地方,本文只是针对domain object编程来看待compass带来的便利。 |
最近读者: