mirror of
https://shylinux.com/x/icebergs
synced 2025-04-26 01:24:05 +08:00
371 lines
9.8 KiB
Go
371 lines
9.8 KiB
Go
package mdb
|
|
|
|
import (
|
|
"path"
|
|
"strings"
|
|
|
|
ice "github.com/shylinux/icebergs"
|
|
kit "github.com/shylinux/toolkits"
|
|
"github.com/shylinux/toolkits/task"
|
|
|
|
"encoding/csv"
|
|
"encoding/json"
|
|
"os"
|
|
"sort"
|
|
)
|
|
|
|
func _file_name(m *ice.Message, arg ...string) string {
|
|
return kit.Select(path.Join("usr/export", kit.Select(arg[0], arg[0]+"/"+arg[1], arg[1] != ""), arg[2]), arg, 3)
|
|
}
|
|
|
|
func _hash_insert(m *ice.Message, prefix, key string, arg ...string) string {
|
|
m.Log_INSERT("prefix", prefix, arg[0], arg[1])
|
|
return m.Rich(prefix, key, kit.Dict(arg))
|
|
|
|
}
|
|
func _hash_inputs(m *ice.Message, prefix, key string, field, value string) {
|
|
list := map[string]int{}
|
|
m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
|
|
list[kit.Format(val[field])]++
|
|
})
|
|
for k, i := range list {
|
|
m.Push("key", k)
|
|
m.Push("count", i)
|
|
}
|
|
m.Sort("count", "int_r")
|
|
}
|
|
func _hash_modify(m *ice.Message, prefix, key string, field, value string, arg ...string) {
|
|
m.Richs(prefix, key, value, func(key string, value map[string]interface{}) {
|
|
for i := 0; i < len(arg)-1; i += 2 {
|
|
if arg[i] == field {
|
|
continue
|
|
}
|
|
kit.Value(value, arg[i], arg[i+1])
|
|
}
|
|
})
|
|
m.Log_MODIFY("prefix", prefix, field, value, arg)
|
|
}
|
|
func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
|
m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) {
|
|
m.Log_DELETE("prefix", prefix, field, value, "value", kit.Format(val))
|
|
m.Conf(prefix, kit.Keys(chain, kit.MDB_HASH, key), "")
|
|
})
|
|
}
|
|
func _hash_export(m *ice.Message, prefix, key, file string) {
|
|
f, p, e := kit.Create(kit.Keys(file, JSON))
|
|
m.Assert(e)
|
|
defer f.Close()
|
|
|
|
en := json.NewEncoder(f)
|
|
en.SetIndent("", " ")
|
|
en.Encode(m.Confv(prefix, kit.Keys(key, HASH)))
|
|
m.Log_EXPORT(kit.MDB_FILE, p)
|
|
m.Echo(p)
|
|
}
|
|
func _hash_import(m *ice.Message, prefix, key, file string) {
|
|
f, e := os.Open(kit.Keys(file, JSON))
|
|
m.Assert(e)
|
|
defer f.Close()
|
|
|
|
list := map[string]interface{}{}
|
|
de := json.NewDecoder(f)
|
|
de.Decode(&list)
|
|
|
|
if m.Conf(prefix, kit.Keys(key, kit.MDB_META, kit.MDB_SHORT)) == "" {
|
|
m.Conf(prefix, kit.Keys(key, kit.MDB_META, kit.MDB_SHORT), m.Conf(prefix, kit.Keys(kit.MDB_META, kit.MDB_SHORT)))
|
|
}
|
|
|
|
count := 0
|
|
if m.Conf(prefix, kit.Keys(key, kit.MDB_META, kit.MDB_SHORT)) == "" {
|
|
for k, data := range list {
|
|
// 导入数据
|
|
m.Conf(prefix, kit.Keys(key, kit.MDB_HASH, k), data)
|
|
count++
|
|
}
|
|
} else {
|
|
for _, data := range list {
|
|
// 导入数据
|
|
m.Rich(prefix, key, data)
|
|
count++
|
|
}
|
|
}
|
|
|
|
m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count)
|
|
m.Echo(kit.Keys(file, JSON))
|
|
}
|
|
func _hash_select(m *ice.Message, prefix, key, field, value string) {
|
|
fields := strings.Split(kit.Select("time,hash,type,name,text", m.Option("fields")), ",")
|
|
m.Richs(prefix, key, value, func(key string, val map[string]interface{}) {
|
|
if value == kit.MDB_FOREACH {
|
|
m.Push(key, val, fields)
|
|
return
|
|
}
|
|
if field != "" && value != val[field] {
|
|
return
|
|
}
|
|
m.Push("detail", val)
|
|
})
|
|
}
|
|
func _hash_search(m *ice.Message, prefix, key, field, value string) {
|
|
m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
|
|
if field != "" && value != val[field] {
|
|
return
|
|
}
|
|
m.Push(key, value)
|
|
})
|
|
}
|
|
|
|
func _list_insert(m *ice.Message, prefix, key string, arg ...string) int {
|
|
m.Log_INSERT("prefix", prefix, arg[0], arg[1])
|
|
return m.Grow(prefix, key, kit.Dict(arg))
|
|
}
|
|
func _list_modify(m *ice.Message, prefix, key string, field, value string, arg ...string) {
|
|
m.Grows(prefix, key, field, value, func(index int, value map[string]interface{}) {
|
|
for i := 0; i < len(arg)-1; i += 2 {
|
|
if arg[i] == field {
|
|
continue
|
|
}
|
|
kit.Value(value, arg[i], arg[i+1])
|
|
}
|
|
m.Log_MODIFY("prefix", prefix, field, value, kit.Format(arg))
|
|
})
|
|
}
|
|
func _list_delete(m *ice.Message, prefix, chain, field, value string) {
|
|
}
|
|
func _list_export(m *ice.Message, prefix, key, file string) {
|
|
f, p, e := kit.Create(kit.Keys(file, CSV))
|
|
m.Assert(e)
|
|
defer f.Close()
|
|
|
|
w := csv.NewWriter(f)
|
|
defer w.Flush()
|
|
|
|
count := 0
|
|
head := []string{}
|
|
m.Grows(prefix, key, "", "", func(index int, value map[string]interface{}) {
|
|
if index == 0 {
|
|
// 输出表头
|
|
for k := range value {
|
|
head = append(head, k)
|
|
}
|
|
sort.Strings(head)
|
|
w.Write(head)
|
|
}
|
|
|
|
// 输出数据
|
|
data := []string{}
|
|
for _, k := range head {
|
|
data = append(data, kit.Format(value[k]))
|
|
}
|
|
w.Write(data)
|
|
count++
|
|
})
|
|
m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_COUNT, count)
|
|
m.Echo(p)
|
|
}
|
|
func _list_import(m *ice.Message, prefix, key, file string) {
|
|
f, e := os.Open(kit.Keys(file, CSV))
|
|
m.Assert(e)
|
|
defer f.Close()
|
|
|
|
r := csv.NewReader(f)
|
|
|
|
count := 0
|
|
head, _ := r.Read()
|
|
for {
|
|
line, e := r.Read()
|
|
if e != nil {
|
|
break
|
|
}
|
|
|
|
data := kit.Dict()
|
|
for i, k := range head {
|
|
if k == kit.MDB_EXTRA {
|
|
data[k] = kit.UnMarshal(line[i])
|
|
} else {
|
|
data[k] = line[i]
|
|
}
|
|
}
|
|
|
|
// 导入数据
|
|
m.Grow(prefix, key, data)
|
|
count++
|
|
}
|
|
m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count)
|
|
m.Echo(kit.Keys(file, CSV))
|
|
}
|
|
func _list_select(m *ice.Message, prefix, key, field, value string) {
|
|
fields := strings.Split(kit.Select("time,type,name,text", m.Option("fields")), ",")
|
|
m.Grows(prefix, key, field, value, func(index int, value map[string]interface{}) {
|
|
if field == kit.MDB_ID {
|
|
m.Push("detail", value)
|
|
return
|
|
}
|
|
m.Push("", value, fields)
|
|
})
|
|
}
|
|
|
|
func _story_catch(m *ice.Message, kind, file string) {
|
|
m.Cmdy("web.story", "catch", kind, file)
|
|
}
|
|
|
|
func _list_search(m *ice.Message, prefix, key, field, value string) {
|
|
list := []interface{}{}
|
|
files := map[string]bool{}
|
|
m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
|
kit.Fetch(kit.Value(value, "meta.record"), func(index int, value map[string]interface{}) {
|
|
file := value["file"].(string)
|
|
if _, ok := files[file]; ok {
|
|
list = append(list, file)
|
|
} else {
|
|
files[file] = true
|
|
}
|
|
})
|
|
})
|
|
defer m.Cost("search")
|
|
|
|
task.Sync(list, func(task *task.Task, lock *task.Lock) error {
|
|
kit.CSV(kit.Format(task.Arg), 100000, func(index int, line map[string]string, head []string) {
|
|
if line[field] != value {
|
|
return
|
|
}
|
|
|
|
defer lock.WLock()()
|
|
m.Push("", line)
|
|
})
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func _dict_import(m *ice.Message, prefix, key, file string) {
|
|
f, e := os.Open(file)
|
|
m.Assert(e)
|
|
defer _story_catch(m, JSON, file)
|
|
defer f.Close()
|
|
|
|
data := map[string]interface{}{}
|
|
de := json.NewDecoder(f)
|
|
de.Decode(&data)
|
|
|
|
count := 0
|
|
for k, v := range data {
|
|
m.Log_MODIFY(kit.MDB_KEY, kit.Keys(prefix, key), "k", k, "v", v)
|
|
m.Conf(prefix, kit.Keys(key, k), v)
|
|
count++
|
|
}
|
|
m.Log_EXPORT(kit.MDB_FILE, file, kit.MDB_COUNT, count)
|
|
}
|
|
func _dict_export(m *ice.Message, prefix, key, file string) {
|
|
f, p, e := kit.Create(kit.Keys(file, JSON))
|
|
m.Assert(e)
|
|
defer _story_catch(m, JSON, p)
|
|
defer f.Close()
|
|
|
|
en := json.NewEncoder(f)
|
|
en.SetIndent("", " ")
|
|
en.Encode(m.Confv(prefix, kit.Keys(key)))
|
|
m.Log_EXPORT(kit.MDB_FILE, p)
|
|
}
|
|
|
|
const (
|
|
ErrDenyModify = "deny modify "
|
|
)
|
|
const (
|
|
CSV = "csv"
|
|
JSON = "json"
|
|
)
|
|
const (
|
|
DICT = "dict"
|
|
META = "meta"
|
|
HASH = "hash"
|
|
LIST = "list"
|
|
)
|
|
const (
|
|
CREATE = "create"
|
|
RENAME = "rename"
|
|
REMOVE = "remove"
|
|
COMMIT = "commit"
|
|
IMPORT = "import"
|
|
EXPORT = "export"
|
|
|
|
FIELDS = "fields"
|
|
INPUTS = "inputs"
|
|
|
|
INSERT = "insert"
|
|
MODIFY = "modify"
|
|
DELETE = "delete"
|
|
SELECT = "select"
|
|
)
|
|
|
|
var Index = &ice.Context{Name: "mdb", Help: "数据模块",
|
|
Commands: map[string]*ice.Command{
|
|
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
|
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
|
|
|
INSERT: {Name: "insert conf key type arg...", Help: "添加", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch arg[2] {
|
|
case HASH:
|
|
m.Echo(_hash_insert(m, arg[0], arg[1], arg[3:]...))
|
|
case LIST:
|
|
m.Echo("%d", _list_insert(m, arg[0], arg[1], arg[3:]...))
|
|
}
|
|
}},
|
|
MODIFY: {Name: "modify conf key type field value arg...", Help: "编辑", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch arg[2] {
|
|
case HASH:
|
|
_hash_modify(m, arg[0], arg[1], arg[3], arg[4], arg[5:]...)
|
|
case LIST:
|
|
_list_modify(m, arg[0], arg[1], arg[3], arg[4], arg[5:]...)
|
|
}
|
|
}},
|
|
DELETE: {Name: "delete conf key type field value arg...", Help: "删除", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch arg[2] {
|
|
case HASH:
|
|
_hash_delete(m, arg[0], arg[1], arg[3], arg[4])
|
|
case LIST:
|
|
_list_delete(m, arg[0], arg[1], arg[3], arg[4])
|
|
}
|
|
}},
|
|
SELECT: {Name: "select conf key type field value", Help: "数据查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch arg[2] {
|
|
case HASH:
|
|
_hash_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select(kit.MDB_FOREACH, arg, 4))
|
|
case LIST:
|
|
_list_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select("", arg, 4))
|
|
}
|
|
}},
|
|
EXPORT: {Name: "export conf key type [name]", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch file := _file_name(m, arg...); arg[2] {
|
|
case HASH:
|
|
_hash_export(m, arg[0], arg[1], file)
|
|
case LIST:
|
|
_list_export(m, arg[0], arg[1], file)
|
|
}
|
|
}},
|
|
IMPORT: {Name: "import conf key type file", Help: "导入数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch file := _file_name(m, arg...); arg[2] {
|
|
case HASH:
|
|
_hash_import(m, arg[0], arg[1], file)
|
|
case LIST:
|
|
_list_import(m, arg[0], arg[1], file)
|
|
}
|
|
}},
|
|
INPUTS: {Name: "inputs conf key type field value", Help: "输入补全", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
switch arg[2] {
|
|
case HASH:
|
|
_hash_inputs(m, arg[0], arg[1], arg[3], kit.Select("", arg, 4))
|
|
case LIST:
|
|
}
|
|
}},
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
ice.Index.Register(Index, nil,
|
|
IMPORT, EXPORT, SELECT,
|
|
PLUGIN, ENGINE, SEARCH, RENDER,
|
|
INSERT, MODIFY, DELETE,
|
|
INPUTS,
|
|
)
|
|
}
|