Skip to content

Commit c2c2072

Browse files
committed
feat: 为所有存储和索引器添加Clear清空数据接口
本次提交为全文索引、向量存储、图谱存储以及上层索引器统一添加了Clear清空数据的方法: 1. 扩展各存储接口定义,新增Clear方法声明 2. 实现各具体存储实现的Clear逻辑: - 全文索引:关闭并重建索引目录 - 向量存储:删除重建集合 - 图谱存储:执行Cypher清空所有节点边 3. 为混合索引器、安全包装的全文索引器等上层组件实现Clear转发逻辑 4. 优化语义索引器删除逻辑,忽略从属维度向量不存在的错误 5. 补充完善了部分接口文档注释
1 parent 8817ed9 commit c2c2072

11 files changed

Lines changed: 162 additions & 6 deletions

File tree

core/fulltext.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ type FullTextStore interface {
1313

1414
// Count 返回全文索引中的文档总数
1515
Count() (int, error)
16+
17+
// Clear 清除全文索引中的所有数据
18+
Clear() error
1619
}
1720

1821
// FullTextSearchResult 全文搜索结果

core/graphstore.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ type GraphStore interface {
4646
// Useful for introspection and building UI filters.
4747
GetAllEdgeTypes(ctx context.Context) ([]string, error)
4848

49+
// Clear removes all nodes and edges from the graph store.
50+
// After Clear, the graph is empty and ready for new data.
51+
//
52+
// Parameters:
53+
// - ctx: Context for cancellation and timeout
54+
//
55+
// Returns:
56+
// - error: Any error that occurred during the operation
57+
Clear(ctx context.Context) error
58+
4959
// Close cleanly tears down Graph Store connections
5060
Close(ctx context.Context) error
5161
}

core/indexer.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,22 @@ type Indexer interface {
100100
// Count returns the total number of indexed chunks/entries.
101101
//
102102
// Parameters:
103-
// - ctx: Context for cancellation
103+
// - ctx: Context for cancellation and timeout
104104
//
105105
// Returns:
106106
// - int: The total count of indexed items
107-
// - error: An error if the operation fails
107+
// - error: Any error that occurred
108108
Count(ctx context.Context) (int, error)
109+
110+
// Clear removes all data from the indexer.
111+
// After Clear, the indexer is empty and ready for new data.
112+
//
113+
// Parameters:
114+
// - ctx: Context for cancellation and timeout
115+
//
116+
// Returns:
117+
// - error: Any error that occurred during the operation
118+
Clear(ctx context.Context) error
109119
}
110120

111121

