`
lushuaiyin
  • 浏览: 674892 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

compass入门例子1

 
阅读更多
在新架构中打算选择Compass或Hibernate Search作为搜索引擎框架,比较后,感觉Hibernate Search上还是没有Compass成熟,另外考虑到后期对网页的爬取及搜索需求,决定还是基于Compass来作为架构缺省的搜索引擎。网上关于Compass的文档很多,但说得相对完整其详细的入门文档基本上没有,Compass的官方文档倒是说得很详细,但是例子一塌糊涂,存在很大问题。记录一下搭建的过程,作为入门的指南。

Compass 通过OSEM(Object/Search Engine Mapping)允许把应用对象的领域模型映射到搜索引擎,最终通过访问common meta data来达到访问对象的目的。

1、几个核心概念
1.1、annotation vs. xml配置文件

Compass的配置文件主要分成三类:

第一类:*.cmd.xml文件*

.cmd.xml文件是对common meta data进行定义,定义了最终搜索的结果中的最基本的元数据。

第二类:*.cpm.xml文件

*.cpm.xml是Object/Search Engine Mapping,提供了POJO到common meta data的映射。

第三类:*.cfg.xml文件

Compass的*.cfg.xml定义了Compass的Index存放路径、搜索引擎分词等相关信息。

与采用xml配置文件相比较,采用Annonation方式还是相对简单,尤其是采用Spring时候,不用写*.cmd.xml文件、*.cpm.xml、*.cfg.xml,相对很方便,而且不像Hibernate的Annonation很多,Compass的Annonation的核心标注只有@Searchable、@SearchableId、@SearchableProperty、@SearchableComponent个,很容易记忆。因此推荐使用Annonation方式

1.2、Compass核心API
Compass的核心API借鉴了Hibernate的术语,因此在操作上基本上与Hibernate类似,以下为Compass的几个核心接口:

CompassConfiguration(类似Hibernate Configuration):用来在一些设置参数、配置文件和映射定义上配置Compass。通常用来创建Compass接口。
Compass(类似Hibernate SessionFactory):为单线程使用,创建线程安全的实例来打开Compass Seesion。同样还提供了一些搜索引擎索引级别的操作。
CompassSesssion(类似Hibernate Session):用来执行像保存、删除、查找、装载这样的搜索操作。很轻量但是并不是线程安全的。
CompassTransaction(类似Hibernate Transaction):管理Compass事务的接口。使用它并不需要事务管理环境(像Spring、JTA)。

1.3、Compass与Spring集成

Compass已经对对spring集成做了很好的封装,同时与Spring对Hibernate的支持类似,Compass也提供了CompassTemplate来简化诸如对Session、Transaction、Exception等操作,尽量充分使用此工具,可以有效提高效率。例如:

CompassTemplate ct = (CompassTemplate) context.getBean("compassTemplate");

Article article = new Article();
article.setTitle("Compass Test");
article.setPublishDate(new Date());
article.setAuthor(1);

ct.save(article); //存储对象需要索引的数据到Compass的索引中。

2、软件环境
Spring :2.5

Compas:1.2.1

Hibernate:3.2.5

Mysql :5.0.5

3、数据库脚本
CREATE TABLE `article` (

`Id` int(11) NOT NULL auto_increment,

`title` varchar(40) NOT NULL default '',

`author` int(11) default '0',

`publish_date` date NOT NULL default '0000-00-00',

PRIMARY KEY (`Id`) ) TYPE=MyISAM;

CREATE TABLE `author` (

`Id` int(11) NOT NULL auto_increment,

`username` varchar(20) NOT NULL default '',

`password` varchar(20) NOT NULL default '',

`age` smallint(6) default '0',

PRIMARY KEY (`Id`) ) TYPE=MyISAM;
4、测试用例
从测试用例讲起比较容易把关系理清楚,不然一堆术语和概念很让人晕乎。

import org.apache.log4j.Logger;
import java.util.Date;

import junit.framework.TestCase;

import org.compass.core.Compass;
import org.compass.core.CompassDetachedHits;
import org.compass.core.CompassHit;
import org.compass.core.CompassHits;
import org.compass.core.CompassSession;
import org.compass.core.CompassTemplate;
import org.compass.core.CompassTransaction;
import org.compass.core.support.search.CompassSearchCommand;
import org.compass.core.support.search.CompassSearchResults;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mobilesoft.esales.dao.hibernate.ArticleDAO;
import com.mobilesoft.esales.dao.hibernate.AuthorDAO;
import com.mobilesoft.esales.model.Article;
import com.mobilesoft.esales.model.Author;
import com.mobilesoft.framework.search.service.CompassSearchService;

/**
* Compass服务使用的测试用例
*
* @author liangchuan@mobile-soft.cn
*
*/

public class TestCompass extends TestCase {

private static final Logger logger = Logger.getLogger(TestCompass.class);

private static ClassPathXmlApplicationContext context = null;
private static CompassTemplate ct;

static {
context = new ClassPathXmlApplicationContext(new String[] {
"applicationContext.xml", "applicationContext-resources.xml",
"applicationContext-dao.xml", "applicationContext-service.xml",
"applicationContext-compass.xml" });
ct = (CompassTemplate) context.getBean("compassTemplate");
}

protected void setUp() throws Exception {

}

/**
* 插入测试数据
*/
public void testInsert() {

ArticleDAO articleDao = (ArticleDAO) context.getBean("articleDAO");
AuthorDAO authorDao = (AuthorDAO) context.getBean("authorDAO");
Article article = new Article();
Author author = new Author();
author.setAge((short) 27);
author.setUsername("liangchuan");
author.setPassword("liangchuan");
article.setTitle("Compass Test");
article.setPublishDate(new Date());
article.setAuthor(1);
authorDao.save(author);
articleDao.save(article);
ct.save(article);
ct.save(author);
}

/**
* 用于测试使用CompassTransaction事务方式
*/
public void testTransactionalFind() {

Compass compass = ct.getCompass();
CompassSession session = compass.openSession();
CompassTransaction tx = null;
try {
tx = session.beginTransaction();
CompassHits hits = session.find("Compass*");

logger.error("testTransactionalFind() - CompassHits hits="
+ hits.getLength());
for (int i = 0; i < hits.getLength(); i++) {
Object hit = hits.data(i);
if (hit instanceof Article) {
Article item = (Article) hit;
logger.error("testTransactionalFind() - article hits="
+ item.getTitle());
} else if (hit instanceof Author) {
Author item = (Author) hit;
logger.error("testTransactionalFind() - author hits="
+ item.getUsername());
} else {
logger.error("testTransactionalFind() - error hits=");
}
}
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
} finally {
session.close();
}
}

/**
* 用于演示CompassDetachedHits的使用。
* 由于CompassTempalte得到的结果集必须在transactionalcontext中才能使用,
* 因此必须使用CompassDetachedHits方式测试CompassDetachedHits方式
*/
public void testDetachedFind() {

// 由于CompassTempalte得到的结果集必须在transactional
// context中才能使用,因此必须使用CompassDetachedHits方式
// 测试CompassDetachedHits方式
CompassDetachedHits hits = ct.findWithDetach("Compass*");

logger.error("testDetachedFind() - CompassHits hits="
+ hits.getLength());
for (int i = 0; i < hits.getLength(); i++) {
Object hit = hits.data(i);
if (hit instanceof Article) {
Article item = (Article) hit;
logger.error("testDetachedFind() - article hits="
+ item.getTitle());
} else if (hit instanceof Author) {
Author item = (Author) hit;
logger.error("testDetachedFind() - author hits="
+ item.getUsername());
} else {
logger.error("testDetachedFind() - error hits=");
}
}

}

/**
* 用于演示com.mobilesoft.framework.search.service.CompassSearchService的使用
*
*/
class CompassSearch extends CompassSearchService{
CompassSearch(){
Compass compass = ct.getCompass();
CompassSession session = compass.openSession();
CompassTransaction tx = null;

try {
tx = session.beginTransaction();
CompassSearchCommand command = new CompassSearchCommand();
command.setQuery("Compass");
CompassSearchResults results= performSearch(command,session);
logger.error("CompassSearch() - CompassHit TotalHits value=" +results.getTotalHits());

for (int i = 0; i < results.getHits().length; i++) {
CompassHit hits=results.getHits()[i];
Object hit=hits.getData();
logger.error("CompassSearch() - CompassHit hit=" + hit); //$NON-NLS-1$

if (hit instanceof Article) {
Article item = (Article) hit;
logger.error("testCompassSearchService() - article hits="
+ item.getTitle());
} else if (hit instanceof Author) {
Author item = (Author) hit;
logger.error("testCompassSearchService() - author hits="
+ item.getUsername());
} else {
logger.error("testCompassSearchService() - error hits=");
}

tx.commit();
}
} catch (Exception e) {
if (tx != null) {
tx.rollback();
}
} finally {
session.close();
}

}

}
public void testCompassSearchService() {
new CompassSearch();
}

protected void tearDown() throws Exception {
}
}

5、配置文件
applicationContext-compass.xml
<?xml version="1.0"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-lazy-init="true">
<bean id="compassTemplate" class="org.compass.core.CompassTemplate">
<property name="compass" ref="compass"/>
</bean>
<bean id="annotationConfiguration"
class="org.compass.annotations.config.CompassAnnotationsConfiguration">
</bean>
<bean id="compass" class="org.compass.spring.LocalCompassBean">
<property name="classMappings">
<list>
<value>com.mobilesoft.esales.model.Article</value>
<value>com.mobilesoft.esales.model.Author</value>
</list>
</property>
<property name="compassConfiguration" ref="annotationConfiguration"/>

<property name="compassSettings">
<props>
<prop key="compass.engine.connection"> file://compass </prop>
<prop key="compass.transaction.factory">
org.compass.spring.transaction.SpringSyncTransactionFactory
</prop>
<prop
key="compass.engine.highlighter.default.formatter.simple.pre">
<![CDATA[<font color="red"><b>]]>
</prop>
<prop
key="compass.engine.highlighter.default.formatter.simple.post">
<![CDATA[</b></font>]]>
</prop>
</props>
</property>

<property name="transactionManager" ref="transactionManager"/>
</bean>

<bean id="hibernateGpsDevice"
class="org.compass.gps.device.hibernate.HibernateGpsDevice">
<property name="name">
<value>hibernateDevice</value>
</property>
<property name="sessionFactory" ref="sessionFactory"/>
<property name="mirrorDataChanges">
<value>true</value>
</property>
</bean>
<bean id="compassGps" class="org.compass.gps.impl.SingleCompassGps"
init-method="start" destroy-method="stop">
<property name="compass" ref="compass"/>
<property name="gpsDevices">
<list>
<bean
class="org.compass.spring.device.SpringSyncTransactionGpsDeviceWrapper">
<property name="gpsDevice" ref="hibernateGpsDevice"/>
</bean>
</list>
</property>
</bean>
<bean id="compassSearchService" class="com.mobilesoft.framework.search.service.CompassSearchService">
<property name="compass" ref="compass"/>
<property name="pageSize" value="15"/>
</bean>

<!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 -->
<bean id="compassIndexBuilder" class="com.mobilesoft.framework.search.service.CompassIndexBuilder" lazy-init="false">
<property name="compassGps" ref="compassGps"/>
<property name="buildIndex" value="false"/>
<property name="lazyTime" value="10"/>
</bean>


</beans>
applicationContext-dao.xml、applicationContext-service.xml、applicationContext-resources.xml等略去。

6、Service层(参考了SpringSide实现)
AdvancedSearchCommand.java

package com.mobilesoft.framework.search.service;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.compass.core.CompassQuery.SortDirection;
import org.compass.core.CompassQuery.SortPropertyType;
import org.compass.core.support.search.CompassSearchCommand;

import org.springframework.util.Assert;

public class AdvancedSearchCommand extends CompassSearchCommand {

/**
* 封装基于Compass 的排序参数.
*/
class CompassSort {

private String name;

private SortPropertyType type;

private SortDirection direction;

public CompassSort() {
}

public CompassSort(String sortParamName, String paramType,
boolean isAscend) {
Assert.isTrue(StringUtils.isNotBlank(sortParamName));
setName(sortParamName);

if ("int".equalsIgnoreCase(paramType)) {
setType(SortPropertyType.INT);
} else if ("float".equalsIgnoreCase(paramType)) {
setType(SortPropertyType.FLOAT);
} else if ("string".equalsIgnoreCase(paramType)) {
setType(SortPropertyType.STRING);
} else {
setType(SortPropertyType.AUTO);
}

if (isAscend) {
setDirection(SortDirection.AUTO);
} else {
setDirection(SortDirection.REVERSE);
}
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public SortPropertyType getType() {
return type;
}

public void setType(SortPropertyType type) {
this.type = type;
}

public SortDirection getDirection() {
return direction;
}

public void setDirection(SortDirection direction) {
this.direction = direction;
}
}

/**
* 搜索结果排序表.
*/
private Set<CompassSort> sortMap = new HashSet<CompassSort>();

private String[] highlightFields;

/**
* @param paramType 现定义了三种类型: int string 以及 float。<br>
* 除去这三种外,其他会被自动定义为SortPropertyType.AUTO 具体的可见{@link org.compass.core.CompassQuery.SortPropertyType}
* @param isAscend 顺序还是倒序排序
* @see org.compass.core.CompassQuery.SortPropertyType#AUTO
* @see org.compass.core.CompassQuery.SortPropertyType#INT
* @see org.compass.core.CompassQuery.SortPropertyType#STRING
* @see org.compass.core.CompassQuery.SortPropertyType#FLOAT
* @see org.compass.core.CompassQuery.SortDirection#AUTO
* @see org.compass.core.CompassQuery.SortDirection#REVERSE
*/
public void addSort(String sortParamName, String paramType, boolean isAscend) {
this.sortMap.add(new CompassSort(sortParamName, paramType, isAscend));
}

public Set<CompassSort> getSortMap() {
return sortMap;
}

public void setSortMap(Set<CompassSort> sortMap) {
this.sortMap = sortMap;
}

public String[] getHighlightFields() {
return highlightFields;
}

public void setHighlightFields(String[] highlightFields) {
this.highlightFields = highlightFields;
}
}

CompassIndexBuilder.java

package com.mobilesoft.framework.search.service;

import org.apache.log4j.Logger;
import org.compass.gps.CompassGps;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

分享到:
评论

相关推荐

    compass 全文搜索

    基于lucene 的compass 全文搜索实例,可运行,对新手入门很有帮助

    SSH+compass 整合

    本资源是struts2 + spring2.5 + hibernate 3.2 + lucene 2.4 + compass 2.0整合实例,可以为初学入门者,提供个参考,本人也是网上找的,感觉很不错(因其中所用的jar文件太大,无法上传,大家可以自己添加各框架...

    自己动手写搜索引擎

    该书详细讲解了搜索引擎与信息检索基础,Lucene入门实例,Lucene索引的建立,使用Lucene进行搜索,排序,过滤和分页,Lucene的分析器,对Word、Excel和PDF格式文档的处理,Compass搜索引擎框架,Lucene分布式和...

    JAVA上百实例源码以及开源项目源代码

    1个目标文件,JNDI的使用例子,有源代码,可以下载参考,JNDI的使用,初始化Context,它是连接JNDI树的起始点,查找你要的对象,打印找到的对象,关闭Context…… ftp文件传输 2个目标文件,FTP的目标是:(1)提高...

    JAVA上百实例源码以及开源项目

    1个目标文件,JNDI的使用例子,有源代码,可以下载参考,JNDI的使用,初始化Context,它是连接JNDI树的起始点,查找你要的对象,打印找到的对象,关闭Context…… ftp文件传输 2个目标文件,FTP的目标是:(1)提高...

    leaflet-mapkey-icon:传单标记的新维度。 基于MapkeyIcons

    兼容Leaflet 0.6.0或更高版本例子入门使用leaflet-mapkey-icon插件非常容易和舒适。用法将文件从dist文件夹下载并放置到项目中的同一位置。 在HTML文档中链接javascript和样式文件: &lt; script src =" ...path-to...

    基于NVIDIA Jetson Nano的教育型AI机器人。-Python开发

    寻找快速入门的JetBot吗? 现在有许多第三方工具包! JetBot是一款基于NVIDIA Jetson Nano的开源机器人,价格合理-不到$ 150的Jetson Nano附加组件JetBot寻找快速上手的捷径吗? 现在有许多第三方工具包! JetBot是...

    安卓(Android)程序开发初级教程技术文档【视频+教程+源码】

    网上发行的一个资料很适合初学者,安卓经典Android开发入门教程,有实例,有android开发视频教程,还附带源码,欢迎各位下载一起学习! 教程(一) 平台简介  令人激动的Google手机操作系统平台-Android正式发布了,...

    java开源包1

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    Ext Js权威指南(.zip.001

    第1章 ext js 4开发入门 / 1 1.1 学习ext js必需的基础知识 / 1 1.2 json概述 / 3 1.2.1 认识json / 3 1.2.2 json的结构 / 3 1.2.3 json的例子 / 4 1.2.4 在javascript中使用json / 4 1.2.5 在.net中使用...

    popmednet:这是分布式数据网络平台PopMedNet的开源代码的存储库

    PopMedNet:trade_mark: PopMedNet:trade_mark:是一个开放源代码应用程序,用于促进多站点健康数据... 入门数据库位于此处: : 请注意,PMN-Starter-2020.5.bak文件是最新备份。 请通过与我们联系,以报告任何问题。

    java开源包2

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包3

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包6

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包5

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包10

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包8

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包7

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

    java开源包9

    开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的缩写,它绝不是简单的另外一种模板引擎,而是新一代的模板引擎,...

Global site tag (gtag.js) - Google Analytics