IT技术博客大学习 共学习 共进步

音乐搜索的极致

福林雨-博客 2009-11-16 23:21:51 浏览 4,044 次

    12530 PC客户端 咪咕 (页面最下方有一个很不显眼的下载链接) 搜索 原本计划是今天上线内测,20号正是随资源库后台一起上线,其实昨晚就已经替换掉了正式服务器上原来的接口。正因为昨晚悄无声息的上线,原本已经下班走到家门口的我们,又被电话叫回公司,来解决一个刚刚发现的bug。

    音乐搜索,第一期还没有特别做歌词的搜索,只对歌手名,歌曲名,专辑名做优化,加上数据量本身就很小(一共才不到100万首歌),只好在查询上做文章。我们当前一共设置了十层查询 Query:

1。精确匹配:歌手,歌曲,专辑,不分词字段,去掉前后多余空格,精确匹配

    2。过滤后的精确匹配:歌手,歌曲,专辑,过滤字段,去掉所有特殊字符,英文转成小写,精确匹配

    3。拼音全量匹配:歌手,歌曲,专辑,拼音全量字段,去掉所有非英文字符,英文转成小写,精确匹配

    4。同音纠错匹配:歌手,歌曲,专辑,拼音全量字段,只对含中文的搜索词使用,中文转拼音,英文转小写,去掉所有特殊字符,精确匹配

    5。拼音首字母匹配:歌手,拼音首字母字段,中文转拼音首字母,英文转小写,去掉所有特殊字符,精确匹配

    6。前缀匹配:歌手,歌曲,专辑,不分词字段,去掉前后多余空格,英文转小写,前缀匹配

    7。分词Must匹配:歌手,歌曲,专辑,(歌词),分词字段,分词,词之间使用Must连接,分词匹配

    8。分词Should匹配:歌手,歌曲,专辑,(歌词),分词字段,分词,词之间使用Should连接,分词匹配

    9。合并分词匹配:歌手+歌曲+专辑 分词字段,分词,(当前使用 Should 连接),分词匹配

    10。模糊匹配:歌手,歌曲,专辑,分词字段,去掉前后多余空格,英文转小写,模糊匹配, 包含中文时模糊度:0.65 全英文模糊度:0.85

    其中模糊匹配还分了两级:

a 拼音纠错

    b 模糊查询,包括中文模糊和英文模糊(模糊度不一样)

    当前拼音模糊是使用组合的办法来实现的:

1。建索引的时候,拼音全量字段里建的是字段的准确拼音,包括多音字的组合

    2。搜索的时候,将用户输入的关键词转成拼音,在拼音全量字段里搜

    3。模糊的时候,将用户输入关键词转成的拼音,按照模糊规则:n-l 互换,zh-z, ch-c, sh-s 互换,an-ang, en-eng, in-ing, on-ong 互换,每次只换一个(当前只支持模糊度为1的拼音模糊查询),如果有多个可以替换的点,则返回的结果为一个数组组合,然后使用 精确匹配在拼音全量字段进行查询

    还有一种做法:

首先定义个所谓的拼音标准化过程:

    n->l,zh->z, ch->c, sh->s ,an->ang, en->eng, in->ing, on->ong 不是互换,而是单向替换。

    将一个拼音串的所有可替换点都替换后,得到的一个串,称为标准化串。

    1。建索引的时候,歌曲名,歌手名,专辑名各新增一个标准化串字段,按","分词(多音字),存储字段的拼音标准化串

    2。搜索的时候,将用户输入的关键词转成拼音,在拼音全量里面搜索

    3。模糊的时候,将用户输入关键词的拼音再转成标准化串,在标准化串字段里面搜索

    优点:不同那么复杂的组合逻辑

    缺点:无法控制模糊度

    拼一个很大的 Query 去 Lucene 里面查询最大的问题就是,排序很难控制。不停的查看 Lucene Explain 出来的打分细节,再微调 Query 之间的 boost 权值,再查看打分细节,再微调。特别是分词命中这个 Query ,Lucene 分词命中的默认打分规则,总觉得不太满意。自己做了一个 Similarity 的子类来算分,可毕竟不是专业的,考虑的不够全面,解决了一个问题,副作用带来更多的问题。最后,还是不得不放弃这个方向的尝试。

    拼一个大 Query 的一个意外收获就是,发现 Lucene 2.9.0 的一个 bug:LUCENE-1974,提到官方 JIRA 后,很快被确认,并修复了,并且我提交的 TestCase 也被将接纳到 Lucene 的测试用例集合中。可惜 2.9.1 出来前,我们还是不得不将项目切换回 2.4.1 , 以避免这个 bug。

    现在使用的 IK 分词器,总觉得行为有些奇怪,又没有什么地方可以设置的。天龙八部,最多分词分出来“天”,“八”是我们不想要的,最长分词,又分不出“天龙”,真是郁闷。

    因为 Query 太复杂,Lucene 自带的标红效果不是很令人满意,所以标红的部分也是完全自己做的。仿照 Query 的模式,定义了一系列的规则,如全量命中,拼音命中,分词命中等,记录下每种规则匹配到的区段,最后做一次归并就可以了。

    关键词提示,即用户在搜索框里输入的同时,下拉一个提示列表。现在的做法是建了一个单独的关键词索引,用户输入的时候,使用前缀去匹配。中文的 Trie 树比英文复杂不少,所以最开始没有选它。但现在发现关键词索引太大了,Lucene 更新太慢,才后悔最初的选型失误。关键词里面需要保存词频的信息,搜索量的信息,所以以后的更新肯定也会不少。明天继续想办法解决这个问题。

    做完这个项目以后,大约所有的搜索功能,都不会让我觉得害怕了吧。

建议继续学习

  1. 怎样用好Google进行搜索 (阅读 15,664)
  2. 淘宝搜索:定向抓取网页技术漫谈 (阅读 9,364)
  3. 简析搜索引擎中网络爬虫的搜索策略 (阅读 7,287)
  4. 几种常见的基于Lucene的开源搜索解决方案对比 (阅读 5,984)
  5. 基于用户行为分析的搜索引擎自动性能评价 (阅读 5,605)
  6. 百度搜索URL参数解析 (阅读 5,581)
  7. 用Sphinx快速搭建站内搜索功能 (阅读 5,569)
  8. php实现百度音乐采集下载 (阅读 5,404)
  9. Xapian搜索体系结构 (阅读 5,164)
  10. 附近地点搜索初探 (阅读 5,146)