功能:实现索引查询功能

- 为 Index 添加 Query 方法支持条件查询
- 实现 QueryBuilder 支持索引查询
- 添加索引查询测试用例
- 支持 Eq/Gt/Lt/Gte/Lte 等比较操作
This commit is contained in:
2025-10-09 19:35:38 +08:00
parent 4aade1cff1
commit c4d79bc54b
3 changed files with 372 additions and 9 deletions

View File

@@ -98,7 +98,9 @@ func (idx *SecondaryIndex) Build() error {
// 使用 B+Tree 写入器
writer := NewIndexBTreeWriter(idx.file, idx.metadata)
// 添加所有条目
// 写入内存中的所有条目
// 注意:这假设 valueToSeq 包含所有数据(包括从磁盘加载的)
// 对于增量更新场景Get() 会合并内存和磁盘的结果
for value, seqs := range idx.valueToSeq {
writer.Add(value, seqs)
}
@@ -109,8 +111,25 @@ func (idx *SecondaryIndex) Build() error {
return fmt.Errorf("failed to build btree index: %w", err)
}
// 关闭旧的 btreeReader
if idx.btreeReader != nil {
idx.btreeReader.Close()
}
// 重新加载 btreeReader读取刚写入的数据
reader, err := NewIndexBTreeReader(idx.file)
if err != nil {
return fmt.Errorf("failed to reload btree reader: %w", err)
}
idx.btreeReader = reader
idx.useBTree = true
idx.ready = true
// 不清空 valueToSeq保留所有数据在内存中
// 这样下次 Build() 时可以写入完整数据
// Get() 方法会合并内存和磁盘的结果(去重)
return nil
}
@@ -197,7 +216,7 @@ func (idx *SecondaryIndex) loadJSON() error {
return nil
}
// Get 查询索引
// Get 查询索引(优先查内存,然后查磁盘,合并结果)
func (idx *SecondaryIndex) Get(value any) ([]int64, error) {
idx.mu.RLock()
defer idx.mu.RUnlock()
@@ -208,18 +227,37 @@ func (idx *SecondaryIndex) Get(value any) ([]int64, error) {
key := fmt.Sprintf("%v", value)
// 如果使用 B+Tree从 B+Tree 读取
if idx.useBTree && idx.btreeReader != nil {
return idx.btreeReader.Get(key)
// 收集所有匹配的 seqs需要去重
seqMap := make(map[int64]bool)
// 1. 先从内存 map 读取(包含最新的未持久化数据)
if memSeqs, exists := idx.valueToSeq[key]; exists {
for _, seq := range memSeqs {
seqMap[seq] = true
}
}
// 否则从内存 map 读取
seqs, exists := idx.valueToSeq[key]
if !exists {
// 2. 如果使用 B+Tree从 B+Tree 读取(持久化的数据)
if idx.useBTree && idx.btreeReader != nil {
diskSeqs, err := idx.btreeReader.Get(key)
if err == nil && diskSeqs != nil {
for _, seq := range diskSeqs {
seqMap[seq] = true
}
}
}
// 3. 合并结果
if len(seqMap) == 0 {
return nil, nil
}
return seqs, nil
result := make([]int64, 0, len(seqMap))
for seq := range seqMap {
result = append(result, seq)
}
return result, nil
}
// IsReady 索引是否就绪