- 浏览: 212591 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
wuMing2014:
楼主,在ExtendServlet类中的Ioc ioc = n ...
freemarker 自定义标签 -
washingtonDC:
非常精彩!运行时异常(即非受控异常)自动强制执行整个逻辑工作单 ...
Spring事务的传播行为 @Transactional -
tom31203120:
freemarker 自定义标签 -
osacar:
tom31203120 写道oscar 不是 osacar还真 ...
freemarker 自定义标签 -
tom31203120:
oscar 不是 osacar
freemarker 自定义标签
在上一篇文章中主要讲了,配置要索引的表和compass与spring整合时的配置。接下来我把余下的两部分写出来。 第三步:配置手动创建索引的功能。 这个其实只需在第一次生成索引的时候用,当系统正常运行时,compass中的hibernateGps会自动检测数据的变动,同时同步索引文件的。 首先在applicationContext.xml中配置bean. <!-- 手工生成索引 --> <bean id="buildIndexController" class="org.compass.spring.web.mvc.CompassIndexController"> <property name="compassGps" ref="hibernateGps" /> <property name="indexView" value="/ftl/create.ftl" /> <property name="indexResultsView" value="/ftl/create.ftl" /> </bean> 同时我们也要配置与之相应的请求映射。 <bean id="urlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/buildindex.htm">buildIndexController</prop> </props> </property> </bean> 最后就是自动生成索引的页面了,这里我用的是freemarker.用什么都一样,你可以用jsp,html. create.ftl(在WebRoot下的ftl文件夹下) <html> <head> <title>builderIndex</title> </head> <body> <h1> 手工重建索引 </h1> <p> <form name="keyword" action="/buildindex.htm" method="post"> <INPUT type="hidden" name="doIndex" value="true"> <input type="submit" value="手工重建索引" /> </form> <#if indexResults?exists> 本次索引耗时${indexResults.indexTime}毫秒! </#if> <p> </body> </html> 当我们点击手工重建索引按钮时,会在我们指定的索引目录下<prop key="compass.engine.connection">E:/video</prop>也就先在E:/video下生成gpsindex/video-index当索引生成完以后,会返回生成索引所用的毫秒数。这时就会把gpsindex文件夹下的video-index覆盖到E:/video/index/下的video-index文件夹。这时gpsindex/video-index也消失了。这就是简单的生成索引的过程。接下来我们要说最后一步了。索引我们已建好了,怎么去搜索我们想要的数据了。 第四步:建立搜索功能。 首先写一个controller.即searchController.java public class SearchController extends AbstractCompassCommandController { private String searchView; private String searchResultsView; private String searchResultsName = "searchResults"; private Integer pageSize; private Integer sectionSize; private CompassSearchHelper searchHelper; public CompassSearchHelper getSearchHelper() { return searchHelper; } public SearchController() { setCommandClass(CompassSearchCommand.class); } public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); if (searchView == null) { throw new IllegalArgumentException( "Must set the searchView property"); } if (searchResultsView == null) { throw new IllegalArgumentException( "Must set the serachResultsView property"); } if (searchHelper == null) { searchHelper = new CompassSearchHelper(getCompass(), getPageSize()); } } protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { Log log4j = LogFactory.getLog("video"); log4j.info("SearchController say: hello"); final CompassSearchCommand searchCommand = (CompassSearchCommand) command; String query = searchCommand.getQuery(); searchCommand.setQuery(query); if (!StringUtils.hasText(searchCommand.getQuery())) { return new ModelAndView(getSearchView(), getCommandName(), searchCommand); } CompassSearchResults searchResults = searchHelper.search(searchCommand); log4j.info("searchResults.getHits().length = " + searchResults.getHits().length); CompassPage page = new CompassPage(searchResults.getHits(), pageSize.intValue(), searchCommand.getPage().intValue() + 1, searchResults.getTotalHits(), sectionSize.intValue(), searchCommand.getQuery(), searchResults.getSearchTime()); return new ModelAndView(getSearchResultsView(), "data", page); } /** * Returns the view that holds the screen which the user will initiate the * search operation. */ public String getSearchView() { return searchView; } /** * Sets the view that holds the screen which the user will initiate the * search operation. */ public void setSearchView(String searchView) { this.searchView = searchView; } /** * Returns the name of the results that the * {@link org.compass.core.support.search.CompassSearchResults} will be * saved under. Defaults to "searchResults". */ public String getSearchResultsName() { return searchResultsName; } /** * Sets the name of the results that the * {@link org.compass.core.support.search.CompassSearchResults} will be * saved under. Defaults to "searchResults". */ public void setSearchResultsName(String searchResultsName) { this.searchResultsName = searchResultsName; } /** * Returns the view which will show the results of the search operation. */ public String getSearchResultsView() { return searchResultsView; } /** * Sets the view which will show the results of the search operation. */ public void setSearchResultsView(String resultsView) { this.searchResultsView = resultsView; } /** * Sets the page size for the pagination of the results. If not set, not * pagination will be used. */ public Integer getPageSize() { return pageSize; } /** * Returns the page size for the pagination of the results. If not set, not * pagination will be used. * * @param pageSize * The page size when using paginated results */ public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } /** * <p> * The search helper is used to execute teh actual search. By default (if * not set) the search controller will create a new search helper. If * provided, the search controller will use it to perform the search. * * <p> * Mainly used to extend the search helper and execute additional operation * within specific calbacks the search helper exposes. * * @param searchHelper * A specific search helper to use */ public void setSearchHelper(CompassSearchHelper searchHelper) { this.searchHelper = searchHelper; } public Integer getSectionSize() { return sectionSize; } public void setSectionSize(Integer sectionSize) { this.sectionSize = sectionSize; } } 还需要一个CompassPage.java主要来实现分页的。 public class CompassPage implements Page { private CompassHit[] elements; private int pageSize; private int pageNumber; private int totalElements = 0; private int sectionSize; private String query; private long searchTime; public long getSearchTime() { return searchTime; } public void setSearchTime(long searchTime) { this.searchTime = searchTime; } /** * * @param pageNumber * 当前页编码,从1开始,如果传的值为Integer.MAX_VALUE表示获取最后一页。 * 如果你不知道最后一页编码,传Integer.MAX_VALUE即可。如果当前页超过总页数,也表示最后一页。 * 这两种情况将重新更改当前页的页码为最后一页编码。 * @param pageSize * 每一页显示的条目数 * @param sectionSize * 每一节显示的页数. */ public CompassPage(CompassHit[] elements, int pageSize, int pageNumber, int totalElements, int sectionSize, String query, long searchTime) { super(); this.elements = elements; this.pageSize = pageSize; this.pageNumber = pageNumber; this.totalElements = totalElements; this.sectionSize = sectionSize; this.query = query; this.searchTime = searchTime; if (Integer.MAX_VALUE == this.pageNumber || this.pageNumber > getLastPageNumber()) // last page { this.pageNumber = getLastPageNumber(); } } public String getQuery() { return query; } public void setQuery(String query) { this.query = query; } public CompassHit[] getElements() { return elements; } public void setElements(CompassHit[] elements) { this.elements = elements; } public int getPageNumber() { return pageNumber; } public void setPageNumber(int pageNumber) { this.pageNumber = pageNumber; } public int getSectionSize() { return sectionSize; } public void setSectionSize(int sectionSize) { this.sectionSize = sectionSize; } public int getTotalElements() { return totalElements; } public void setTotalElements(int totalElements) { this.totalElements = totalElements; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getLastPageNumber() { return totalElements % this.pageSize == 0 ? totalElements / this.pageSize : totalElements / this.pageSize + 1; } public int getNextPageNumber() { return getThisPageNumber() + 1; } public int getNextSectionFirstPageNumber() { return (pageNumber / sectionSize + 1) * sectionSize + 1; } public int getPageSize() { return pageSize; } public int getPreviousPageNumber() { return (getThisPageNumber() == 1) ? 1 : getThisPageNumber() - 1; } public int getPreviousSectionFirstPageNumber() { return (pageNumber / sectionSize - 1) * sectionSize + 1; } public Object getThisPageElements() { return elements; } public int getThisPageFirstElementNumber() { return (getThisPageNumber() - 1) * getPageSize() + 1; } public int getThisPageLastElementNumber() { int fullPage = getThisPageFirstElementNumber() + getPageSize() - 1; return getTotalNumberOfElements() < fullPage ? getTotalNumberOfElements() : fullPage; } public int getThisPageNumber() { return pageNumber; } public int getThisSectionFirstPageNumber() { return (getThisPageNumber() % sectionSize == 0) ? getThisPageNumber() / sectionSize * sectionSize : getThisPageNumber() / sectionSize * sectionSize + 1; } public int getThisSectionLastPageNumber() { int fullSection = (getThisPageNumber() / sectionSize + 1) * sectionSize; return getLastPageNumber() < fullSection ? getLastPageNumber() : fullSection; } public List getThisSectionPagesBar() { // 翻页 页码条 List pagesBar = new ArrayList(); if (hasPreviousSection()) { // 不是第一捆 if (hasNextSection()) {// 不是最后一捆 for (int j = getPreviousSectionFirstPageNumber() + sectionSize; j <= getNextSectionFirstPageNumber() - 1; j++) { pagesBar.add(new Integer(j)); } } else { // 是最后一捆 for (int j = getPreviousSectionFirstPageNumber() + sectionSize; j <= (getLastPageNumber()); j++) { pagesBar.add(new Integer(j)); } } } else { // 是第一捆 // log4j.info("是第一捆 getLastPageNumber()=" + getLastPageNumber()); for (int j = 1; j <= (getLastPageNumber() < sectionSize ? getLastPageNumber() : sectionSize); j++) { // log4j.info("j=" + j); pagesBar.add(new Integer(j)); } } return pagesBar; } public int getTotalNumberOfElements() { return totalElements; } public boolean hasNextPage() { return getLastPageNumber() > getThisPageNumber(); } public boolean hasNextSection() { return getLastPageNumber() > (pageNumber / sectionSize + 1) * sectionSize; } public boolean hasPreviousPage() { return getThisPageNumber() > 1; } public boolean hasPreviousSection() { return pageNumber / sectionSize * sectionSize > 1; } public boolean isFirstPage() { return getThisPageNumber() == 1; } public boolean isLastPage() { return getThisPageNumber() >= getLastPageNumber(); } } 在定义一个分页接口Page.java。 /** * 分页信息接口 */ public interface Page { /** * 是否是首页(第一页),第一页页码为1 * * @return 首页标识 */ public boolean isFirstPage(); /** * 是否是最后一页 * * @return 末页标识 */ public boolean isLastPage(); /** * 是否有下一页 * * @return 下一页标识 */ public boolean hasNextPage(); /** * 是否有上一页 * * @return 上一页标识 */ public boolean hasPreviousPage(); /** 是否有下一个页面单元 */ public boolean hasNextSection(); /**是否有前一个页面单元*/ public boolean hasPreviousSection(); /** * 获取最后一页页码,也就是总页数 * * @return 最后一页页码 */ public int getLastPageNumber(); /** * 当前页包含的数据,不同的情况可能返回的数据类型不一样,如List,RowSet等,请参考具体的实现 * * @return 当前页数据源 */ public Object getThisPageElements(); /** * 总的数据条目数量,0表示没有数据 * * @return 总数量 */ public int getTotalNumberOfElements(); /** * 获取当前页的首条数据的行编码 * * @return 当前页的首条数据的行编码 */ public int getThisPageFirstElementNumber(); /** * 获取当前页的末条数据的行编码 * * @return 当前页的末条数据的行编码 */ public int getThisPageLastElementNumber(); /** * 获取下一页编码 * * @return 下一页编码 */ public int getNextPageNumber(); /** * 获取上一页编码 * * @return 上一页编码 */ public int getPreviousPageNumber(); /* 获取下一个页面单元的第一页 */ public int getNextSectionFirstPageNumber(); /* 获取前一个页面单元的第一页 */ public int getPreviousSectionFirstPageNumber(); /** * 每一页显示的条目数 * * @return 每一页显示的条目数 */ public int getPageSize(); /** * 当前页的页码 * * @return 当前页的页码 */ public int getThisPageNumber(); /* 当前片断第一页页码 */ public int getThisSectionFirstPageNumber(); /* 当前片断第一页页码 */ public int getThisSectionLastPageNumber(); /* *当前片断 页码表 */ public List getThisSectionPagesBar(); } 最后要配置一下bean和请求映射了。 <bean id="urlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/search.htm">searchController</prop> </props> </property> </bean> <!-- 搜索的控制器 --> <bean id="searchController" class="com.jack.video.SearchController" lazy-init="true"> <property name="compass" ref="compass" /> <property name="searchView" value="/ftl/search.ftl" /> <property name="searchResultsView" value="/ftl/search.ftl" /> <property name="pageSize" value="10" /> <property name="sectionSize" value="10" /> <property name="searchHelper"> <ref local="advanceCompassSearchHelper" /> </property> </bean> 最后为了能给搜索到的结果高亮显示。还需要配置。 <!-- 高亮字段显示 --> <bean id="advanceCompassSearchHelper" class="com.jack.video.util.AdvanceCompassSearchHelper"> <property name="highlightFields"> <list> <value>CName</value> </list> </property> <property name="pageSize"> <value>10</value> </property> <constructor-arg ref="compass" /> </bean> AdvanceCompassSearchHelper .java文件 public class AdvanceCompassSearchHelper extends CompassSearchHelper { private String[] highlightFields; public String[] getHighlightFields() { return highlightFields; } public void setHighlightFields(String[] highlightFields) { this.highlightFields = highlightFields; } /** * @param compass */ public AdvanceCompassSearchHelper(Compass compass) { super(compass); } /* * (non-Javadoc) * * @see org.compass.core.support.search.CompassSearchHelper#doProcessBeforeDetach(org.compass.core.support.search.CompassSearchCommand, * org.compass.core.CompassSession, org.compass.core.CompassHits, int, * int) */ @Override protected void doProcessBeforeDetach(CompassSearchCommand searchCommand, CompassSession session, CompassHits hits, int from, int size) { if (from < 0) { from = 0; size = hits.getLength(); } if (highlightFields == null) { return; } // highlight fields for (int i = from; i < size; i++) { for (String highlightField : highlightFields) { hits.highlighter(i).fragment(highlightField); } } } }
这是搜索页主要的代码。 <form method="get" action="/search.htm"> <input type="text" size="50" name="query" value="${query?if_exists}" /> <input type="hidden" name="page" value="1"/> <input type="submit" value="搜索" /> </form> 以下是结果页的主要代码。
<#macro s_search_result data="" config=""> <script type="text/javascript"> var videoList = { channelId: ${channelId} }; </script> <div class="box"> <div class="ir_box"> <div class="title"> <@s_option_button /> <ul class="tag_menu"> <li><a class="current" href="javascript:;"><span>搜索结果</span></a></li> </ul> </div> <div class="content"> <@s_module_config data=config /> <div class="show_mode"> </div> <div class="show_mode"> <ul class="nonce_mode"> <li>共有 ${data.totalElements} 项符合 ${data.query} 的查询结果</li> <li>第 ${data.pageNumber}/${data.lastPageNumber} 页</li> <li>用时 ${data.searchTime} 毫秒</li> </ul> <ul class="choose_mode"> <li></li> <li></li> </ul> </div> <#if data.elements?exists && data.elements?has_content > <#list data.elements as d> <div class="veol_cloud"> <div class="vec_content"> <div class="vec_info"> <p> <strong>名字:</strong><@s_se v=d.data.description /> </p> <p> <strong>导演:</strong> <span class="null_director"><@s_se v=d.data.director /></span> </p> <p> <strong>类型:</strong> <span class="null_genre"><@s_se v=d.data.genre /></span> </p> </div> </div> </div> </div> </#list> <ul class="paging"> <li> <span>共有 <b>${data.totalElements}</b> 项 第 <b>${data.pageNumber}</b> / <b>${data.lastPageNumber}</b> 页</span> </li> <li> <a href="/search.htm?query=${data.query}&page=1" title="第一页">←</a> </li> <#if (data.getThisSectionFirstPageNumber()>1)> <li> <a href="/search.htm?query=${data.query}&page=${data.getThisSectionFirstPageNumber()}" title="快速向前翻10页" /><<</a> </li> </#if> <#if (data.getPreviousPageNumber()>1)> <li> <a href="/search.htm?query=${data.query}&page=${data.getPreviousPageNumber()}" title="向前翻1页" /><</a> </li> </#if> <#if data.getThisSectionPagesBar()?exists> <#list data.getThisSectionPagesBar() as d> <li> <a href="/search.htm?query=${data.query}&page=${d}">${d}</a> </li> </#list> </#if> <#if (data.getNextPageNumber()<=data.lastPageNumber)> <li> <a href="/search.htm?query=${data.query}&page=${data.getNextPageNumber()}" title="向后翻1页" />></a> </li> </#if> <#if (data.getNextSectionFirstPageNumber()<=data.lastPageNumber)> <li> <a href="/search.htm?query=${data.query}&page=${data.getNextSectionFirstPageNumber()}" title="快速向后翻10页" />>></a> </li> </#if> <li> <a href="/search.htm?query=${data.query}&page=${data.lastPageNumber}" title="最后一页">→</a> </li> </ul> <#else> 暂无相关影片 </#if> </div> </div> </div></#macro>
现在把快速给你的网站搭建搜索功能已讲完。写的过程中可能有不对的地方,希望你在调试的时候该过来。基本的实现原理及过程已讲了,至于如何用,就看你自己来。我主要快速的把要点讲了一下。里面还有很多细节。有时间的话再和大家讨论。
发表评论
-
Compass将lucene、Spring、Hibernate三者结合
2011-05-20 01:31 43151.概述 Compass将lucene、Spring、Hib ... -
compass 使用详解
2011-05-20 01:21 6597我们在使用lucene管理document时,难免有些复杂,并 ... -
用compass快速给你的网站添加搜索功能<一>
2011-05-20 00:48 1219如果你的网站架构采用的是spring+hibernate。用现 ... -
compass 分页查询
2011-05-20 00:43 1514有了配置文件之后,我们就可以写出相应的增删改查了 public ... -
Spring Compass (Lucene) 全文本搜索排序问题
2011-05-19 23:57 2389import org.compass.core.Com ... -
再谈compass:集成站内搜索
2011-05-19 06:12 1569前段时间已经写了一篇关于compass的文章,相信大家对com ...
相关推荐
Compass是一个开源的.NET和Java框架,它为应用程序提供了完整的文本搜索功能。该框架支持多种搜索引擎(如Elasticsearch, Solr等),使得开发人员能够在不深入学习特定搜索引擎的情况下,轻松地在其应用中集成高级的...
Compass搜索引擎技术是一种基于Lucene的全文检索框架,它提供了更高级别的API和集成机制,使得在Java应用程序中实现搜索引擎功能变得更加便捷。Compass的主要目标是将全文索引能力无缝地融入到现有的业务应用程序中...
总的来说,使用 Compass 和 Lucene 实现全文检索功能,能够极大地提升 Java 应用的搜索体验,让开发者能够快速响应用户的查询需求。这两个工具的结合使用,不仅可以处理简单的文本搜索,还能够应对复杂的查询条件和...
Lucene提供了底层的搜索功能,而Compass是对Lucene的高级封装,它在Lucene的基础上添加了更多便利的功能,如ORM集成、事务支持等。对于开发者来说,使用Compass可以更快地上手,减少对Lucene底层细节的了解,提高...
学习和使用Compass全文搜索,你需要掌握以下几个关键知识点: 1. **Lucene基础知识**:理解Lucene的索引结构、倒排索引、Term和Document的概念,以及如何使用Analyzer处理文本。 2. **Compass配置**:设置数据源、...
通过Compass,你可以将对象-关系映射(ORM)与全文检索完美结合,使得数据库中的数据能够被快速高效地搜索。 **Compass的核心特性** 1. **对象-搜索映射(OSM)**:Compass允许你定义对象-搜索映射,将Java对象与...
6. **搜索**:使用Compass提供的API执行搜索操作。 #### 五、基于SSH的Compass实例 下面是一个基于SSH(Struts2+Spring+Hibernate)架构的Compass使用示例: 1. **添加依赖库**:在SSH项目基础上添加Compass及...
你需要下载并添加compass库的jar文件,然后配置Compass的连接器,使其与Hibernate集成。这样,当Hibernate进行数据操作时,Compass会自动更新索引。在Spring配置中,你可以声明一个CompassTemplate bean,它提供了与...
1. **Lucene**: Apache Lucene是一个基于Java的全文搜索引擎库,通过它可以轻松地为Java应用程序添加全文搜索功能。Lucene的主要工作是对文件中的每个词进行索引,这种索引机制极大地提高了搜索效率。它提供了一组...
通过使用Compass,开发者可以轻松地在应用程序中添加全文索引和搜索功能,从而提升用户体验和数据查询效率。 **Compass的主要特性** 1. **无缝集成**:Compass能够自动跟踪和索引数据库中的变化,使得索引始终保持...
这使得在不改变业务逻辑的情况下,轻松地为已有对象添加搜索能力。 一旦映射配置完成,你可以启动Compass实例,它会自动建立索引。之后,每当数据发生变化时,Compass可以实时更新索引,保持搜索结果的准确性。在你...
这个实例提供了从零开始使用Compass进行全文检索的一个起点,通过它你可以快速地了解和实践Compass的使用,同时也可以学习如何在SSH框架下整合全文检索功能。在深入学习和实践中,你将进一步掌握如何利用Compass提升...
Compass是基于Apache Lucene的一个高级全文搜索引擎,它将Lucene的功能与持久化层相结合,使得数据库中的数据能够被快速检索。Compass的核心特性包括: 1. **ORM集成**:Compass可以与流行的ORM框架如Hibernate、...
标题中的"S2SH+compass"指的是使用Struts2(S),Spring(S)和Hibernate(H)这三种开源框架的组合,再加上Compass搜索引擎库来实现一个网站内部的全文检索功能。这种组合常见于Java Web开发中,用于构建复杂、高...
在实际应用中,`compass+lucene`的组合使得开发者可以轻松地在Java应用中添加全文搜索功能,而无需深入了解搜索引擎的复杂细节。通过 Compass 的 ORM 集成,开发者可以直接在存储在数据库中的对象上执行全文搜索,这...
### C# 安装并使用 Mongodb 的详细指南 #### Mongodb 在 Windows 7 上的安装与配置 **一、Mongodb 安装步骤** 1. **下载 Mongodb 安装包** - 下载 `mongodb-win32-x86_64-2008plus-ssl-3.6.5-signed`。 - 注意...
通过Compass,开发者可以轻松地为数据库中的对象添加全文索引,实现快速的全文搜索。 Lucene,另一方面,是Apache软件基金会的一个项目,它是一个高性能、可扩展的信息检索库。Lucene提供了完整的搜索功能,包括...
而Compass是一个基于Lucene的搜索引擎库,它简化了在Java应用中集成全文搜索的功能。 首先,让我们详细了解一下SSH2中的每个框架: 1. Spring:这是一个轻量级的IoC(Inversion of Control)和AOP(Aspect-...
在实际项目中,使用SSH框架集成Compass插件,可以有效地提升Web应用的搜索性能,为用户提供快速、精准的查询体验。同时,Compass的易用性和灵活性使其成为Java开发中一个理想的全文搜索解决方案。