用户在输入搜索关键词时,根据已经输入的部分,自动提示出后面可能需要输入的词,既减少了用户输入的劳动量,也可以提示用户当前有哪些备选,有效的降低输错的几率,提升搜索的体验。
在第一期中,我们做了一个汉字提示的功能,从User Log中提取出每天搜索频率最高的词,和这些词命中的搜索结果数,更新到服务器中,然后提供补全提示功能。数据每天凌晨增量更新一次,保证数据的实时性,相比其他产品的补全功能,我们的数据要及时准确的多。
系统结构:
系统的性能:
由于结构简单,使用UDP通信,后台全部使用内存树的结构,处理能力>3000个/秒
数据结构和算法:
1.原始数据 <<string keyword,int freq,int cnt>........>
keyword按照unsigned char建立节点:0~255 最多可以建立 255棵树
下层子节点按照1/4字节(0~16)建立子节点,主要是存储效率和查询效率上考虑,同时使用一个tag标识节点是否是最后一个节点
2.树结构示意图:
3.例如,原始数据中的字符串:我是中国人,分解后:0XA0B0C1D2...这样的十六进制串,按照2中的格式存储到树中
4.用户输入,用户每次按下键盘,触发js的keydown事件,发送一个请求到CGI,CGI将用户输入的内容送到SuggestSvr,suggestsvr分解用户输入串,根据编码去树中查询,最后将结果压入优先级队列中,返回搜索频率最高的前10个结果给用户,值得一提的是,我们对返回结果的用户的KeyWord做了分词处理,以保证用户的搜索结果更加丰富
在实际的运营环境中,我们从log中看到,用户直接输入拼音进行搜索导致失败的比率比较高,例如输入“shouji”来搜索“手机”,在上个版本中,我们做了一个优化,增加了对拼音的支持。
由于汉语的复杂性,支持拼音比仅仅支持汉字要复杂的多,即使在一些比较大型的搜索引擎上,不完善的地方也随处可见。
1.汉字到拼音映射表:
我们准备了一个基本词表,每个汉字->拼音的映射,词表非常小,只有几K,格式如下:
<拼音,汉字 freq,汉字 freq,汉字 freq>
例如<a 阿 13555 啊 13444 呵 13333......>
2.汉字短语到拼音的转化:
根据1中的映射表,我们可以建立这样一个二维数组:
char PY2HZ[65535][32]={.....}
一维下标表示一个汉字的编码,单个汉字是2字节组成,单个汉字的取值范围刚好在[0,65535],可以直接通过数组下标获取到汉字对应的拼音
3.建立索引:
1)针对用户日志中的keyword,首先转换成拼音
例如:我是中国人,根据每个汉字的编码获取到单个汉字的拼音,汉字直接用"‘"分隔,wo’shi‘zhong’guo‘ren
2)建内存树
以每个字母为一个节点建树,{a~z}{A~Z}最多64颗树,实际上远小于这个数字,一些不可见字符
typdef struct NODE{
char value;
Node *pBrother;
Node *pChild;
char ctag; //-3表示到达一个汉字拼音的结尾,-2表示当前节点的字母是一个声母
DocInfo *pDoc;//指向当前短语对应的文档列表,如果短语没有结束,指针为NULL
}Node,*pNode;
typdef DOCINFO{
int iDocId;
int iFreq;
}DocInfo,*pDocInfo;
结构示意图:“手表”和“手机”的存储结构
4)检索时同样把用户输入的拼音串在树中查找
几个挑战:
1.一字多音,例如阿,可以读a,可以读e,这就导致在二维数组中,对“阿”查找拼音的时候比较麻烦,这里的做法是根据频率选择一个搜索频率比较高的
2.同音短语,比如:手机和收集,对应的拼音都是"shou'ji",这种情况处理起来比较简单,在上面的Node结构中,有一个DocInfo *pDocInfo,以数组的方式记录了拼音对应的所有同音短语
3.简拼,比如:sj,对应的可能是"手机",“收集”,“四级"........这种情况,在上面的Node结构中,有一个ctag=-2标识声母,通过这种方式,可以很好的处理简拼
4.混拼,比如:nuojy,对应的是“诺基亚”,混拼的处理方式和简拼的方式比较类似
5.对于一些英文和拼音的处理,电子商务中包含很多英文名的商品名,如何区分英文和拼音还有简拼、混拼,其实这里的关键在于音节的划分,处理上没有太大的区别
本文介绍了一种基于用户日志的拼音搜索建议系统。该系统能够根据用户输入的拼音部分匹配并推荐最有可能的汉字词组,有效提高了搜索的准确性和用户体验。文章详细描述了系统结构、性能特点以及数据处理流程。
4565

被折叠的 条评论
为什么被折叠?



