diff --git a/index/index.go b/index/index.go index a1ea224..be76f68 100644 --- a/index/index.go +++ b/index/index.go @@ -16,11 +16,20 @@ const ( Composite IndexType = "composite" ) +// IndexSortOrder 表示索引的排序方式 +type IndexSortOrder string + +const ( + Ascending IndexSortOrder = "asc" + Descending IndexSortOrder = "desc" +) + // IndexMetadata 索引元数据 type IndexMetadata struct { - Name string - Type IndexType - KeyFields []string + Name string + Type IndexType + KeyFields []string + SortOrders []IndexSortOrder // 每个字段对应的排序方式(长度应与KeyFields一致) } // IndexStore 管理索引的存储和查询 @@ -38,12 +47,18 @@ func NewIndexStore(path string) (*IndexStore, error) { } // CreateIndex 创建索引 -func (is *IndexStore) CreateIndex(indexName string, indexType IndexType, keyFields []string) error { +func (is *IndexStore) CreateIndex(indexName string, indexType IndexType, keyFields []string, sortOrders []IndexSortOrder) error { + // 验证keyFields和sortOrders长度一致 + if len(keyFields) != len(sortOrders) { + return fmt.Errorf("keyFields and sortOrders must have the same length") + } + // 存储索引元数据 metadata := IndexMetadata{ - Name: indexName, - Type: indexType, - KeyFields: keyFields, + Name: indexName, + Type: indexType, + KeyFields: keyFields, + SortOrders: sortOrders, // 使用字段级排序方式 } data, err := bson.Marshal(metadata) diff --git a/index/index_test.go b/index/index_test.go index a4a8c94..7d32362 100644 --- a/index/index_test.go +++ b/index/index_test.go @@ -23,8 +23,8 @@ func TestIndexStore(t *testing.T) { indexName := "test_index" keyFields := []string{"name"} - // 测试创建索引 - if err := is.CreateIndex(indexName, SingleField, keyFields); err != nil { + // 测试创建索引(默认升序) + if err := is.CreateIndex(indexName, SingleField, keyFields, []IndexSortOrder{Ascending}); err != nil { t.Errorf("CreateIndex failed: %v", err) } @@ -66,8 +66,8 @@ func TestCompositeIndex(t *testing.T) { indexName := "composite_index" keyFields := []string{"name", "age"} - // 创建复合索引 - if err := is.CreateIndex(indexName, Composite, keyFields); err != nil { + // 创建复合索引(默认升序) + if err := is.CreateIndex(indexName, Composite, keyFields, []IndexSortOrder{Ascending, Ascending}); err != nil { t.Errorf("CreateIndex failed: %v", err) } @@ -82,6 +82,91 @@ func TestCompositeIndex(t *testing.T) { } } +func TestIndexSortOrder(t *testing.T) { + // 测试目录 + dir := "./testdb_sort" + defer os.RemoveAll(dir) + + // 初始化索引存储 + is, err := NewIndexStore(dir) + if err != nil { + t.Fatalf("Failed to create index store: %v", err) + } + defer is.storage.Close() + + // 测试单字段索引的排序 + indexName := "sorted_index" + keyFields := []string{"timestamp"} + + // 测试创建升序索引 + if err := is.CreateIndex(indexName, SingleField, keyFields, []IndexSortOrder{Ascending}); err != nil { + t.Errorf("CreateIndex failed: %v", err) + } + + // 验证元数据 + metadata, err := is.GetIndexMetadata(indexName) + if err != nil { + t.Errorf("GetIndexMetadata failed: %v", err) + } + + if len(metadata.SortOrders) != 1 || metadata.SortOrders[0] != Ascending { + t.Errorf("Expected sort order to be ascending, got %v", metadata.SortOrders) + } + + // 测试创建降序索引 + indexNameDesc := "sorted_index_desc" + if err := is.CreateIndex(indexNameDesc, SingleField, keyFields, []IndexSortOrder{Descending}); err != nil { + t.Errorf("CreateIndex failed: %v", err) + } + + // 验证降序元数据 + metadataDesc, err := is.GetIndexMetadata(indexNameDesc) + if err != nil { + t.Errorf("GetIndexMetadata failed: %v", err) + } + + if len(metadataDesc.SortOrders) != 1 || metadataDesc.SortOrders[0] != Descending { + t.Errorf("Expected sort order to be descending, got %v", metadataDesc.SortOrders) + } +} + +func TestCompositeIndexSortOrders(t *testing.T) { + // 测试复合索引的不同字段排序 + dir := "./testdb_composite_sort" + defer os.RemoveAll(dir) + + is, err := NewIndexStore(dir) + if err != nil { + t.Fatalf("Failed to create index store: %v", err) + } + defer is.storage.Close() + + // 测试复合索引(不同字段不同排序) + indexName := "composite_index_mixed" + keyFields := []string{"name", "age"} + sortOrders := []IndexSortOrder{Descending, Ascending} + + // 创建复合索引 + if err := is.CreateIndex(indexName, Composite, keyFields, sortOrders); err != nil { + t.Errorf("CreateIndex failed: %v", err) + } + + // 验证元数据 + metadata, err := is.GetIndexMetadata(indexName) + if err != nil { + t.Errorf("GetIndexMetadata failed: %v", err) + } + + if metadata.Type != Composite || len(metadata.KeyFields) != 2 { + t.Errorf("Composite index metadata mismatch: got %+v want type=%s fieldsCount=2", metadata, Composite) + } + + // 验证每个字段的排序方式 + if metadata.SortOrders[0] != Descending || metadata.SortOrders[1] != Ascending { + t.Errorf("Expected sort orders [desc, asc], got [%v, %v]", metadata.SortOrders[0], metadata.SortOrders[1]) + } +} + func BenchmarkSingleFieldQuery(b *testing.B) { // 基准测试单字段查询性能 dir := "./testdb_bench" @@ -91,7 +176,7 @@ func BenchmarkSingleFieldQuery(b *testing.B) { // 创建测试数据 for i := 0; i < 1000; i++ { - is.CreateIndex(fmt.Sprintf("index_%d", i), SingleField, []string{"name"}) + is.CreateIndex(fmt.Sprintf("index_%d", i), SingleField, []string{"name"}, []IndexSortOrder{Ascending}) } b.ResetTimer() @@ -120,8 +205,8 @@ func TestConcurrentIndexOperations(t *testing.T) { defer wg.Done() indexName := fmt.Sprintf("concurrent_index_%d", i) - // 创建索引 - if err := is.CreateIndex(indexName, SingleField, []string{"name"}); err != nil { + // 创建索引(默认升序) + if err := is.CreateIndex(indexName, SingleField, []string{"name"}, []IndexSortOrder{Ascending}); err != nil { t.Errorf("CreateIndex failed: %v", err) } @@ -133,4 +218,4 @@ func TestConcurrentIndexOperations(t *testing.T) { } wg.Wait() -} \ No newline at end of file +}