- 浏览: 209911 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
wuMing2014:
楼主,在ExtendServlet类中的Ioc ioc = n ...
freemarker 自定义标签 -
washingtonDC:
非常精彩!运行时异常(即非受控异常)自动强制执行整个逻辑工作单 ...
Spring事务的传播行为 @Transactional -
tom31203120:
freemarker 自定义标签 -
osacar:
tom31203120 写道oscar 不是 osacar还真 ...
freemarker 自定义标签 -
tom31203120:
oscar 不是 osacar
freemarker 自定义标签
前段时间已经写了一篇关于compass的文章,相信大家对compass也已经有了一定的了解
由于最近做的项目中涉及到了站内搜索,而且是基于JPA注解形式的,在网上找了好久,关于JPA集成compass的例子很少,有些也是基于 xml的,基于注解形式的甚是少,没有办法只有去compass的官网下载英文文档自己研究一下,花费了一下午时间调试出来,集成到项目中!
在这里给大家分享下,希望大家可以少走些弯路!
1.去官方网站下载compass的jar包,我用的的2.1版本
http://www.compass-project.org/
ProductInfo.java
ProductType.java
ProductStyle.java
这里要特别注意有集合类型要搜索或显示的时候,两边定义的@SearchableReference或 @SearchableComponent必须一致
2.再spring的配置文件中加入以下代码
3.自动建立索引的java bean
4.建立索引Service 层代码
控制层
junit测试
由于最近做的项目中涉及到了站内搜索,而且是基于JPA注解形式的,在网上找了好久,关于JPA集成compass的例子很少,有些也是基于 xml的,基于注解形式的甚是少,没有办法只有去compass的官网下载英文文档自己研究一下,花费了一下午时间调试出来,集成到项目中!
在这里给大家分享下,希望大家可以少走些弯路!
1.去官方网站下载compass的jar包,我用的的2.1版本
http://www.compass-project.org/
ProductInfo.java
@Entity @Searchable public class ProductInfo implements Serializable{ private static final long serialVersionUID = -8860864584425256200L; private Integer id; /** 货号 **/ private String code; /** 产品名称 **/ private String name; /** 产品类型 **/ private ProductType type; /** 产品样式 **/ private Set<ProductStyle> styles = new HashSet<ProductStyle>(); public ProductInfo() {} @OneToMany(cascade={CascadeType.REMOVE,CascadeType.PERSIST}, mappedBy="product",fetch=FetchType.EAGER) @OrderBy("visible desc, id asc") @SearchableReference public Set<ProductStyle> getStyles() { return styles; } public void setStyles(Set<ProductStyle> styles) { this.styles = styles; } @Id @GeneratedValue @SearchableId public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=30) @SearchableProperty(index = Index.TOKENIZED, store = Store.YES) public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Column(length=50,nullable=false) @SearchableProperty(index = Index.TOKENIZED, store = Store.YES) public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToOne(cascade=CascadeType.REFRESH,optional=false) @JoinColumn(name="typeid") @SearchableReference public ProductType getType() { return type; } public void setType(ProductType type) { this.type = type; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final ProductInfo other = (ProductInfo) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
ProductType.java
@Entity @Searchable public class ProductType implements Serializable{ private static final long serialVersionUID = 8106351120886053881L; /** 类别id **/ private Integer typeid; /** 类别名称 **/ private String name; /** 子类别 **/ private Set<ProductType> childtypes = new HashSet<ProductType>(); /** 所属父类 **/ private ProductType parent; private Set<ProductInfo> products = new HashSet<ProductInfo>(); @OneToMany(mappedBy="type", cascade=CascadeType.REMOVE) @SearchableReference public Set<ProductInfo> getProducts() { return products; } public void setProducts(Set<ProductInfo> products) { this.products = products; } public ProductType() {} @ManyToOne(cascade=CascadeType.REFRESH) @JoinColumn(name="parentid") public ProductType getParent() { return parent; } public void setParent(ProductType parent) { this.parent = parent; } @OneToMany(cascade={CascadeType.REFRESH,CascadeType.REMOVE},mappedBy="parent") public Set<ProductType> getChildtypes() { return childtypes; } public void setChildtypes(Set<ProductType> childtypes) { this.childtypes = childtypes; } @Column(length=36,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Id @GeneratedValue(strategy=GenerationType.AUTO) @SearchableId public Integer getTypeid() { return typeid; } public void setTypeid(Integer typeid) { this.typeid = typeid; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((typeid == null) ? 0 : typeid.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final ProductType other = (ProductType) obj; if (typeid == null) { if (other.typeid != null) return false; } else if (!typeid.equals(other.typeid)) return false; return true; } }
ProductStyle.java
@Entity @Searchable public class ProductStyle implements Serializable{ private static final long serialVersionUID = -4926119953511144279L; private Integer id; /** 样式的名称 **/ private String name; /** 图片 **/ private String imagename; private String image140FullPath; /** 是否可见 **/ private Boolean visible = true; private ProductInfo product; public ProductStyle() {} public ProductStyle(Integer id) { this.id = id; } public ProductStyle(String name, String imagename) { this.name = name; this.imagename = imagename; } @ManyToOne(cascade=CascadeType.REFRESH,optional=false) @JoinColumn(name="productid") @SearchableReference public ProductInfo getProduct() { return product; } public void setProduct(ProductInfo product) { this.product = product; } @Id @GeneratedValue @SearchableId public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=30,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(length=40,nullable=false) @SearchableProperty(index = Index.UN_TOKENIZED, store = Store.YES) public String getImagename() { return imagename; } public void setImagename(String imagename) { this.imagename = imagename; } @Column(nullable=false) public Boolean getVisible() { return visible; } public void setVisible(Boolean visible) { this.visible = visible; } @Transient public String getImageFullPath(){ return "/images/product/"+ this.getProduct().getType().getTypeid()+ "/"+ this.getProduct().getId()+ "/prototype/"+ this.imagename; } @Transient public String getImage140FullPath(){ image140FullPath = "/images/product/"+ this.getProduct().getType().getTypeid()+ "/"+ this.getProduct().getId()+ "/140x/"+ this.imagename; return image140FullPath; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final ProductStyle other = (ProductStyle) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }
这里要特别注意有集合类型要搜索或显示的时候,两边定义的@SearchableReference或 @SearchableComponent必须一致
2.再spring的配置文件中加入以下代码
<bean id="annotationConfiguration" class="org.compass.annotations.config.CompassAnnotationsConfiguration"> </bean> <!-- compass Bean --> <bean id="compass" class="org.compass.spring.LocalCompassBean"> <property name="compassConfiguration" ref="annotationConfiguration" /> <property name="transactionManager" ref="txManager" /> <property name="compassSettings"> <props> <!-- 定义索引的存储位置 --> <prop key="compass.engine.connection">d:/compass</prop> <prop key="compass.transaction.factory"> org.compass.spring.transaction.SpringSyncTransactionFactory </prop> <!-- 定义分词器--> <prop key="compass.engine.analyzer.MMAnalyzer.CustomAnalyzer"> org.mira.lucene.analysis.IK_CAnalyzer </prop> </props> </property> <property name="resourceDirectoryLocations"> <list> <value>classpath:net/shopin/bean/product</value> </list> </property> </bean> <bean id="jpaGpsDevice" class="org.compass.gps.device.jpa.JpaGpsDevice"> <property name="name"> <value>JpaGpsDevice</value> </property> <property name="entityManagerFactory" ref="entityManagerFactory" /> <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="jpaGpsDevice" /> </bean> </list> </property> </bean> <bean id="compassTemplate" class="org.compass.core.CompassTemplate"> <property name="compass" ref="compass" /> </bean> <!-- 定时重建索引(利用quartz)或随Spring ApplicationContext启动而重建索引 --> <bean id="compassIndexBuilder" class="net.shopin.service.search.impl.CompassIndexBuilder" lazy-init="false"> <property name="compassGps" ref="compassGps" /> <property name="buildIndex" value="true" /> <property name="lazyTime" value="5" /> </bean>
3.自动建立索引的java bean
/** * 通过quartz定时调度定时重建索引或自动随Spring ApplicationContext启动而重建索引的Builder. * 会启动后延时数秒新开线程调用compassGps.index()函数. * 默认会在Web应用每次启动时重建索引,可以设置buildIndex属性为false来禁止此功能. * 也可以不用本Builder, 编写手动调用compassGps.index()的代码. * */ public class CompassIndexBuilder implements InitializingBean { // 是否需要建立索引,可被设置为false使本Builder失效. private boolean buildIndex = false; // 索引操作线程延时启动的时间,单位为秒 private int lazyTime = 10; // Compass封装 private CompassGps compassGps; // 索引线程 private Thread indexThread = new Thread() { @Override public void run() { try { Thread.sleep(lazyTime * 1000); System.out.println("begin compass index..."); long beginTime = System.currentTimeMillis(); // 重建索引. // 如果compass实体中定义的索引文件已存在,索引过程中会建立临时索引, // 索引完成后再进行覆盖. compassGps.index(); long costTime = System.currentTimeMillis() - beginTime; System.out.println("compss index finished."); System.out.println("costed " + costTime + " milliseconds"); } catch (InterruptedException e) { e.printStackTrace(); } } }; /** * 实现<code>InitializingBean</code>接口,在完成注入后调用启动索引线程. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { if (buildIndex) { indexThread.setDaemon(true); indexThread.setName("Compass Indexer"); indexThread.start(); } } public void setBuildIndex(boolean buildIndex) { this.buildIndex = buildIndex; } public void setLazyTime(int lazyTime) { this.lazyTime = lazyTime; } public void setCompassGps(CompassGps compassGps) { this.compassGps = compassGps; } }
4.建立索引Service 层代码
@Service @Transactional public class SearchServiceBean extends DaoSupport implements SearchService { @Resource(name = "compass") Compass compass; /** 创建索引 **/ public void index(ProductInfo p) { CompassSession session = compass.openSession(); CompassTransaction tx = null; try { tx = session.beginTransaction(); session.create(p); tx.commit(); } catch (Exception e) { if (tx != null) { tx.commit(); } throw new RuntimeException(e); } finally { if (session != null) { session.close(); } } } /** 删除一条索引 **/ public void delete(ProductInfo p) { CompassTemplate ct = new CompassTemplate(compass); ct.delete(p); } /** 更新(重新创建)一条索引 **/ public void update(final ProductInfo p) { CompassTemplate ct = new CompassTemplate(compass); CompassCallback<Object> action = new CompassCallback<Object>() { public Object doInCompass(CompassSession session) throws CompassException { session.delete(p); session.create(p); return null; } }; ct.execute(action); } /** 索引查询 **/ public List<ProductInfo> find(final String keywords) { CompassTemplate ct = new CompassTemplate(compass); return ct.execute(new CompassCallback<List<ProductInfo>>() { public List<ProductInfo> doInCompass(CompassSession session) throws CompassException { List<ProductInfo> result = new ArrayList<ProductInfo>(); CompassQueryBuilder queryBuilder = session.queryBuilder(); CompassHits hits = null; // session.find(query); /** 在所有字段中查询 **/ CompassQuery allPropertyQuery = queryBuilder.queryString(keywords).toQuery(); hits = allPropertyQuery.hits(); /** 在指定字段中查询 **/ // CompassQuery query = queryBuilder.term("name", keywords); // hits = query.hits(); /** 指定范围查询 **/ // CompassQuery dateRangeQuery = // queryBuilder.between("postTime",startTime, endTime, true); // hits = queryBuilder.bool() // .addMust(allPropertyQuery) // .addMust(dateRangeQuery) // .toQuery() // .hits(); // System.out.println("---------"); for (int i = 0; i < hits.length(); i++) { ProductInfo p = (ProductInfo) hits.data(i); /** 如果进行高亮的属性中没有出现关键字, 则返回null **/ // String ht = hits.highlighter(i).fragment("name"); // if (ht != null) { // p.setName(ht); // } // String hc = hits.highlighter(i).fragment("code"); // if (hc != null) { // p.setCode(hc); // } result.add(p); } return result; } }); }
控制层
@Controller("/search/gosearch") public class SearchAction extends Action { @Resource(name = "searchServiceBean") private SearchService SearchService; @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String keywords=request.getParameter("word").trim(); if(keywords==null||"".equals(keywords)){ return mapping.findForward("noproduct"); } System.out.println("------"+keywords); List<ProductInfo> list = SearchService.find(keywords); request.setAttribute("word", keywords); request.setAttribute("product",list); if(list.isEmpty()){ return mapping.findForward("noproduct"); }else{ return mapping.findForward("list"); } } }
junit测试
public class SearchTest { private static AbstractApplicationContext context; @BeforeClass public static void setUpBeforeClass() throws Exception { try { context = new ClassPathXmlApplicationContext("beans.xml"); } catch (Exception e) { e.printStackTrace(); } } @Test public void testDelete() { SearchService searchService = (SearchService) context .getBean("searchServiceBean"); ProductInfo p = new ProductInfo(2); searchService.delete(p); } @Test public void createIndex(){ SearchService searchService = (SearchService) context .getBean("searchServiceBean"); ProductInfoService productInfoService = (ProductInfoService) context .getBean("productInfoServiceBean"); List<ProductInfo> list=productInfoService.getAllProduct(); for(ProductInfo productInfo:list){ // System.out.println("-------"+productInfo.getName()); searchService.index(productInfo); } } @Test public void testSearch() { SearchService searchService = (SearchService) context .getBean("searchServiceBean"); String query = "手机"; List<ProductInfo> ProductInfos; ProductInfos = searchService.find(query); for (ProductInfo p : ProductInfos) { System.out.println(p.getName()); } System.out.println("------------"); } }
发表评论
-
Compass将lucene、Spring、Hibernate三者结合
2011-05-20 01:31 42841.概述 Compass将lucene、Spring、Hib ... -
compass 使用详解
2011-05-20 01:21 6542我们在使用lucene管理document时,难免有些复杂,并 ... -
用compass快速给你的网站添加搜索功能<二>
2011-05-20 00:51 1285在上一篇文章中主要 ... -
用compass快速给你的网站添加搜索功能<一>
2011-05-20 00:48 1183如果你的网站架构采用的是spring+hibernate。用现 ... -
compass 分页查询
2011-05-20 00:43 1491有了配置文件之后,我们就可以写出相应的增删改查了 public ... -
Spring Compass (Lucene) 全文本搜索排序问题
2011-05-19 23:57 2340import org.compass.core.Com ...
相关推荐
ssh+compass实现站内搜索分页.rar
compass:我们走吧
NULL 博文链接:https://topmanopensource.iteye.com/blog/484303
NULL 博文链接:https://aa00aa00.iteye.com/blog/1030043
maptalks.control.compass maptalks罗盘控件。 例子 安装 使用npm npm install maptalks.control.compass : npm install maptalks.control.compass 。 用纱安装: yarn add maptalks.control.compass 。 从下载...
Compass是搜狗商业平台研发部开发的一套轻量级的分布式数据库访问框架,支持单库、主从库读写分离、分库、分库之后再分表、从库负载均衡和HA等使用场景,并且在框架层面提供了主从反延迟策略。Compass采用Spring配置...
#Codiad 指南针 指南针命令集成插件 ##要求 ##安装 下载 zip 文件并将其解压缩到您的插件文件夹。 ##特征 创造 编译 干净的 手表 日志窗口 ##去做 国际化 #接触 推特: ##执照
细胞指南 :compass: 在您的Web浏览器中浏览单细胞RNA-seq数据集。 在尝试 产品特点 在UMAP图上显示元数据 在UMAP图形上显示基因表达 单元群集和元数据类别的汇总统计信息 立即找到任何基因 浏览每个基因的统计数据...
:compass: 导航套件 NavigationKit是一个轻量级的库,它使SwiftUI导航超级易于使用。 :laptop: 安装 :package: 迅捷软件包管理器 使用 ,将其作为Xcode 11.0或更高版本中的select File > Swift Packages > Add ...
grunt-contrib-compass v1.1.1 使用Compass将Sass编译为CSS入门如果您以前从未使用过 ,请务必查看《指南》,因为它说明了如何创建以及安装和使用Grunt插件。 熟悉该过程后,可以使用以下命令安装此插件: npm ...
棱镜多租户 :compass: :compass: 使用Prisma作为您的应用程序的多租户提供程序什么是多租户应用程序? 应用程序是指应用程序的单个实例在服务器上运行并为多个租户提供服务的情况。 借助多租户体系结构,软件应用...
compass搜索引擎技术 eclipse mysql 实现像google的搜索功能
compass文档资料
compass对象搜索引擎
做自己的搜索引擎-搜索引擎精解案例教程lucenen compass 搜索引擎框架
Compass概念: 1:Compass相当于hb的SessionFactory 2:CompassSession相当于hb的Session 3:CompassTransaction相当于hb的transaction。 <br>Compass也是采用CompassConfiguration(装载配置和映射文件...
team-compass:用于在整个JupyterHub生态系统中进行团队交互,同步和处理会议记录的存储库
如何使用这张图片指南针手表 docker run --rm -v [SCSS_DIR]:/input -v [CSS_DIR]:/output -v [IMAGES_DIR]:/images stevevega/compass watch将[SCSS_DIR]替换为主机scss源目录,将[CSS_DIR]替换为主机css输出目录。...
使用RCON命令compass.SetPosition , compass.SetIndicator和compass.ShowDegrees 通过从另一个mod调度事件,传递您的首选值 -- update the config from another mod example Events: Dispatch ( ' Compass:Config '...