APP上線一段時(shí)間有用戶反應(yīng)說不方便找東西,其實(shí)APP的數(shù)據(jù)不大也就三四百條而以,但受限于手機(jī)端展示區(qū)域太小、信息大爆炸,大家也基本上不會去記具體的名稱都是根據(jù)模糊的印象進(jìn)行搜索而且現(xiàn)在大家基本都用拼音搜索經(jīng)常輸不準(zhǔn)確也很正常。所以之前通過關(guān)鍵詞查找的方法不行了,思來想去還是加個(gè)同音詞搜索吧!
由于比較懶所以基本上就想看看有沒有什么現(xiàn)成的解決方案最好是配幾個(gè)API就能搞定的,可以找了一圈沒發(fā)現(xiàn)什么“簡便”的方案,像ElectricSearch、Lucene之類的后端的方案雖然特別牛逼但是一想到還要配置服務(wù)器、集成API啥的腦袋都大。所以還是放棄了!
但在查找的過程中還是有收獲的,無意中發(fā)現(xiàn)PinyinLite這個(gè)項(xiàng)目,這項(xiàng)目太有愛了不僅包小(經(jīng)過最終測試未壓縮版的bundle增加100K左右了)而且?guī)Я艘粋€(gè)模糊查的的示例因此很快就實(shí)現(xiàn)該功能了,具體實(shí)現(xiàn)方案如下:
1、在原有列表數(shù)據(jù)中針對要查找的標(biāo)題增加一個(gè)拼音的字段,標(biāo)題的中文轉(zhuǎn)拼音是在后端MySQL實(shí)現(xiàn)的,具體可以參考:Mysql中文漢字轉(zhuǎn)拼音的實(shí)現(xiàn)(每個(gè)漢字轉(zhuǎn)換全拼)。
[{
"title": "戳爆她們",
"titlePinyin": "chuo bao ta men "
......
}]
2、安裝PinyinLite及其依賴項(xiàng)
npm install pinyinlite --save
npm install lodash --save
npm install string_score ?--save
3、修改一下在React Native里的引用語法
import pinyinlite from 'pinyinlite';
import string_score from 'string_score';
import _ from? 'lodash';
4、根據(jù)參數(shù)進(jìn)行查詢(key為輸入的中文,db.allGames為JSON數(shù)據(jù)反序列化之后的數(shù)組對像)
//將中文拼音數(shù)據(jù)按字符串輸出
var keyPinyin = pinyinlite(key).map(item => {
return item[0] }).join(' ');
//返回帶fuzzy匹配分值的數(shù)組
const scores = db.allGames.map(item => {
return {
data: item,
score: item.titlePinyin.score(keyPinyin)
};})
//篩選數(shù)組獲得結(jié)果,0.3為精度控制可以根據(jù)實(shí)際結(jié)果進(jìn)行調(diào)整
result = scores.filter(i => i.score > 0.3).sort((a, b) => b.score - a.score).map(item => item.data);
運(yùn)行結(jié)果示例:
總結(jié):
開發(fā)過程中最大的震撼是 JS的庫實(shí)在是太豐富了,用簡單的方法實(shí)現(xiàn)同音詞搜索功能,最終使Bundle未壓縮前大了100K左右,執(zhí)行速度查詢大概是20毫秒以內(nèi),因此整個(gè)解決方案是可以接受的。當(dāng)然可能也不是最優(yōu)的解決方案,歡迎留言或郵件cbcye#live.com批評指正!