<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Go語言實戰 - 我需要站內搜索

      山坡網的用戶抱怨“為什么搜索‘二鬼子李富貴’找不到‘二鬼子漢奸李富貴’?我用百度搜都能找到。”

      當時我就滴汗了,用戶說的有道理,應該要能搜索到。

      之前的方案很簡單,用戶輸入的字串會在數據庫里做正則表達式匹配,以便用“二鬼子”能搜到“二鬼子漢奸李富貴”。事實證明,我想當然了,即便是這么簡單的一個書名搜索,也不能馬虎。

      那就來分析一下怎么做吧,即便不是專業做搜索的,思路上也可以先YY一下。按照本能,先把問題大而化小。

      1. 先把搜索字符串進行中文分詞

      2. 用詞組在數據庫里做 or 包含匹配。

      3. 搜索出來的結果按與搜索條件相關度排序。

      看起來也不難(玩笑話,每一條水都很深),一條一條來解決。

      1. 中文分詞。

      我找了一下,免費的不多,選擇了盤古分詞Go語言Port。從Github看到,代碼是四個月以前的了,字典文件有些老。所以我在盤古網站上下載了最新的字典,測試了一下Go的代碼,運行結果良好。

      這個Port可能蠻久沒有更新過,代碼的結構不能直接go get,需要自己下載src里面的segment文件夾出來使用。

      我把新的字典文件全都放到了revel app的conf文件夾里,如下圖所示。

      image

      然后在Controller.Init方法里加上初始化代碼。

      revel.OnAppStart(func() {
         segHandler = segment.NewSegment()
         err := segHandler.Init(path.Join(revel.ConfPaths[0], "dicts"))
         if err != nil {
           glog.Fatalln("Failed to init segment handler", err)
         }

      然后在需要的地方就可以開始用它分詞了。

      //對搜索的字符串進行分詞
      searchKey := "(" + key + "|"

      segs := segHandler.DoSegment(key)
      for cur := segs.Front(); cur != nil; cur = cur.Next() {
        word := cur.Value.(*dict.WordInfo)
        if word.Word != "的" {
          searchKey += word.Word + "|"
        }
      }

      searchKey = strings.TrimRight(searchKey, "|") + ")"

      searchResults, pageSum, err := d.findBookBy(M{"$or": []M{
        M{"title": M{"$regex": searchKey}},
        M{"author": M{"$regex": key}},
        M{"category": M{"$regex": key}}}}, "-score", pageNum, numPerPage)
      if err != nil {
        return nil, pageSum, err
      }

      思路是把搜索條件分成詞組,再組合成正則表達式,比如“二鬼子李富貴”變成“(二|鬼子|李富貴)”,然后使用mongodb的正則查詢。

      這里我把“的”字去掉了,因為中文里面“的”字用的太多了,基本沒有查詢價值。

      2. 搜索出來的結果按與搜索條件相關度排序。

      搜索引擎里,這部分是技術含量最大的。我這邊只是牛刀小試,所以方案簡單很多,把搜索出來的書籍標題與搜索條件比對相似度。

      正好,字符串比對相似度的庫我之前Port過一個,叫做simhash(當時為什么port我都忘了,哈,工具箱里東西多還是有好處的?。?。算法具體就不多說了,免得跑題??从梅ò?。

      needle := "Reading bytes into structs using reflection"
      hayStack := "Golang - mapping an variable length array to a struct"
      
      likeness := GetLikenessValue(needle, hayStack)
      fmt.Println("Likeness:", likeness)
      就一個函數,輸入兩個字符串,輸出一個從0到1的浮點數,代表相似百分比。
      為了方便計算,我在SearchResult結構中加入了一個新的字段,OriginalQueryString,存儲原始搜索條件,之后實現一下Sort接口。

      type SearchResult struct {
        Id                bson.ObjectId "_id"
        Title             string
        OriginQueryString string //原始的搜索條件,用于排序
      }

      type SearchResults []SearchResult

      func (srs SearchResults) Len() int {
        return len(srs)
      }

      func (srs SearchResults) Less(i, j int) bool {
        likenessI := simhash.GetLikenessValue(srs[i].Title, srs[i].OriginQueryString)
        likenessJ := simhash.GetLikenessValue(srs[j].Title, srs[j].OriginQueryString)

        return likenessI < likenessJ
      }

      func (srs SearchResults) Swap(i, j int) {
        srs[i], srs[j] = srs[j], srs[i]
      }

      就可以在搜索出來之后按照相關性排序了。

      //為searchResult的OriginQueryString賦值,以便按照搜索相關性排序
      for i, _ := range searchResults {
        searchResults[i].OriginQueryString = key
      }

      sort.Sort(sort.Reverse(SearchResults(searchResults)))

      我的實現到這里就完成了。

      但其實有一部分很重要的東西我取巧了。由于使用模糊搜索,結果集的大小是無法預料的,全部取的話隨時可能把內存用完。分批的話怎么保證相關性排序的準確性呢?好問題,這里是非常關鍵又很難做的部分,我取巧的方式是把書籍按評分排序,然后取前20個出來,僅僅在這20本書中做相似度排序。這并不是完美的方案,僅僅只是夠用。

      后期如果有時間,可以用mongodb的游標做一個即省內存又靠譜的實現。

      posted @ 2013-09-23 18:10  AllenDang  閱讀(2911)  評論(16)    收藏  舉報
      主站蜘蛛池模板: 国产性色的免费视频网站| 久久精品国产一区二区三| 中文字幕在线精品人妻| 内射老阿姨1区2区3区4区| 国产成人AV大片大片在线播放| 亚洲熟女精品一区二区| 亚洲精品日韩中文字幕| 亚洲无线码一区二区三区| 精品人妻一区二区三区蜜臀| 中文字幕亚洲精品人妻| 亚洲精品国产综合麻豆久久99| 中国熟妇牲交视频| 亚洲国产精品一二三四五| 国产超高清麻豆精品传媒麻豆精品| 国产成人综合色就色综合| 国产果冻豆传媒麻婆精东 | 国产第一页浮力影院入口| 丁香五月婷激情综合第九色| 亚洲高清国产自产拍av| 中文字幕 欧美日韩| 成人免费在线播放av| 国产综合精品一区二区三区| 日韩精品中文字一区二区| 鄂尔多斯市| 亚洲成色精品一二三区| 国产99视频精品免费视频76| 亚洲AV成人无码精品电影在线| 成人av专区精品无码国产| 熟女少妇精品一区二区| 人妻无码中文专区久久app| 性色av无码久久一区二区三区| 亚洲国产中文字幕在线视频综合 | 精品国产亚洲午夜精品a| 97人妻蜜臀中文字幕| 加勒比久久综合网天天| 护士的小嫩嫩好紧好爽| 日韩午夜一区二区福利视频| 精品国产成人国产在线观看| 国产日韩一区二区在线| 日韩亚洲精品国产第二页| 欧美日韩v|