feat: 优化标签ID处理逻辑,新增批量更新TagID功能

This commit is contained in:
wizardchen
2025-12-25 17:16:35 +08:00
committed by lyingbug
parent 4c0846f9c7
commit a025ebe7fb
4 changed files with 22 additions and 7 deletions
+14 -3
View File
@@ -90,7 +90,7 @@ func (r *chunkRepository) ListPagedChunksByKnowledgeID(
baseFilter := func(db *gorm.DB) *gorm.DB {
db = db.Where("tenant_id = ? AND knowledge_id = ? AND chunk_type IN (?) AND status in (?)",
tenantID, knowledgeID, chunkType, []int{int(types.ChunkStatusIndexed), int(types.ChunkStatusDefault)})
if tagID == "__untagged__" {
if tagID == types.UntaggedTagID {
// Special value to filter entries without a tag
db = db.Where("tag_id = ''")
} else if tagID != "" {
@@ -601,6 +601,7 @@ func (r *chunkRepository) UpdateChunkFlagsBatch(
// UpdateChunkFieldsByTagID updates fields for all chunks with the specified tag ID.
// Returns the list of affected chunk IDs for syncing with retriever engines.
// newTagID: if not nil, updates tag_id to this value (empty string means uncategorized)
func (r *chunkRepository) UpdateChunkFieldsByTagID(
ctx context.Context,
tenantID uint64,
@@ -609,6 +610,7 @@ func (r *chunkRepository) UpdateChunkFieldsByTagID(
isEnabled *bool,
setFlags types.ChunkFlags,
clearFlags types.ChunkFlags,
newTagID *string,
excludeIDs []string,
) ([]string, error) {
// First, get the IDs of chunks that will be affected (for is_enabled sync)
@@ -619,7 +621,7 @@ func (r *chunkRepository) UpdateChunkFieldsByTagID(
Select("id").
Where("tenant_id = ? AND knowledge_base_id = ? AND chunk_type = ?",
tenantID, kbID, types.ChunkTypeFAQ)
if tagID == "" {
if tagID == "" || tagID == types.UntaggedTagID {
query = query.Where("(tag_id = '' OR tag_id IS NULL)")
} else {
query = query.Where("tag_id = ?", tagID)
@@ -648,11 +650,20 @@ func (r *chunkRepository) UpdateChunkFieldsByTagID(
updates["is_enabled"] = *isEnabled
}
// Handle newTagID update (__untagged__ is stored as empty string)
if newTagID != nil {
if *newTagID == types.UntaggedTagID {
updates["tag_id"] = ""
} else {
updates["tag_id"] = *newTagID
}
}
query := r.db.WithContext(ctx).Model(&types.Chunk{}).
Where("tenant_id = ? AND knowledge_base_id = ? AND chunk_type = ?",
tenantID, kbID, types.ChunkTypeFAQ)
if tagID == "" {
if tagID == "" || tagID == types.UntaggedTagID {
query = query.Where("(tag_id = '' OR tag_id IS NULL)")
} else {
query = query.Where("tag_id = ?", tagID)
+1 -1
View File
@@ -3570,7 +3570,7 @@ func (s *knowledgeService) UpdateFAQEntryFieldsBatch(ctx context.Context,
// Update all chunks with this tag
affectedIDs, err := s.chunkRepo.UpdateChunkFieldsByTagID(
ctx, tenantID, kb.ID, tagID,
update.IsEnabled, setFlags, clearFlags, req.ExcludeIDs,
update.IsEnabled, setFlags, clearFlags, update.TagID, req.ExcludeIDs,
)
if err != nil {
return err
+4 -1
View File
@@ -228,6 +228,9 @@ type FAQSearchRequest struct {
MatchCount int `json:"match_count"`
}
// UntaggedTagID is the special tag ID representing uncategorized entries
const UntaggedTagID = "__untagged__"
// FAQEntryFieldsUpdate 单个FAQ条目的字段更新
type FAQEntryFieldsUpdate struct {
IsEnabled *bool `json:"is_enabled,omitempty"`
@@ -243,7 +246,7 @@ type FAQEntryFieldsUpdate struct {
type FAQEntryFieldsBatchUpdate struct {
// ByID 按条目ID更新,key为条目ID
ByID map[string]FAQEntryFieldsUpdate `json:"by_id,omitempty"`
// ByTag 按Tag批量更新,key为TagID(空字符串表示未分类)
// ByTag 按Tag批量更新,key为TagID(__untagged__表示未分类)
ByTag map[string]FAQEntryFieldsUpdate `json:"by_tag,omitempty"`
// ExcludeIDs 在ByTag操作中需要排除的ID列表
ExcludeIDs []string `json:"exclude_ids,omitempty"`
+3 -2
View File
@@ -64,8 +64,9 @@ type ChunkRepository interface {
// clearFlags: map of chunk ID to flags to clear (AND NOT operation)
UpdateChunkFlagsBatch(ctx context.Context, tenantID uint64, kbID string, setFlags map[string]types.ChunkFlags, clearFlags map[string]types.ChunkFlags) error
// UpdateChunkFieldsByTagID updates fields for all chunks with the specified tag ID.
// Supports updating is_enabled and flags fields.
UpdateChunkFieldsByTagID(ctx context.Context, tenantID uint64, kbID string, tagID string, isEnabled *bool, setFlags types.ChunkFlags, clearFlags types.ChunkFlags, excludeIDs []string) ([]string, error)
// Supports updating is_enabled, flags, and tag_id fields.
// newTagID: if not nil, updates tag_id to this value (empty string means uncategorized)
UpdateChunkFieldsByTagID(ctx context.Context, tenantID uint64, kbID string, tagID string, isEnabled *bool, setFlags types.ChunkFlags, clearFlags types.ChunkFlags, newTagID *string, excludeIDs []string) ([]string, error)
// FAQChunkDiff compares FAQ chunks between two knowledge bases and returns the differences.
// Returns: chunksToAdd (content_hash in src but not in dst), chunksToDelete (content_hash in dst but not in src)
FAQChunkDiff(ctx context.Context, srcTenantID uint64, srcKBID string, dstTenantID uint64, dstKBID string) (chunksToAdd []string, chunksToDelete []string, err error)