Compare commits
4 Commits
76b132a8b7
...
0d998482cd
Author | SHA1 | Date |
---|---|---|
|
0d998482cd | |
|
eff399c4e4 | |
|
fd28639f17 | |
|
00ec4fd001 |
|
@ -1,10 +1,12 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"git.pyer.club/kingecg/godocdb/document"
|
||||
"git.pyer.club/kingecg/godocdb/index" // "fmt"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// "go.mongodb.org/mongo-driver/bson"
|
||||
|
@ -44,9 +46,18 @@ func NewCollection(name string, storagePath string) (*Collection, error) {
|
|||
func (coll *Collection) InsertOne(doc interface{}) error {
|
||||
// 自动生成文档ID
|
||||
// docID := generateID()
|
||||
docMap, ok := doc.(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("document must be a map[string]interface{}")
|
||||
}
|
||||
docID, exists := docMap["_id"].(primitive.ObjectID)
|
||||
if !exists {
|
||||
docID = primitive.NewObjectID()
|
||||
docMap["_id"] = docID
|
||||
}
|
||||
|
||||
// 将collection信息传递给文档管理层和索引管理层
|
||||
if err := coll.documentStore.StoreDocument(coll.name, "", doc); err != nil {
|
||||
if err := coll.documentStore.StoreDocument(coll.name, docID.String(), doc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package api
|
||||
|
||||
import "git.pyer.club/kingecg/godocdb/index"
|
||||
|
||||
type Index struct {
|
||||
metadata index.IndexMetadata
|
||||
store *index.IndexStore
|
||||
}
|
|
@ -32,7 +32,7 @@ func NewDocumentStore(storeName string) (*DocumentStore, error) {
|
|||
storage.Close()
|
||||
return nil, fmt.Errorf("failed to create index store: %v", err)
|
||||
}
|
||||
if errCreate := is.CreateIndex("default_index", index.NonUnique, []string{"_id"}, []index.IndexSortOrder{index.Ascending}); errCreate != nil {
|
||||
if _, errCreate := is.CreateIndex("default_index", index.NonUnique, []string{"_id"}, []index.IndexSortOrder{index.Ascending}); errCreate != nil {
|
||||
return nil, errCreate
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ func (ds *DocumentStore) StoreDocument(collection string, id string, doc interfa
|
|||
// 创建默认索引(如果不存在)
|
||||
if _, err := ds.indexStore.GetIndexMetadata("default_index"); err != nil {
|
||||
// 如果索引不存在,创建默认索引
|
||||
if errCreate := ds.indexStore.CreateIndex("default_index", index.NonUnique, []string{"_id"}, nil); errCreate != nil {
|
||||
if _, errCreate := ds.indexStore.CreateIndex("default_index", index.NonUnique, []string{"_id"}, nil); errCreate != nil {
|
||||
return errCreate
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,13 +62,13 @@ func NewIndexStore(storeName string) (*IndexStore, error) {
|
|||
}
|
||||
|
||||
// CreateIndex 创建索引
|
||||
func (is *IndexStore) CreateIndex(indexName string, indexType IndexType, keyFields []string, sortOrders []IndexSortOrder) error {
|
||||
func (is *IndexStore) CreateIndex(indexName string, indexType IndexType, keyFields []string, sortOrders []IndexSortOrder) (*IndexMetadata, error) {
|
||||
is.mu.Lock()
|
||||
defer is.mu.Unlock()
|
||||
|
||||
// 验证keyFields和sortOrders长度一致
|
||||
if len(keyFields) != len(sortOrders) {
|
||||
return fmt.Errorf("keyFields and sortOrders must have the same length")
|
||||
return nil, fmt.Errorf("keyFields and sortOrders must have the same length")
|
||||
}
|
||||
|
||||
// 存储索引元数据
|
||||
|
@ -82,25 +82,26 @@ func (is *IndexStore) CreateIndex(indexName string, indexType IndexType, keyFiel
|
|||
|
||||
data, err := bson.Marshal(metadata)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal index metadata: %v", err)
|
||||
return nil, fmt.Errorf("failed to marshal index metadata: %v", err)
|
||||
}
|
||||
|
||||
key := []byte(fmt.Sprintf("indexes:metadata:%s", indexName))
|
||||
if err := is.storage.Put(key, data); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
return &metadata, nil
|
||||
|
||||
// 初始化索引结构
|
||||
index := make(map[string]string)
|
||||
// // 初始化索引结构
|
||||
// index := make(map[string]string)
|
||||
|
||||
// 存储初始索引结构
|
||||
indexKey := fmt.Sprintf("indexes:data:%s", indexName)
|
||||
indexData, err := bson.Marshal(index)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal index data: %v", err)
|
||||
}
|
||||
// // 存储初始索引结构
|
||||
// indexKey := fmt.Sprintf("indexes:data:%s", indexName)
|
||||
// indexData, err := bson.Marshal(index)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to marshal index data: %v", err)
|
||||
// }
|
||||
|
||||
return is.storage.Put([]byte(indexKey), indexData)
|
||||
// return is.storage.Put([]byte(indexKey), indexData)
|
||||
}
|
||||
|
||||
// UpdateIndex 在指定collection下更新索引
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestIndexStore(t *testing.T) {
|
|||
keyFields := []string{"name"}
|
||||
|
||||
// 测试创建索引(默认升序)
|
||||
if err := is.CreateIndex(indexName, NonUnique, keyFields, []IndexSortOrder{Ascending}); err != nil {
|
||||
if _, err := is.CreateIndex(indexName, NonUnique, keyFields, []IndexSortOrder{Ascending}); err != nil {
|
||||
t.Errorf("CreateIndex failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ func TestCompositeIndex(t *testing.T) {
|
|||
keyFields := []string{"name", "age"}
|
||||
|
||||
// 创建复合索引(默认升序)
|
||||
if err := is.CreateIndex(indexName, NonUnique, keyFields, []IndexSortOrder{Ascending, Ascending}); err != nil {
|
||||
if _, err := is.CreateIndex(indexName, NonUnique, keyFields, []IndexSortOrder{Ascending, Ascending}); err != nil {
|
||||
t.Errorf("CreateIndex failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ func TestIndexSortOrder(t *testing.T) {
|
|||
keyFields := []string{"timestamp"}
|
||||
|
||||
// 测试创建升序索引
|
||||
if err := is.CreateIndex(indexName, NonUnique, keyFields, []IndexSortOrder{Ascending}); err != nil {
|
||||
if _, err := is.CreateIndex(indexName, NonUnique, keyFields, []IndexSortOrder{Ascending}); err != nil {
|
||||
t.Errorf("CreateIndex failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ func TestIndexSortOrder(t *testing.T) {
|
|||
|
||||
// 测试创建降序索引
|
||||
indexNameDesc := "sorted_index_desc"
|
||||
if err := is.CreateIndex(indexNameDesc, NonUnique, keyFields, []IndexSortOrder{Descending}); err != nil {
|
||||
if _, err := is.CreateIndex(indexNameDesc, NonUnique, keyFields, []IndexSortOrder{Descending}); err != nil {
|
||||
t.Errorf("CreateIndex failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ func TestCompositeIndexSortOrders(t *testing.T) {
|
|||
sortOrders := []IndexSortOrder{Descending, Ascending}
|
||||
|
||||
// 创建复合索引
|
||||
if err := is.CreateIndex(indexName, NonUnique, keyFields, sortOrders); err != nil {
|
||||
if _, err := is.CreateIndex(indexName, NonUnique, keyFields, sortOrders); err != nil {
|
||||
t.Errorf("CreateIndex failed: %v", err)
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ func TestConcurrentIndexOperations(t *testing.T) {
|
|||
indexName := fmt.Sprintf("concurrent_index_%d", i)
|
||||
|
||||
// 创建索引(默认升序)
|
||||
if err := is.CreateIndex(indexName, NonUnique, []string{"name"}, []IndexSortOrder{Ascending}); err != nil {
|
||||
if _, err := is.CreateIndex(indexName, NonUnique, []string{"name"}, []IndexSortOrder{Ascending}); err != nil {
|
||||
t.Errorf("CreateIndex failed: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,10 @@ package storage
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.pyer.club/kingecg/godocdb/utils"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
|
@ -56,4 +60,83 @@ func (s *LevelDBStorage) Scan(prefix []byte) (keys [][]byte, values [][]byte, er
|
|||
// Close 关闭数据库连接
|
||||
func (s *LevelDBStorage) Close() {
|
||||
s.db.Close()
|
||||
}
|
||||
}
|
||||
|
||||
type LevelDBComparator struct {
|
||||
}
|
||||
|
||||
func (c *LevelDBComparator) Compare(a, b []byte) int {
|
||||
ka := string(a)
|
||||
kb := string(b)
|
||||
|
||||
if strings.HasPrefix(ka, utils.Prefix_Index_Data) && strings.HasPrefix(kb, utils.Prefix_Index_Data) {
|
||||
kas := strings.Split(ka, utils.Separator_Key)
|
||||
kab := strings.Split(kb, utils.Separator_Key)
|
||||
if kas[1] == kab[1] {
|
||||
typestr := kas[2]
|
||||
orderstr := kas[3]
|
||||
kav := kas[4]
|
||||
kbv := kab[4]
|
||||
return c.mycompare(typestr, orderstr, kav, kbv)
|
||||
}
|
||||
|
||||
}
|
||||
return bytes.Compare(a, b)
|
||||
}
|
||||
|
||||
// LevelDBComparator 的 mycompare 方法用于按照指定类型和排序规则比较两个字符串
|
||||
// 参数:
|
||||
// types: 比较类型字符串(每个字符对应一种类型)
|
||||
// orders: 排序方向字符串(每个字符对应升序/降序)
|
||||
// a: 待比较的第一个字符串
|
||||
// b: 待比较的第二个字符串
|
||||
// 返回值:
|
||||
// 0: 相等
|
||||
// -1: a 小于 b
|
||||
// 1: a 大于 b
|
||||
//
|
||||
// 支持的比较类型:
|
||||
// Type_String: 字符串比较
|
||||
// Type_Int: 整数比较(当前未实现)
|
||||
// Type_Date: 日期比较(基于时间戳数值)
|
||||
// Type_Float: 浮点数比较
|
||||
//
|
||||
// 排序方向:
|
||||
// 'a' 表示升序,其他值表示降序
|
||||
func (c *LevelDBComparator) mycompare(types, orders, a, b string) int {
|
||||
ret := 0
|
||||
// 遍历所有比较类型
|
||||
for i := 0; i < len(types); i++ {
|
||||
switch string(types[i]) {
|
||||
case utils.Type_String:
|
||||
ret = strings.Compare(a, b)
|
||||
case utils.Type_Int:
|
||||
case utils.Type_Date:
|
||||
// 将字符串转换为时间戳进行比较
|
||||
ai, _ := strconv.ParseInt(a, 10, 64)
|
||||
bi, _ := strconv.ParseInt(b, 10, 64)
|
||||
if ai < bi {
|
||||
ret = -1
|
||||
} else if ai > bi {
|
||||
ret = 1
|
||||
}
|
||||
case utils.Type_Float:
|
||||
// 将字符串转换为浮点数进行比较
|
||||
af, _ := strconv.ParseFloat(a, 64)
|
||||
bf, _ := strconv.ParseFloat(b, 64)
|
||||
if af < bf {
|
||||
ret = -1
|
||||
} else if af > bf {
|
||||
ret = 1
|
||||
}
|
||||
}
|
||||
// 根据排序方向调整比较结果
|
||||
if ret != 0 {
|
||||
if string(orders[i]) == "a" {
|
||||
return ret
|
||||
}
|
||||
return -1 * ret
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package utils
|
||||
|
||||
const (
|
||||
Prefix_Index_Data = "indexes:data:"
|
||||
Prefix_Index_Meta = "indexes:meta:"
|
||||
Separator_Key = ":"
|
||||
Separator_IndexField = "|"
|
||||
Type_String = "s"
|
||||
Type_Int = "i"
|
||||
Type_Float = "f"
|
||||
Type_Bool = "b"
|
||||
Type_Date = "d"
|
||||
)
|
Loading…
Reference in New Issue