首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

凭借Play!framwork,lucene,taobao kissy 实现完整的前后端suggest功能

2012-12-22 
借助Play!framwork,lucene,taobao kissy 实现完整的前后端suggest功能先上效果图:我是基于Play!framework

借助Play!framwork,lucene,taobao kissy 实现完整的前后端suggest功能
先上效果图:


   我是基于Play!framework开发的网站 想了解童鞋可以看看http://www.iteye.com/topic/806974这篇帖子,目前最新版本是1.1,还有童鞋没听说过play!framework吗?简单的科普一下(以下内容来自于互联网):

  去掉标注为红色的那一行前面的#号,如果你将你的项目部署到服务器上,而你的服务器上没有play安装包,那你可以把search包直接放到你的项目WEB-INF(把项目打成war后)路径下,这儿改为:module.search=../search,这样就不会有找不到search module的错误了。
  Search module已经配置好了,那我们就完整的实现这个小东西:前端的东西基本上引入kissy的主文件和kissy suggest 就行(当然还少不了必要的css^_^)。我们这儿为:
 

<script type="text/javascript" src="@{'public/javascripts/kissy/kissy.js'}"></script>     <script type="text/javascript" src="@{'/public/javascripts/kissy/suggest.js'}"></script>  

然后查询控件为:

 <form id="J_TSearchForm" action="@{Shops.search()}" name="search" target="_top">           <div id="q" autocomplete="off" accesskey="s"> <s name="code">   KISSY.ready(function(S) {      var sug = new S.Suggest('#q', "@{Shops.searchSuggest()}", {            autoFocus: true,            resultFormat: '约%result%个宝贝'        });   });

   开始说说后端实现的思路:  首先我们需要建立一个搜索词的词库。这个词库包含的内容有 1、检索词  2、检索次数(用于实现哪个词热度排序)3、检索词的拼音缩写版  用于输入个拼音也能给出提示。

首先说下模型类

这儿我们主要用到了两个实体:Product(商品对象)  SearchIndex(搜索建议词对象)

@Entity@Indexedpublic class SearchIndex extends Model{@Fieldpublic String name;//关键词@Fieldpublic long searchTimes;// 搜索次数@Fieldpublic String pinyin;//拼音版public SearchIndex(String name){this.name = name;this.pinyin = Tool.cn2Spell(name);save();}

  上面是SearchIndex的大部分代码。大体说下:@Index表示这个类可以需要lucene建立索引,继承的Model类是play对CRUD的大部分封装,是以JPA为基础作的富血的Domain Model的基类。然后@Field注解表示需要索引的字段。  在构造方法中,有Tool.cn2Spell这一句,使用了Pinyin4j做的从汉字到拼音简写的转换。这段代码网上找的,我就不贴出来了。

   然后说下搜索词的词库的建立:这儿我们主要是把商品名给分词后保存到词库中建立的搜索提示词的词库。在Product的构造方法里我们加了这么一句:
  
this.addToIndexStore(name);

这个方法的实现为:
public static void addToIndexStore(String productName){try {List<String> list =Tool.paodingAnalyzerWord(productName);for(String str:list){if(!SearchIndex.isExsist(str)){new SearchIndex(str);Logger.info("SearchIndex  添加索引:", str);}}} catch (IOException e) {e.printStackTrace();}}

  这儿我们用到了庖丁解牛的中文分词。Search module默认使用的分词是lucene自带的那个StandardAnalyzer,这个在处理中文上还无法满足我们的需要,所以我选用了社区中比较知名的庖丁解牛,事实上开始我选的是IK Analyzer的,但一直没有找到合适匹配Play自带的lucene的版本 ^_^ 。下载庖丁http://code.google.com/p/paoding/  因为我使用的play版本是1.0.3 其中自带的lucene版本是2.3.1  所以我们下载庖丁用那个paoding-analysis-2.0.4-beta.zip 即可 
还需要更改一下search module默认的分词:找到application.conf: 加入下面两句
  play.search.reindex=enabled  play.search.analyser=net.paoding.analysis.analyzer.PaodingAnalyzer

第一句的作用官方文档是这样解释的:



  然后我们再来看看上面包含代码的那个图中的代码:分词的那一句是:
   Tool.paodingAnalyzerWord:看代码:
public static List<String> paodingAnalyzerWord(String word) throws IOException{    PaodingAnalyzer analyzer = new PaodingAnalyzer();    StringBuilder sb = new StringBuilder();    TokenStream ts = analyzer.tokenStream("", new StringReader(word));    Token token;             sb.setLength(0);             ArrayList<String> results = new ArrayList<String>();             while ((token = ts.next()) != null) {                sb.append(new String(token.termBuffer()).trim()).append('/');             results.add(new String(token.termBuffer()).trim());        }        if (sb.length() > 0) {           sb.setLength(sb.length() - 1);        }                return results;}


这段代码实现了中文分词,基本上没有啥需要解释的。
然后我们遍历分出来的词,查询下这个词是不是已经存在,存在的话就不用理它,不存在的话就加入到检索词词库中。这儿我都是和数据库直接交互,可能性能上会有问题,所以我们可以把搜索词全部加载到缓存中再做处理。

这样搜索建议词的词库就建立好了。

然后我们看看Shops.searchSuggest(上图中搜索form提交的地方)方法的实现:
    /**     * 商品搜索提示     */public static void searchSuggest(String q) throws IOException{Search.Query query = Search.search("name:"+q.trim()+"* OR pinyin:"+q.trim()+"*", SearchIndex.class);List<SearchIndex> list =query.orderBy("searchTimes").reverse().page(0, 8).fetch();List<String[]> results = new ArrayList<String[]>();for(SearchIndex si:list){     Search.Query q2=Search.search("name:"+si.name+"*",Product.class);     String[] str ={si.name,String.valueOf(q2.count())};     results.add(str);}String result =new Gson().toJson(results);renderJSON("KISSY.Suggest.callback({'result':"+result.replace(""", "\'")+"})");}

  解释下上面的代码:

  第一句中的Search.Query是search module中的类,主要是对lucene操作的一些封装。Search.search()中的第一个参数是lucene查询表达式。这儿表示以name或者pinyin这两个字段进行匹配查询。这个查询用于查找用户输入字的相关搜索词(suggest)。

   下面的for循环用于查询匹配这个搜索词的商品的数量。
最后返回json:注意,这儿返回的JSON串都必须是单引号包括。比如{‘name’:’zhangsan’}这种。

   这样基本上就完成了一个简单的search suggest  功能。写的比较繁杂,主要是为了力求把事情说清楚,同时掺杂了一些play的使用说明。本文主要目的是向大家展示Play!framework的灰常好用,由于个人水平有限,极有可能存在不合适的地方,所以本文参考为主,不对的还请大家多多指教
不是的。。。play这儿是个服务端的东西。我只是顺路普及了下play!framework。。用其它的服务端框架是一样的
),还没用用过您所说的spellchecker,您如果熟悉的话可以写写您的经验啊   <p>?</p>

热点排行