前面说过,接收indexerRequest的代码在index_worker.go里:

func (engine *Engine) indexerAddDocumentWorker(shard int) {
for {
request := <-engine.indexerAddDocumentChannels[shard] //关键
addInvertedIndex := engine.indexers[shard].AddDocument(request.document, request.dealDocInfoChan) // 向反向索引表(数组)中加入一个文档
// save
if engine.initOptions.UsePersistentStorage {
for k, v := range addInvertedIndex {
engine.persistentStorageIndexDocumentChannels[shard] <- persistentStorageIndexDocumentRequest{
typ: "index",
keyword: k,
keywordIndices: v,
}
}
} atomic.AddUint64(&engine.numTokenIndexAdded,
uint64(len(request.document.Keywords)))
atomic.AddUint64(&engine.numDocumentsIndexed, )
}

持久化的代码:engine/persistent_storage_worker.go

package engine

import (
"bytes"
"encoding/binary"
"encoding/gob"
"github.com/huichen/wukong/core"
"github.com/huichen/wukong/types"
"sync"
"sync/atomic"
) type persistentStorageIndexDocumentRequest struct {
typ string //"info"or"index" // typ=="info"时,以下两个字段有效
docId uint64
docInfo *types.DocInfo // typ=="index"时,以下两个字段有效
keyword string
keywordIndices *types.KeywordIndices
} func (engine *Engine) persistentStorageIndexDocumentWorker(shard int) {
for {
request := <-engine.persistentStorageIndexDocumentChannels[shard]
switch request.typ {
case "info":
// 得到key
b := make([]byte, )
length := binary.PutUvarint(b, request.docId) // 得到value
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(request.docInfo)
if err != nil {
atomic.AddUint64(&engine.numDocumentsStored, )
return
} // 将key-value写入数据库
engine.dbs[shard][getDB(request.typ)].Set(b[:length], buf.Bytes())
atomic.AddUint64(&engine.numDocumentsStored, ) case "index":
// 得到key
b := []byte(request.keyword) // 得到value
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(request.keywordIndices)
if err != nil {
return
} // 将key-value写入数据库
engine.dbs[shard][getDB(request.typ)].Set(b, buf.Bytes())
}
}
} func (engine *Engine) persistentStorageRemoveDocumentWorker(docId uint64, shard int) {
// 得到key
b := make([]byte, )
length := binary.PutUvarint(b, docId) // 从数据库删除该key
engine.dbs[shard][getDB("info")].Delete(b[:length])
} func (engine *Engine) persistentStorageInitWorker(shard int) {
var finish sync.WaitGroup
finish.Add()
// 恢复docInfo
go func() {
defer finish.Add(-)
engine.dbs[shard][getDB("info")].ForEach(func(k, v []byte) error {
key, value := k, v
// 得到docID
docId, _ := binary.Uvarint(key) // 得到data
buf := bytes.NewReader(value)
dec := gob.NewDecoder(buf)
var data types.DocInfo
err := dec.Decode(&data)
if err == nil {
// 添加索引
core.AddDocInfo(shard, docId, &data)
}
return nil
})
}() // 恢复invertedIndex
go func() {
defer finish.Add(-)
engine.dbs[shard][getDB("index")].ForEach(func(k, v []byte) error {
key, value := k, v
// 得到keyword
keyword := string(key) // 得到data
buf := bytes.NewReader(value)
dec := gob.NewDecoder(buf)
var data types.KeywordIndices
err := dec.Decode(&data)
if err == nil {
// 添加索引
core.AddKeywordIndices(shard, keyword, &data)
}
return nil
})
}()
finish.Wait()
engine.persistentStorageInitChannel <- true
}

可以看到,倒排索引存在DB里是丑陋的,直接set(key, value) 其中,key是倒排列表的关键字,而value是doc id list也就是数组。

如果索引比较多,每次去DB set是非常耗时的,尤其针对同一个keyword有doc id插入时!

总之,wukong对于持久化的做法很丑陋!

wukong引擎源码分析之索引——part 2 持久化 直接set(key,docID数组)在kv存储里的更多相关文章

  1. wukong引擎源码分析之索引——part 1 倒排列表本质是有序数组存储

    searcher.IndexDocument(0, types.DocumentIndexData{Content: "此次百度收购将成中国互联网最大并购"}) engine.go ...

  2. wukong引擎源码分析之索引——part 3 文档评分 无非就是将docid对应的fields信息存储起来,为搜索结果rank评分用

    之前的文章分析过,接受索引请求处理的代码在segmenter_worker.go里: func (engine *Engine) segmenterWorker() { for { request : ...

  3. wukong引擎源码分析之搜索——docid有序的数组里二分归并求交集,如果用跳表的话,在插入索引时会更快

    searcher.Search(types.SearchRequest{Text: "百度中国"}) // 查找满足搜索条件的文档,此函数线程安全 func (engine *En ...

  4. Spark源码分析 – 汇总索引

    http://jerryshao.me/categories.html#architecture-ref http://blog.csdn.net/pelick/article/details/172 ...

  5. bleve搜索引擎源码分析之索引——mapping真复杂啊

    接下来看看下面index部分的源码实现: data := struct { Name string Des string }{ Name: "hello world this is bone ...

  6. 转:Irrlicht 0.1引擎源码分析与研究(一)

    目录(?)[-] 主要技术特性 引擎概览 Irrlicht的窗口管理   Irrlicht引擎主要是由一个名叫Nikolaus Gebhardt奥地利人所设计,是sourceforge上的一个开源项目 ...

  7. lua源码分析 伪索引

    Lua 提供了一个 注册表, 这是一个预定义出来的表, 可以用来保存任何 C 代码想保存的 Lua 值. 这个表可以用有效伪索引 LUA_REGISTRYINDEX 来定位. 任何 C 库都可以在这张 ...

  8. bleve搜索引擎源码分析之索引——mapping和lucene一样,也有_all

    例子: package main import ( "fmt" "github.com/blevesearch/bleve" ) func main() { / ...

  9. 4 weekend110的textinputformat对切片规划的源码分析 + 倒排索引的mr实现 + 多个job在同一个main方法中提交

    好的,现在,来weekend110的textinputformat对切片规划的源码分析, Inputformat默认是textinputformat,一通百通. 这就是今天,weekend110的te ...

随机推荐

  1. R语言入门视频笔记--8--数据框

    一.数据框 使用data.frame函数生成数据框 x <- c(20122014101:20122014128) y <- rnorm(28,85,18) #生成28个平均数为85,方差 ...

  2. HUNAN -11566 Graduation Examination(找规律)

    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11566&courseid=0 输入n,求出第n个fi ...

  3. Centos7 下安装 RabbitMQ

    安装 erlang 1.下载erlang 官网地址 http://www.erlang.org/download 挑选合适的版本 然后 wget 比如目前最新版本 19.3 运行命令 wget htt ...

  4. intellij idea springmvc web工程之helloworld

    1.新建java工程 2.设置项目 2.添加jar包 3.配置web.xml <?xml version="1.0" encoding="UTF-8"?& ...

  5. uibutton去掉点击后背景有阴影的方法

    1,将normal和highlight两种方式都设置上图片即可 UIButton *goback = [[UIButton alloc]initWithFrame:CGRectMake(5.0f, 5 ...

  6. Go -- 交叉编译

    编译Windows程序和mac程序

  7. 删除DataGridView选中行并更新数据库

    前面写过一篇文章是DataGridView控件显示数据的,DataGridView在与数据库打交道时会常常出现,也非常有用.通过DataGridView对数据库进行更改和查询都比較方便. 这里我们须要 ...

  8. binary-tree-postorder-traversal——二叉树后续遍历

    Given a binary tree, return the postorder traversal of its nodes' values. For example:Given binary t ...

  9. Using Virtual Serial Ports on Linux (Ubuntu)

    http://www.xappsoftware.com/wordpress/2013/10/07/using-virtual-serial-ports-on-linux-ubuntu/?goback= ...

  10. HDU 1114 Piggy-Bank (完全背包)

    Piggy-Bank Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...