Bleve代码阅读(一)——新建索引 (2)

初始化一个indexImpl结构,注意此结构还不是具体的index,而是包含index及其meta数据,还有统计信息的一个结构。

if path != "" { err = rv.meta.Save(path) if err != nil { return nil, err } kvconfig["create_if_missing"] = true kvconfig["error_if_exists"] = true kvconfig["path"] = indexStorePath(path) } else { kvconfig["path"] = "" }

保存索引的meta数据,这个meta数据只是包含了index的具体类型,底层kv存储的具体类型。index的元数据如mapping不在这里保存。

indexTypeConstructor := registry.IndexTypeConstructorByName(rv.meta.IndexType) if indexTypeConstructor == nil { return nil, ErrorUnknownIndexType }

获取index的Constructor,index类型默认是upsitedown。这个Constructor是一个函数,是在upsidedown包的init函数初始化设置的。在bleve/registry/index_type.go文件中定义。

rv.i, err = indexTypeConstructor(rv.meta.Storage, kvconfig, Config.analysisQueue) if err != nil { return nil, err }

调用Index的Constructor,如果是upsidedown,函数是upsidedown.go文件的NewUpsideDownCouch函数。返回一个index.Index接口,如果是upsidedown,则也是UpsideDownCouch结构。

err = rv.i.Open() if err != nil { if err == index.ErrorUnknownStorageType { return nil, ErrorUnknownStorageType } return nil, err }

打开上一步建立的index.Index接口。包括打开kv存储,初始化reader等,具体细节没有往下深究。

mappingBytes, err := json.Marshal(mapping) if err != nil { return nil, err } err = rv.i.SetInternal(mappingInternalKey, mappingBytes) if err != nil { return nil, err }

将indexMapping序列化后保存至刚打开的index。

indexStats.Register(&rv)

注册index的统计信息。

1.3 相关Golang特性说明 1.3.1 init()函数

这里要额外说一下中Config这个变量。通过查找,可以看到Config是一个package内的全局变量。

var Config *configuration

然而这个变量是一个指向configuration结构的指针,它是通过init()函数初始化的。

func init() { bootStart := time.Now() // build the default configuration Config = newConfiguration() // set the default highlighter Config.DefaultHighlighter = html.Name // default kv store Config.DefaultKVStore = "" // default mem only kv store Config.DefaultMemKVStore = gtreap.Name // default index Config.DefaultIndexType = upsidedown.Name bootDuration := time.Since(bootStart) bleveExpVar.Add("bootDuration", int64(bootDuration)) indexStats = NewIndexStats() bleveExpVar.Set("indexes", indexStats) initDisk() }

对于init函数的解释,来自知乎五分钟理解golang的init函数。init()函数是Golang的一个特性,它先于main函数执行。init函数的主要作用:

初始化不能采用初始化表达式初始化的变量。

程序运行前的注册。

实现sync.Once功能。

其他

init函数的主要特点有:

init函数先于main函数自动执行,不能被其他函数调用;

init函数没有输入参数、返回值;

每个包可以有多个init函数;

包的每个源文件也可以有多个init函数,这点比较特殊;

同一个包的init执行顺序,golang没有明确定义,编程时要注意程序不要依赖这个执行顺序。

不同包的init函数按照包导入的依赖关系决定执行顺序。

golang程序初始化:

初始化导入的包(包的初始化顺序并不是按导入顺序(“从上到下”)执行的,runtime需要解析包依赖关系,没有依赖的包最先初始化,与变量初始化依赖关系类似;

初始化包作用域的变量;

执行包的init函数。

1.3.2 struct类型的tag

在1.1节定义中,我们看到定义结构体的每个成员时用到了三个字段,前两个字段是成员变量名和类型,第三个字段就是struct的Tag。

TypeMapping map[string]*DocumentMapping `json:"types,omitempty"` DefaultMapping *DocumentMapping `json:"default_mapping"`

struct的Tag是用双引号或反向单引号括起来的字符串,可以通过reflect包来访问和获取。

// ojb是indexMappingImpl结构的一个实例 t := reflect.TypeOf(obj) for i := 0; i < t.NumField(); i++ { if t.Field(i).CanInterface(){ fmt.Printf("%s %s = %v -tag:%s \n", t.Field(i).Name, t.Field(i).Type, v.Field(i).Interface(), t.Field(i).Tag) } }

在我们的例子中,Tag的内容是json:后跟一个双引号括起来的value列表,这表示json在marshel这个结构体是,对应的成员应该如何处理。json:"default_mapping"这个tag,表示json在marshel这个结构体时,该成员应该以default_mapping为key,unmarshel时遇到default_mapping这个key,也会解码到对应的成员。json:"types,omitempty"第二个参数omitempty的含义是,当该成员为empty值(0、nil等)时忽略该成员。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyzjw.html