This commit is contained in:
kingecg 2025-06-08 20:42:48 +08:00
parent fd28639f17
commit eff399c4e4
5 changed files with 30 additions and 376 deletions

View File

@ -1,355 +0,0 @@
package alg
import "strings"
type IndexKey interface {
Compare(other IndexKey) int
}
type SortOrder struct {
Field string
Desc bool
}
type IndexEntry struct {
Key IndexKey
Value interface{}
}
const BTreeMinDegree = 2
type BTreeNode struct {
Keys []IndexKey
Values []interface{} // 叶子节点存储数据
Childs []*BTreeNode // 非叶子节点存储子节点
IsLeaf bool
Next *BTreeNode // 叶子节点之间的链表指针
Prev *BTreeNode
}
type BTree struct {
Root *BTreeNode
}
func NewBTreeNode(leaf bool) *BTreeNode {
return &BTreeNode{
Keys: make([]IndexKey, 0),
Values: make([]interface{}, 0),
Childs: make([]*BTreeNode, 0),
IsLeaf: leaf,
}
}
func NewBTree() *BTree {
return &BTree{
Root: NewBTreeNode(true),
}
}
func (bt *BTree) Insert(key IndexKey, value interface{}) {
root := bt.Root
// 如果根节点已满,需要分裂
if len(root.Keys) == 2*BTreeMinDegree-1 {
newRoot := NewBTreeNode(false)
newRoot.Childs = append(newRoot.Childs, root)
splitChild(newRoot, 0)
bt.Root = newRoot
}
insertNonFull(bt.Root, key, value)
}
// 分裂子节点
func splitChild(parent *BTreeNode, index int) {
minDegree := BTreeMinDegree
fullNode := parent.Childs[index]
// 创建新节点
newNode := NewBTreeNode(fullNode.IsLeaf)
// 中间键位置
mid := minDegree - 1
// 拆分键和值
newNode.Keys = fullNode.Keys[mid:]
fullNode.Keys = fullNode.Keys[:mid]
if !fullNode.IsLeaf {
newNode.Childs = fullNode.Childs[mid:]
fullNode.Childs = fullNode.Childs[:mid]
} else {
// 叶子节点需要维护链表
newNode.Values = fullNode.Values[mid:]
fullNode.Values = fullNode.Values[:mid]
newNode.Next = fullNode.Next
newNode.Prev = fullNode
if fullNode.Next != nil {
fullNode.Next.Prev = newNode
}
fullNode.Next = newNode
}
// 将中间键提升到父节点
parent.Keys = append(parent.Keys[:index+1], append([]IndexKey{fullNode.Keys[mid]}, parent.Keys[index+1:]...)...)
fullNode.Keys = fullNode.Keys[:mid]
}
// 插入非满节点
func insertNonFull(node *BTreeNode, key IndexKey, value interface{}) {
i := len(node.Keys) - 1
if node.IsLeaf {
// 在叶子节点插入
for i >= 0 && key.Compare(node.Keys[i]) < 0 {
i--
}
// 插入键值
if i >= 0 {
node.Keys = append(node.Keys[:i+1], append([]IndexKey{key}, node.Keys[i+1:]...)...)
node.Values = append(node.Values[:i+1], append([]interface{}{value}, node.Values[i+1:]...)...)
} else {
node.Keys = append([]IndexKey{key}, node.Keys...)
node.Values = append([]interface{}{value}, node.Values...)
}
} else {
// 找到子节点
for i >= 0 && key.Compare(node.Keys[i]) < 0 {
i--
}
i++
// 如果子节点已满,需要分裂
child := node.Childs[i]
if len(child.Keys) == 2*BTreeMinDegree-1 {
splitChild(node, i)
if key.Compare(node.Keys[i]) > 0 {
i++ // 选择正确的位置
}
}
insertNonFull(node.Childs[i], key, value)
}
}
func (bt *BTree) Search(key IndexKey) (interface{}, bool) {
node := bt.Root
for node != nil {
// 在当前节点查找位置
i := 0
for i < len(node.Keys) && key.Compare(node.Keys[i]) > 0 {
i++
}
if node.IsLeaf {
// 在叶子节点中查找精确匹配
if i < len(node.Keys) && key.Compare(node.Keys[i]) == 0 {
return node.Values[i], true
}
return nil, false
} else {
// 继续查找子节点
node = node.Childs[i]
}
}
return nil, false
}
func (bt *BTree) Delete(key IndexKey) {
deleteFromNode(bt.Root, key)
}
// 从节点删除指定键
func deleteFromNode(node *BTreeNode, key IndexKey) {
minDegree := BTreeMinDegree
// 寻找键的位置
i := 0
for i < len(node.Keys) && key.Compare(node.Keys[i]) > 0 {
i++
}
if node.IsLeaf {
// 叶子节点直接删除
if i < len(node.Keys) && key.Compare(node.Keys[i]) == 0 {
// 删除键值对
node.Keys = append(node.Keys[:i], node.Keys[i+1:]...)
node.Values = append(node.Values[:i], node.Values[i+1:]...)
}
} else {
// 非叶子节点
if i < len(node.Keys) && key.Compare(node.Keys[i]) == 0 {
// 找到键,需要替换为后继值
child := node.Childs[i]
sibling := node.Childs[i+1]
if len(child.Keys) >= minDegree {
// 前驱节点存在,替换为前驱
predecessor := getPredecessor(child)
node.Keys[i] = predecessor
deleteFromNode(child, predecessor)
} else if len(sibling.Keys) >= minDegree {
// 后继节点存在,替换为后继
successor := getSuccessor(sibling)
node.Keys[i] = successor
deleteFromNode(sibling, successor)
} else {
// 合并节点
mergeNodes(node, i)
deleteFromNode(child, key)
}
} else {
// 继续删除子节点
child := node.Childs[i]
if len(child.Keys) >= minDegree {
// 子节点足够大,继续删除
deleteFromNode(child, key)
} else {
// 需要重新平衡
if i > 0 && len(node.Childs[i-1].Keys) >= minDegree {
// 从左兄弟借
borrowFromLeft(node, i)
} else if i < len(node.Childs)-1 && len(node.Childs[i+1].Keys) >= minDegree {
// 从右兄弟借
borrowFromRight(node, i)
} else {
// 合并节点
if i > 0 {
mergeNodes(node, i-1)
} else {
mergeNodes(node, i)
}
}
deleteFromNode(child, key)
}
}
}
}
// 获取前驱节点
func getPredecessor(node *BTreeNode) IndexKey {
for !node.IsLeaf {
node = node.Childs[len(node.Childs)-1]
}
return node.Keys[len(node.Keys)-1]
}
// 获取后继节点
func getSuccessor(node *BTreeNode) IndexKey {
for !node.IsLeaf {
node = node.Childs[0]
}
return node.Keys[0]
}
// 合并节点
func mergeNodes(parent *BTreeNode, index int) {
left := parent.Childs[index]
right := parent.Childs[index+1]
// 将左节点和右节点合并
left.Keys = append(left.Keys, parent.Keys[index])
left.Keys = append(left.Keys, right.Keys...)
if left.IsLeaf {
left.Values = append(left.Values, right.Values...)
left.Next = right.Next
if right.Next != nil {
right.Next.Prev = left
}
} else {
left.Childs = append(left.Childs, right.Childs...)
}
// 更新父节点
parent.Keys = append(parent.Keys[:index], parent.Keys[index+1:]...)
parent.Childs = append(parent.Childs[:index+1], parent.Childs[index+2:]...)
}
// 从左兄弟借
func borrowFromLeft(parent *BTreeNode, index int) {
left := parent.Childs[index-1]
current := parent.Childs[index]
// 移动键
current.Keys = append([]IndexKey{parent.Keys[index-1]}, current.Keys...)
if !left.IsLeaf {
current.Childs = append([]*BTreeNode{left.Childs[len(left.Childs)-1]}, current.Childs...)
left.Childs = left.Childs[:len(left.Childs)-1]
}
// 更新父节点
parent.Keys[index-1] = left.Keys[len(left.Keys)-1]
left.Keys = left.Keys[:len(left.Keys)-1]
}
// 从右兄弟借
func borrowFromRight(parent *BTreeNode, index int) {
current := parent.Childs[index]
right := parent.Childs[index+1]
// 移动键
current.Keys = append(current.Keys, parent.Keys[index])
parent.Keys[index] = right.Keys[0]
if !current.IsLeaf {
current.Childs = append(current.Childs, right.Childs[0])
right.Childs = right.Childs[1:]
}
right.Keys = right.Keys[1:]
}
func (bt *BTree) Traverse(cb func(key IndexKey) bool) []interface{} {
result := make([]interface{}, 0)
// 找到最左边的叶子节点
node := bt.Root
for node != nil && !node.IsLeaf {
node = node.Childs[0]
}
// 遍历所有叶子节点
for node != nil {
for i, key := range node.Keys {
if cb(key) {
result = append(result, node.Values[i])
} else {
return result
}
}
node = node.Next
}
return result
}
type MultiFieldKey struct {
Fields []string
SortDirs []bool // true 表示降序
Values map[string]interface{}
}
func (m MultiFieldKey) Compare(other IndexKey) int {
o := other.(MultiFieldKey)
for i, field := range m.Fields {
v1 := m.Values[field]
v2 := o.Values[field]
var cmp int
switch v1.(type) {
case string:
cmp = strings.Compare(v1.(string), v2.(string))
case float64:
if v1.(float64) < v2.(float64) {
cmp = -1
} else if v1.(float64) > v2.(float64) {
cmp = 1
} else {
cmp = 0
}
default:
panic("Unsupported type")
}
if cmp != 0 {
if m.SortDirs[i] {
return -cmp
}
return cmp
}
}
return 0
}

8
api/index.go Normal file
View File

@ -0,0 +1,8 @@
package api
import "git.pyer.club/kingecg/godocdb/index"
type Index struct {
metadata index.IndexMetadata
store *index.IndexStore
}

View File

@ -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
}
}

View File

@ -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下更新索引

View File

@ -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)
}