feat: 优化标签ID处理逻辑,新增批量更新TagID功能
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user