add sort order support
This commit is contained in:
parent
d51dc51932
commit
857cad7fea
|
@ -16,11 +16,20 @@ const (
|
||||||
Composite IndexType = "composite"
|
Composite IndexType = "composite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IndexSortOrder 表示索引的排序方式
|
||||||
|
type IndexSortOrder string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Ascending IndexSortOrder = "asc"
|
||||||
|
Descending IndexSortOrder = "desc"
|
||||||
|
)
|
||||||
|
|
||||||
// IndexMetadata 索引元数据
|
// IndexMetadata 索引元数据
|
||||||
type IndexMetadata struct {
|
type IndexMetadata struct {
|
||||||
Name string
|
Name string
|
||||||
Type IndexType
|
Type IndexType
|
||||||
KeyFields []string
|
KeyFields []string
|
||||||
|
SortOrders []IndexSortOrder // 每个字段对应的排序方式(长度应与KeyFields一致)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexStore 管理索引的存储和查询
|
// IndexStore 管理索引的存储和查询
|
||||||
|
@ -38,12 +47,18 @@ func NewIndexStore(path string) (*IndexStore, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateIndex 创建索引
|
// 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{
|
metadata := IndexMetadata{
|
||||||
Name: indexName,
|
Name: indexName,
|
||||||
Type: indexType,
|
Type: indexType,
|
||||||
KeyFields: keyFields,
|
KeyFields: keyFields,
|
||||||
|
SortOrders: sortOrders, // 使用字段级排序方式
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := bson.Marshal(metadata)
|
data, err := bson.Marshal(metadata)
|
||||||
|
|
|
@ -23,8 +23,8 @@ func TestIndexStore(t *testing.T) {
|
||||||
indexName := "test_index"
|
indexName := "test_index"
|
||||||
keyFields := []string{"name"}
|
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)
|
t.Errorf("CreateIndex failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ func TestCompositeIndex(t *testing.T) {
|
||||||
indexName := "composite_index"
|
indexName := "composite_index"
|
||||||
keyFields := []string{"name", "age"}
|
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)
|
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) {
|
func BenchmarkSingleFieldQuery(b *testing.B) {
|
||||||
// 基准测试单字段查询性能
|
// 基准测试单字段查询性能
|
||||||
dir := "./testdb_bench"
|
dir := "./testdb_bench"
|
||||||
|
@ -91,7 +176,7 @@ func BenchmarkSingleFieldQuery(b *testing.B) {
|
||||||
|
|
||||||
// 创建测试数据
|
// 创建测试数据
|
||||||
for i := 0; i < 1000; i++ {
|
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()
|
b.ResetTimer()
|
||||||
|
@ -120,8 +205,8 @@ func TestConcurrentIndexOperations(t *testing.T) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
indexName := fmt.Sprintf("concurrent_index_%d", i)
|
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)
|
t.Errorf("CreateIndex failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue