CAE开发日志(2):搜索功能

1、CAE的搜索功能

因为一个call表对应了一首歌,当一个歌手的call表多起来的时候,歌曲的数目也会增多,此时用户就不能简单地通过“查看全部歌曲”来找出自己想要的call表,所以就需要引入搜索功能,但是搜索这个问题实际上还是要看用户群体的习惯性,而且call表都是日文/英文为主,用户的习惯并不能很好地预测。下面是我从一开始到现在对CAE的搜索功能的一些思考历程。


2、使用搜索引擎

一开始我是打算使用搜索引擎,具体来说是准备使用Lucene去实现的,到现在为止CAE的后台lib包中仍然保留了Lucene的jar包。

Lucene的基本功能的jar包就是lucene-analyzers-common-5.4.0.jar、lucene-core-5.4.0.jar、lucene-queryparser-5.4.0.jar,而多出来的lucene-analyzers-kuromoji-5.4.0.jar是Lucene自带的日文检索包。

我一开始的想法是,用户自己也不知道自己会搜些什么东西,可能是歌名,可能是歌手,可能是发售日期,甚至可能是歌词。歌名、歌手、发售日期这种都是简单的情况,因为可以直接使用sql查询就可以完成,但是歌词却并非如此,如果要支持对歌词的搜索的话就说明要支持全文检索,那就不得不用到Lucene了。总之,后台需要把用户的关键词所能联系到的所有可能性都返回给用户。

说到日文分词,就要简单地介绍一下kuromoji,kuromoji本来是一个独立的专用于日语的全文检索包,只是后来它被捐给了Lucene,现在它是Lucene默认自带的日文检索包。

一开始我还希望让歌名也加入全文检索的行列,因为我不希望使用sql的LIKE来进行歌名的模糊查询,所以既然歌词都使用了kuromoji,那歌名也搭一个顺风车吧。但是使用kuromoji其实并没有完全解决全文检索的问题,因为无论是歌名还是歌词,都不一定是纯日文的!因为有可能出现英文甚至是全英文的情况(例如Guilty Fever Eyes),我测试过使用kuromoji去对英文歌名进行分词,但是结果是,kuromoji根本就不会识别英文,所以分词也是失败的,检索自然也是失败的。

后来,我想到了一个权宜之计,在save动作前,先对歌名进行一次判断,判断它是哪种情况(纯英文/英文+日文/日文),这个判断抽出来封装成一个方法,下面将这段代码分享出来:

	//日文的unicode集合
	private Set<Character.UnicodeBlock> japaneseUnicodeBlocks = new HashSet<Character.UnicodeBlock>(){{
		add(Character.UnicodeBlock.HIRAGANA);
		add(Character.UnicodeBlock.KATAKANA);
		add(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS);
	}};
	//判断一个字符串是英文还是日文
	private boolean enOrJp(String word){
		//先把字符串的特殊字符用正则消去,然后再判断是否纯英文
		boolean result=word.replaceAll("[^a-zA-Z_\u2E80-\uFE4F]", "").matches("^[a-zA-z]*");
		//如果是纯英文则返回true
		if(result){
			return result;
		}
		//如果不是纯英文则判断是否有日文,对每个字符进行轮询,一旦出现有日文则认为该字符串是日文并返回false
		for (char c : word.toCharArray()){
			if (japaneseUnicodeBlocks.contains(Character.UnicodeBlock.of(c))){
				result=false;
				break;
			}
		}
		return result;
	}

首先使用正则表达式,将字符串的一些特殊字符,如空格、☆等去掉,因为这些会对之后的判断造成误判。

然后再用正则表达式判断处理后的字符串是不是纯英文,如果是则返回,此时这段字符串就不会交给kuromoji去处理,而是交给Lucene默认的Analysis,也就是StandardAnalyzer去进行分词。

如果不是纯英文,那就开始判断是否包含了日文,这里把字符串变成一个char[]并且进行了遍历,对每一个字符都是用japaneseUnicodeBlocks变量去判断这个字符的unicode码是否在标准日文的unicode码的范围之中,如果是,则表示当前字符是日文,跳出循环。

japaneseUnicodeBlocks这个变量是一个日文的unicode码的set,可以看到初始化时它add了三个记录,第一个“HIRAGANA”代表平假名,第二个“KARAHANA”表示片假名,第三个“CJK_UNIFIED_IDEOGRAPHS”代表的是中国(China)、日本(Japanese)、韩国(Korea)三国的共用unicode码集合,这三个记录的并集就能包含所有日语的情况。

可以看到,上面的这种算法只是非常简陋的,中心思想就是“一旦出现日文,就无视英文的部分交给kuromoji来完成”,后续可以继续改良,可以按照比例来进行判断,例如50%以上是日文才交给kuromoji来分词。

当然,个人认为最根本的解决方法就是自己写一个分词器,但是我对分词器并不是很熟,而且算法也是一窍不通,这里我认为还是交给后人来完善好了,而且最好使用C++来写会更好(以后的后台也不能清一色的Java呀,要考虑多方面多语言发展,尽量发挥各种语言的优势,培养更多方向的人才)。


3、使用tag

采用搜索引擎来做还是太复杂了,而且用户也不一定会搜索歌名、歌词,我认为更有可能会搜索的是和正式的歌曲信息完全无关的关键词,例如假如用户想搜索“太陽を追いかけろ!”,用户不会真的把“太陽”这个日文输进去,也不会搜索歌词(可能他也记不住歌词),而更有可能会输入像“bd7”这样的关键词。

问题是,“bd7”这个关键词相当于是水水人们私底下这么喊的而已,并不是正式的歌曲信息,而且可能哪一天这个称呼就改了,而机器是不懂人类的潮流的,所以简单地使用sql已经无法解决问题,这时,我想到了B站的tag系统。

只要让用户自己编辑tag系统不就完了吗?让用户自己投票产生他们想要的tag,这些tag可以随着时间的推移或者对用户行为的监测分析而删除,这样不就可以达到需求了吗?我认为tag系统是一个非常好的想法,而且实现起来并不困难,在未来还可以让后台去收集用户行为,然后对用户行为进行分析甚至是预判,让系统自己也生成热门的tag,这就扯到nosql、数据分析、数据挖掘甚至是机器学习了,但是我觉得作为未来的一个CAE的发展方向来说,是一个不错的选择。


4、现况

后来我的同伴跟我说,既然大家装了这个app,那就表示大家都有一定的基础的,而且也不会出现搜歌词的需求,歌名也会好好地打上日文的,tag系统看起来很复杂的样子所以就不需要了,简单一点就行。

所以目前CAE还是使用sql的LIKE来完成搜索的功能的。。但是万一以后对搜索功能提出了更严格的要求时,我觉得搜索引擎和tag系统的开发就可以提上日程了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值