- 支持基本的表结构及文档数据插入/更新/删除/批量增删改操作。
- 支持索引维护及查询(遵循最左前缀原则)。
- 支持简单的条件查询与复杂的嵌套查询。
- 支持列表查询(排序+分页)与滚动查询。
- 安装
go get github.com/dpwgc/kv2doc
- 代码示例
package main
import (
"fmt"
"github.com/dpwgc/kv2doc"
)
func main() {
// 新建数据库 demo.db
db, _ := kv2doc.NewDB("demo.db")
// 往 test_table 表中插入2条数据(无需建表,插入数据时会自动建表,同时为每一个字段都建立索引)
_, _ = db.Add("test_table", kv2doc.Doc{
"title": "hello world 1",
"type": "1",
})
id, _ := db.Add("test_table", kv2doc.Doc{
"title": "hello world 2",
"type": "2",
})
// 更新第2条数据,新增一个 color 字段
_ = db.Edit("test_table", id, kv2doc.Doc{
"title": "hello world 2",
"type": "2",
"color": "red",
})
// 查询文档,筛选条件:title 以 hello 为前缀, type 要大于 0 且 存在 color 字段,结果集按主键ID排序后,取前10条返回
// 使用 Eq 或 LeftLike 进行查询时,会走最左前缀索引,其他查询方法走全表扫描
documents, _ := db.Query("test_table").
LeftLike("title", "hello").
Must(kv2doc.Expr().Gt("type", "0").Exist("color")).
Desc("_id").
Limit(0, 10).
List()
// 打印查询结果
for _, v := range documents {
fmt.Println(v.ToJson())
}
// 查看Query执行计划
explain := db.Query("test_table").
LeftLike("title", "hello").
Must(kv2doc.Expr().Gt("type", "0").Exist("color")).
Explain()
// 具体执行逻辑
fmt.Println("expr:", explain.Expr)
// 选择了哪个索引
fmt.Println("index:", explain.Index)
// 删除表
_ = db.Drop("test_table")
}
名称 | 功能 |
---|---|
kv2doc.NewDB | 创建/打开一个数据库 |
kv2doc.ByStore | 创建/打开一个数据库(自定义存储引擎) |
db.Add | 新增文档(表不存在时自动建表) |
db.Edit | 编辑文档 |
db.Delete | 删除文档 |
db.Bulk | 批量操作(增删改) |
db.Drop | 删除表 |
db.Query | 新建查询 |
Query.Eq | 等于 |
Query.Ne | 不等于 |
Query.Gt | 大于 |
Query.Gte | 大于等于 |
Query.Lt | 小于 |
Query.Lte | 小于等于 |
Query.In | 包含 |
Query.NotIn | 不包含 |
Query.Like | 含有 |
Query.LeftLike | 相同前缀 |
Query.RightLike | 相同后缀 |
Query.Exist | 存在 |
Query.NotExist | 不存在 |
Query.Must | 交集语句 |
Query.Should | 并集语句 |
Query.Asc | 正序 |
Query.Desc | 倒序 |
Query.Limit | 分页 |
Query.One | 返回一个文档 |
Query.List | 返回多个文档 |
Query.Count | 返回文档数量 |
Query.Scroll | 滚动查询文档 |
Query.Explain | 查看执行计划 |
{
"_id": "123",
"title": "hello world",
"type": "1",
"color": "red"
}
key | value |
---|---|
f/_id/123/123 | 123 |
f/title/hello world/123 | 123 |
f/type/1/123 | 123 |
f/color/red/123 | 123 |
key | value |
---|---|
p/_id/123 | { "_id": "123", "title": "hello world", "type": "1", "color": "red" } |
-
如果使用了 Eq(等于)、 LeftLike(前缀相同)或者 In(数组内必须要有共同前缀才能走索引),会按最左前缀原则匹配索引
-
例如:执行 LeftLike("title", "hello").Gt("type", "1"),会先利用 BoltDB 的 Cursor 遍历功能扫描所有前缀为 f/title/hello 的 key
-
然后再根据该索引扫描的结果作其他条件筛选(先根据字段索引 value 中的主键 id 找到文档内容,再判断文档中的 type 字段是否大于 1)
- 当全表扫描时,会在 BoltDB 中扫描所有前缀为 p 的 key(即所有存放文档内容的主键 key),然后再根据文档内容逐条匹配
type Store interface {
CreateTable(table string) (err error)
DropTable(table string) (err error)
SetKV(table string, kvs []KV) (err error)
GetKV(table, key string) (kv KV, err error)
ScanKV(table, prefix string, handle func(key string, value []byte) bool) (err error)
NextID(table string) (id string, err error)
}
db := kv2doc.ByStore(rocketStore)
db := kv2doc.ByStore(etcdStore)