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

2023-11-29 00:32

本文主要是介绍借助Play!framwork,lucene,taobao kissy 实现完整的前后端suggest功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我是基于Play!framework开发的网站 想了解童鞋可以看看http://www.iteye.com/topic/806974这篇帖子,目前最新版本是1.1,还有童鞋没听说过play!framework吗?简单的科普一下(以下内容来自于互联网):
引用
Play Framework是一个功能完整的Java Web开发框架。采用RESTful架构设计,简便灵活。Play Framework使用MVC模式作为Web层,集成JPA构建持久层,Play Framework还使用一个基于Groovy的模板引擎。
其特征如下:
1. Play Framework让开发者无须重新编译打包发布应用,即可看到修改后的效果,方便开发人员调试应用。
2. Play!Framework采用了无状态模型,是一个真正意义上的“无共享”系统,能够在多个服务器上部署多个Play!Framework的实例,所有实例都不会互相干扰。
3. Play!Framework采用了Groovy作为模板引擎,让表示层真正做到了开发高效简洁
4. Play!Framework拥有精确的错误定位机制,当错误发生的时候,可以精确的定位到错误代码的位置。
5. Play!Framework的速度很快,启动快,运行的速度也十分快。

官方网站是: [url]http://www.playframework.org/ [/url] 再广一个告:中文社区http://www.daocaozhu.com/ (刚开始弄,还希望喜欢play的童鞋一块在这里交流play!framework的使用心得,为play!framework在中国的发展贡献你的力量)
回到正题上来:要实现这样的效果,我们都知道需要两个必不可少的工具:
1、前端suggest组件;2、中文分词以及全文检索
Suggest组件我选择了淘宝UED团队开发的开源js库:Kissy 官方网站是:[url]https://www.github.com/kissyteam/kissy [/url]为什么选择kissy呐,我主要是被它的suggest组件还有图片轮换的组件所吸引,而且是淘宝UED团队开发的,质量上应该有保证,当然用起来确实也不错,虽然在选型上有些激进^_^。
全文检索毫无疑问是lucene,中文分词我用的是庖丁解牛(感谢作者的贡献)。
Play提供了很多module,而集成lucene我们就需要用到search-module:http://www.playframework.org/modules/search 使用方法很简单,下载search-module到你Play目录下的modules文件夹里(不过好像play的安装包里已经带了,忘记了^_^),然后在你项目的配置文件application.conf中

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

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

然后查询控件为:

Java代码
<form id="J_TSearchForm" action="@{Shops.search()}" name="search" target="_top">
<div class="tsearch-panel-fields ">
<label for="q" class="">输入您想要的商品名称</label>
<input name="q" id="q" autocomplete="off" accesskey="s">
<s class="rc-tp-l"></s>
<s class="rc-bt-l"></s>
</div>
<button type="submit">搜索</button>
</form>

代码很眼熟?好吧,我承认,我山寨的taobao的…..
加入Js 代码:

Java代码
KISSY.ready(function(S) {
var sug = new S.Suggest('#q', "@{Shops.searchSuggest()}", {
autoFocus: true,
resultFormat: '约%result%个宝贝'
});
});

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

首先说下模型类

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

Java代码
@Entity
@Indexed
public class SearchIndex extends Model{

@Field
public String name;//关键词

@Field
public long searchTimes;// 搜索次数

@Field
public 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的构造方法里我们加了这么一句:

Java代码
this.addToIndexStore(name);

这个方法的实现为:
Java代码
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: 加入下面两句
Java代码
play.search.reindex=enabled
play.search.analyser=net.paoding.analysis.analyzer.PaodingAnalyzer

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



然后我们再来看看上面包含代码的那个图中的代码:分词的那一句是:
Tool.paodingAnalyzerWord:看代码:
Java代码
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提交的地方)方法的实现:
Java代码
/**
* 商品搜索提示
*/
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!framwork,lucene,taobao kissy 实现完整的前后端suggest功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/430794

相关文章

MySQL 横向衍生表(Lateral Derived Tables)的实现

《MySQL横向衍生表(LateralDerivedTables)的实现》横向衍生表适用于在需要通过子查询获取中间结果集的场景,相对于普通衍生表,横向衍生表可以引用在其之前出现过的表名,本文就来... 目录一、横向衍生表用法示例1.1 用法示例1.2 使用建议前面我们介绍过mysql中的衍生表(From子句

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

Mybatis的分页实现方式

《Mybatis的分页实现方式》MyBatis的分页实现方式主要有以下几种,每种方式适用于不同的场景,且在性能、灵活性和代码侵入性上有所差异,对Mybatis的分页实现方式感兴趣的朋友一起看看吧... 目录​1. 原生 SQL 分页(物理分页)​​2. RowBounds 分页(逻辑分页)​​3. Page

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

MYSQL查询结果实现发送给客户端

《MYSQL查询结果实现发送给客户端》:本文主要介绍MYSQL查询结果实现发送给客户端方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql取数据和发数据的流程(边读边发)Sending to clientSending DataLRU(Least Rec

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

使用SpringBoot整合Sharding Sphere实现数据脱敏的示例

《使用SpringBoot整合ShardingSphere实现数据脱敏的示例》ApacheShardingSphere数据脱敏模块,通过SQL拦截与改写实现敏感信息加密存储,解决手动处理繁琐及系统改... 目录痛点一:痛点二:脱敏配置Quick Start——Spring 显示配置:1.引入依赖2.创建脱敏

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流