core/vectorstore.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ type VectorStore interface {
8686
// - error: Any error that occurred
8787
Count(ctx context.Context) (int, error)
8888

89+
// Clear removes all vectors from the store.
90+
// After Clear, the store is ready for new data (no reinitialization needed).
91+
//
92+
// Parameters:
93+
// - ctx: Context for cancellation and timeout
94+
//
95+
// Returns:
96+
// - error: Any error that occurred during the operation
97+
Clear(ctx context.Context) error
98+
8999
// Close gracefully shuts down the vector store connection.
90100
// It should release all resources and close any open connections.
91101
//

hybrid.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,28 @@ func (h *HybridIndexer) Close(ctx context.Context) error {
343343
return nil
344344
}
345345

346+
// Clear 清除所有子索引器中的数据
347+
func (h *HybridIndexer) Clear(ctx context.Context) error {
348+
h.mu.RLock()
349+
indexers := make([]core.Indexer, 0, len(h.indexers))
350+
for _, idx := range h.indexers {
351+
indexers = append(indexers, idx)
352+
}
353+
h.mu.RUnlock()
354+
355+
var errs []error
356+
for _, idx := range indexers {
357+
if err := idx.Clear(ctx); err != nil {
358+
h.logger.Warn("clear partial failure", "indexer", idx.Name(), "error", err)
359+
errs = append(errs, fmt.Errorf("%s: %w", idx.Name(), err))
360+
}
361+
}
362+
if len(errs) > 0 {
363+
return fmt.Errorf("clear failed for %d indexers: %v", len(errs), errs)
364+
}
365+
return nil
366+
}
367+
346368
// Name 返回索引器名称
347369
func (h *HybridIndexer) Name() string {
348370
return "hybrid"

indexer/fulltext.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ func (f *safeFulltextIndexer) Count(ctx context.Context) (int, error) {
214214
return f.inner.Count(ctx)
215215
}
216216

217+
func (f *safeFulltextIndexer) Clear(ctx context.Context) error {
218+
f.mu.Lock()
219+
defer f.mu.Unlock()
220+
return f.inner.Clear(ctx)
221+
}
222+
217223
// NewSafeFulltextIndexer 创建线程安全的全文索引器
218224
func NewSafeFulltextIndexer(dbPath string) (core.Indexer, error) {
219225
inner, err := NewFulltextIndexerWithFile(dbPath)
@@ -257,6 +263,10 @@ func (s *fulltextIndexer) NewQuery(terms string) core.Query {
257263
return query.NewFulltextQuery(terms)
258264
}
259265

266+
func (f *fulltextIndexer) Clear(ctx context.Context) error {
267+
return f.store.Clear()
268+
}
269+
260270
// List returns empty result — BM25 indexer does not support chunk browsing.
261271
func (f *fulltextIndexer) List(ctx context.Context, offset, limit int) ([]core.Hit, error) {
262272
return []core.Hit{}, nil

indexer/graph.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,8 @@ func (idx *GraphIndexer) Remove(ctx context.Context, chunkID string) error {
10911091
// 联动删除所有从属维度向量(title + summary)
10921092
for _, dim := range graphDimensions {
10931093
if err := idx.vectorDB.Delete(ctx, chunkID+dim.suffix); err != nil {
1094-
return err
1094+
// 从属维度向量可能不存在(无对应字段可提取),不视为错误
1095+
idx.logger.Warn("remove graph dimension vector: %v", err)
10951096
}
10961097
}
10971098
// 从 graphDB 移除关联的节点和边(级联删除)
@@ -1302,6 +1303,27 @@ func (idx *GraphIndexer) Close(ctx context.Context) error {
13021303
return idx.graphDB.Close(ctx)
13031304
}
13041305

1306+
// Clear 清空索引中的所有数据(向量 + 图谱)。
1307+
func (idx *GraphIndexer) Clear(ctx context.Context) error {
1308+
idx.mu.Lock()
1309+
defer idx.mu.Unlock()
1310+
idx.logger.Info("GraphIndexer.Clear: clearing vectorDB")
1311+
if err := idx.vectorDB.Clear(ctx); err != nil {
1312+
idx.logger.Error("GraphIndexer.Clear: vectorDB.Clear failed", err)
1313+
return fmt.Errorf("clear vectorDB: %w", err)
1314+
}
1315+
idx.logger.Info("GraphIndexer.Clear: vectorDB cleared successfully, clearing graphDB")
1316+
if err := idx.graphDB.Clear(ctx); err != nil {
1317+
idx.logger.Error("GraphIndexer.Clear: graphDB.Clear failed", err)
1318+
return fmt.Errorf("clear graphDB: %w", err)
1319+
}
1320+
// 重置累计统计
1321+
idx.entitiesCreated = 0
1322+
idx.relsCreated = 0
1323+
idx.logger.Info("GraphIndexer.Clear: all stores cleared successfully")
1324+
return nil
1325+
}
1326+
13051327
// ---------------------------------------------------------------------------
13061328
// 扩展方法
13071329
// ---------------------------------------------------------------------------

indexer/semantic.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,8 @@ func (s *semanticIndexer) Remove(ctx context.Context, chunkID string) error {
403403
// 联动删除所有从属维度向量(无对应维度的 chunk 删不到也无副作用)
404404
for _, dim := range semanticDimensions {
405405
if err := s.db.Delete(ctx, chunkID+dim.suffix); err != nil {
406-
return err
406+
// 从属维度向量可能不存在(无对应字段可提取),不视为错误
407+
s.logger.Warn("remove dimension vector: %v", err)
407408
}
408409
}
409410
return nil
@@ -693,3 +694,8 @@ func vectorToHit(vec *core.Vector) core.Hit {
693694
func (s *semanticIndexer) Count(ctx context.Context) (int, error) {
694695
return s.db.Count(ctx)
695696
}
697+
698+
// Clear removes all vectors from the semantic indexer.
699+
func (s *semanticIndexer) Clear(ctx context.Context) error {
700+
return s.db.Clear(ctx)
701+
}

store/doc/bleve/store.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,32 @@ func (s *BleveStore) Count() (int, error) {
124124
return int(count), nil
125125
}
126126

127+
// Clear 清除全文索引中的所有数据
128+
func (s *BleveStore) Clear() error {
129+
s.mu.Lock()
130+
defer s.mu.Unlock()
131+
132+
// 关闭当前索引
133+
if s.index != nil {
134+
if err := s.index.Close(); err != nil {
135+
return err
136+
}
137+
}
138+
139+
// 删除索引目录
140+
if err := os.RemoveAll(s.dbPath); err != nil {
141+
return err
142+
}
143+
144+
// 重新创建索引
145+
index, err := blevedb.New(s.dbPath, blevedb.NewIndexMapping())
146+
if err != nil {
147+
return err
148+
}
149+
s.index = index
150+
return nil
151+
}
152+
127153
// Close 关闭索引
128154
func (s *BleveStore) Close() error {
129155
s.mu.Lock()

store/graph/gograph/graphstore.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,15 @@ func (s *gographStore) GetAllEdgeTypes(ctx context.Context) ([]string, error) {
443443
return types, nil
444444
}
445445

446+
// Clear removes all nodes and edges from the graph store.
447+
func (s *gographStore) Clear(ctx context.Context) error {
448+
_, err := s.db.Exec(ctx, "MATCH (n) DETACH DELETE n", nil)
449+
if err != nil {
450+
return fmt.Errorf("clear graph: %w", err)
451+
}
452+
return nil
453+
}
454+
446455
// GetMultiHopPaths performs multi-hop traversal from starting nodes.
447456
// If edgeTypes is non-empty, only edges matching those types are traversed.
448457
func (s *gographStore) GetMultiHopPaths(ctx context.Context, nodeIDs []string, edgeTypes []string, depth int, limit int) ([]*core.Node, []*core.Edge, error) {

0 commit comments

Comments
 (0)