当前位置: 首页 > news >正文

Coze源码分析-资源库-编辑知识库-后端源码-应用/领域/数据访问层

4. 领域服务层

KnowledgeSVC 领域服务层架构

知识库领域服务层是Coze Studio中处理知识库业务逻辑的核心层,负责知识库资源的编辑、更新和业务规则实现。当用户在知识库编辑界面修改信息并保存时,领域服务层实现了实际的业务逻辑处理。

知识库领域服务接口定义

领域服务接口定义了知识库管理的核心业务能力,包括知识库和文档的完整生命周期管理。

// KnowledgeService 知识库领域服务接口
type KnowledgeService interface {// 更新知识库基本信息UpdateKnowledge(ctx context.Context, req *UpdateKnowledgeRequest) error// 获取知识库详情GetKnowledge(ctx context.Context, knowledgeID string) (*Knowledge, error)// 创建文档CreateDocument(ctx context.Context, req *CreateDocumentRequest) (*CreateDocumentResponse, error)// 更新文档UpdateDocument(ctx context.Context, req *UpdateDocumentRequest) error// 删除文档DeleteDocument(ctx context.Context, req *DeleteDocumentRequest) error// 获取文档详情GetDocument(ctx context.Context, documentID string) (*Document, error)// 获取文档列表ListDocuments(ctx context.Context, req *ListDocumentsRequest) (*ListDocumentsResponse, error)
}// UpdateKnowledgeRequest 更新知识库请求
type UpdateKnowledgeRequest struct {KnowledgeID string  // 知识库IDName        *string // 知识库名称Description *string // 知识库描述CoverUrl    *string // 封面URLVisibility  *string // 可见性Tags        *string // 标签
}// Knowledge 知识库领域实体
type Knowledge struct {ID          string    // 知识库IDName        string    // 知识库名称Description string    // 知识库描述CoverUrl    string    // 封面URLVisibility  string    // 可见性Tags        string    // 标签OwnerID     string    // 所有者IDCreatedAt   int64     // 创建时间UpdatedAt   int64     // 更新时间Version     int64     // 版本号
}// Document 文档领域实体
type Document struct {ID          string    // 文档IDKnowledgeID string    // 所属知识库IDTitle       string    // 文档标题Content     string    // 文档内容Type        string    // 文档类型Version     int32     // 文档版本Status      int32     // 文档状态CreatedBy   string    // 创建者IDCreatedAt   int64     // 创建时间UpdatedAt   int64     // 更新时间
}

知识库领域服务实现

KnowledgeSVC是知识库领域服务的核心实现,处理所有与知识库编辑相关的业务逻辑。

// KnowledgeSVC 知识库领域服务实现
type KnowledgeSVC struct {knowledgeRepo repository.KnowledgeRepositorydocumentRepo  repository.DocumentRepositoryidGenerator   idgen.IDGeneratorcache         cache.Cache
}// KnowledgeSVCConfig 知识库服务配置
type KnowledgeSVCConfig struct {KnowledgeRepo repository.KnowledgeRepositoryDocumentRepo  repository.DocumentRepositoryIDGenerator   idgen.IDGeneratorCache         cache.Cache
}// NewKnowledgeSVC 创建知识库服务实例
func NewKnowledgeSVC(cfg *KnowledgeSVCConfig) (*KnowledgeSVC, error) {if cfg == nil {return nil, errors.New("knowledge svc config is nil")}// 验证必要依赖if cfg.KnowledgeRepo == nil {return nil, errors.New("knowledge repository is required")}if cfg.DocumentRepo == nil {return nil, errors.New("document repository is required")}if cfg.IDGenerator == nil {return nil, errors.New("id generator is required")}return &KnowledgeSVC{knowledgeRepo: cfg.KnowledgeRepo,documentRepo:  cfg.DocumentRepo,idGenerator:   cfg.IDGenerator,cache:         cfg.Cache,}, nil
}

更新知识库核心实现

当用户在编辑界面修改知识库信息并保存时,UpdateKnowledge方法实现了核心的业务逻辑:

// UpdateKnowledge 更新知识库信息
func (s *KnowledgeSVC) UpdateKnowledge(ctx context.Context, req *UpdateKnowledgeRequest) error {// 参数验证if err := s.validateUpdateKnowledgeRequest(req); err != nil {return err}// 查询知识库是否存在existingKnowledge, err := s.knowledgeRepo.Get(ctx, req.KnowledgeID)if err != nil {if errors.Is(err, repository.ErrNotFound) {return errorx.New(errno.ErrKnowledgeNotFoundCode, "knowledge not found")}return err}// 构建更新参数updateParams := make(map[string]interface{})// 仅当字段不为空时更新if req.Name != nil {updateParams["name"] = *req.Name}if req.Description != nil {updateParams["description"] = *req.Description}if req.CoverUrl != nil {updateParams["cover_url"] = *req.CoverUrl}if req.Visibility != nil {// 验证可见性值if !isValidVisibility(*req.Visibility) {return errorx.New(errno.ErrKnowledgeParamErrorCode, "invalid visibility value")}updateParams["visibility"] = *req.Visibility}if req.Tags != nil {updateParams["tags"] = *req.Tags}// 设置更新时间和版本now := time.Now().Unix()updateParams["updated_at"] = nowupdateParams["version"] = existingKnowledge.Version + 1// 执行更新操作err = s.knowledgeRepo.Update(ctx, req.KnowledgeID, updateParams)if err != nil {logs.CtxErrorf(ctx, "update knowledge failed, knowledgeID: %s, err: %v", req.KnowledgeID, err)return err}// 清除缓存if s.cache != nil {_ = s.cache.Delete(ctx, fmt.Sprintf("knowledge:%s", req.KnowledgeID))}return nil
}// validateUpdateKnowledgeRequest 验证更新知识库请求参数
func (s *KnowledgeSVC) validateUpdateKnowledgeRequest(req *UpdateKnowledgeRequest) error {if req.KnowledgeID == "" {return errorx.New(errno.ErrKnowledgeParamErrorCode, "knowledgeID is required")}// 验证名称(如果提供)if req.Name != nil {name := strings.TrimSpace(*req.Name)if name == "" {return errorx.New(errno.ErrKnowledgeParamErrorCode, "knowledge name cannot be empty")}if len(name) > 256 {return errorx.New(errno.ErrKnowledgeParamErrorCode, "knowledge name too long")}}return nil
}

文档管理核心实现

除了知识库基本信息更新外,领域服务层还实现了文档级别的管理功能:

// CreateDocument 创建文档
func (s *KnowledgeSVC) CreateDocument(ctx context.Context, req *CreateDocumentRequest) (*CreateDocumentResponse, error) {// 参数验证if err := s.validateCreateDocumentRequest(req); err != nil {return nil, err}// 验证知识库是否存在_, err := s.knowledgeRepo.Get(ctx, req.KnowledgeID)if err != nil {if errors.Is(err, repository.ErrNotFound) {return nil, errorx.New(errno.ErrKnowledgeNotFoundCode, "knowledge not found")}return nil, err}// 生成文档IDdocumentID := fmt.Sprintf("doc_%s", s.idGenerator.GenString())// 创建文档实体document := &repository.Document{ID:          documentID,KnowledgeID: req.KnowledgeID,Title:       req.Title,Content:     req.Content,Type:        req.Type,Version:     1,Status:      documentStatusNormal,CreatedBy:   req.CreatorID,CreatedAt:   time.Now().Unix(),UpdatedAt:   time.Now().Unix(),}// 执行创建操作err = s.documentRepo.Create(ctx, document)if err != nil {logs.CtxErrorf(ctx, "create document failed, knowledgeID: %s, err: %v", req.KnowledgeID, err)return nil, err}// 更新知识库文档计数err = s.knowledgeRepo.IncrementDocumentCount(ctx, req.KnowledgeID)if err != nil {logs.CtxErrorf(ctx, "increment document count failed, knowledgeID: %s, err: %v", req.KnowledgeID, err)// 计数更新失败不影响文档创建}return &CreateDocumentResponse{DocumentID: documentID,}, nil
}// UpdateDocument 更新文档
func (s *KnowledgeSVC) UpdateDocument(ctx context.Context, req *UpdateDocumentRequest) error {// 参数验证if err := s.validateUpdateDocumentRequest(req); err != nil {return err}// 查询文档是否存在existingDoc, err := s.documentRepo.Get(ctx, req.DocumentID)if err != nil {if errors.Is(err, repository.ErrNotFound) {return errorx.New(errno.ErrDocumentNotFoundCode, "document not found")}return err}// 构建更新参数updateParams := map[string]interface{}{"title":     req.Title,"content":   req.Content,"version":   existingDoc.Version + 1,"updated_at": time.Now().Unix(),}// 执行更新操作err = s.documentRepo.Update(ctx, req.DocumentID, updateParams)if err != nil {logs.CtxErrorf(ctx, "update document failed, documentID: %s, err: %v", req.DocumentID, err)return err}return nil
}

领域服务层设计特点

  1. 依赖注入:通过构造函数注入必要的依赖组件,如知识库仓库、文档仓库、ID生成器和缓存
  2. 参数验证:完善的参数验证机制,确保数据的合法性和完整性
  3. 错误处理:清晰的错误类型定义和错误处理策略
  4. 缓存管理:知识库更新后自动清除相关缓存
  5. 数据一致性:通过事务和状态管理确保数据一致性
  6. 版本控制:知识库和文档都支持版本号管理,用于冲突检测
  7. 事件驱动:与事件系统集成,支持业务事件的发布和订阅

领域服务层与其他层的协作

  1. 与应用服务层协作:接收应用服务层的请求,处理业务逻辑后返回结果
  2. 与数据访问层协作:通过Repository接口与数据访问层交互,实现数据持久化
  3. 与基础设施层协作:使用ID生成器、缓存等基础设施组件

领域服务层作为业务逻辑的核心,实现了知识库编辑场景下的所有业务规则和处理流程,确保了业务逻辑的一致性和可维护性。


**实体设计特点**:
1. **基础信息**:包含ID、名称、描述等基本属性,满足知识库的基本信息需求
2. **状态管理**:Status字段支持知识库和文档的状态管理,如正常、草稿、归档等
3. **关系映射**:KnowledgeID字段在文档实体中建立与知识库的关联关系
4. **版本控制**:文档实体包含Version字段,支持内容版本管理
5. **用户追踪**:CreatorID字段记录创建者信息,支持权限控制和审计
6. **时间追踪**:CreatedAt和UpdatedAt字段支持创建和更新时间追踪,便于版本管理## 5. 数据访问层### 5.1 仓储接口定义#### 知识库仓储接口知识库仓储接口定义了数据访问层的抽象,为领域服务层提供数据持久化能力,实现了业务逻辑与数据存储的解耦。```go
// KnowledgeRepo 知识库仓储接口
type KnowledgeRepo interface {// 创建知识库CreateKnowledge(ctx context.Context, knowledge *knowledgeEntity.Knowledge) (string, error)// 更新知识库UpdateKnowledge(ctx context.Context, knowledgeID string, updates map[string]interface{}) error// 删除知识库DeleteKnowledge(ctx context.Context, knowledgeID string) error// 获取知识库GetKnowledge(ctx context.Context, knowledgeID string) (*knowledgeEntity.Knowledge, error)// 批量获取知识库ListKnowledge(ctx context.Context, query map[string]interface{}, page, pageSize int32) ([]*knowledgeEntity.Knowledge, int64, error)// 创建文档CreateDocument(ctx context.Context, document *knowledgeEntity.Document) (string, error)// 更新文档UpdateDocument(ctx context.Context, documentID string, updates map[string]interface{}) error// 删除文档DeleteDocument(ctx context.Context, documentID string) error// 获取文档GetDocument(ctx context.Context, documentID string) (*knowledgeEntity.Document, error)// 获取知识库下的文档列表ListDocuments(ctx context.Context, knowledgeID string, query map[string]interface{}, page, pageSize int32) ([]*knowledgeEntity.Document, int64, error)
}

接口功能特点

  1. 完整CRUD操作:支持知识库和文档的创建、读取、更新、删除操作
  2. 查询能力:提供单条查询和批量查询接口,支持条件筛选和分页
  3. 批量操作:支持批量获取知识库和文档,提高数据处理效率
  4. 解耦设计:通过接口实现业务层与数据层的解耦,便于测试和替换实现
  5. 参数灵活性:使用map[string]interface{}作为更新参数,支持灵活的字段更新
  6. 统计支持:批量查询接口返回总数,支持分页和统计需求

5. 数据访问层

5.1 仓储接口定义

知识库仓储接口

文件位置:backend/domain/knowledge/repository/repository.go

//go:generate mockgen -destination ../internal/mock/dal/dao/knowledge.go --package dao -source knowledge.go
type KnowledgeRepo interface {Create(ctx context.Context, knowledge *model.Knowledge) errorUpsert(ctx context.Context, knowledge *model.Knowledge) errorUpdate(ctx context.Context, knowledge *model.Knowledge) errorDelete(ctx context.Context, id int64) errorGetByID(ctx context.Context, id int64) (*model.Knowledge, error)MGetByID(ctx context.Context, ids []int64) ([]*model.Knowledge, error)FilterEnableKnowledge(ctx context.Context, ids []int64) ([]*model.Knowledge, error)InitTx() (tx *gorm.DB, err error)UpdateWithTx(ctx context.Context, tx *gorm.DB, knowledgeID int64, updateMap map[string]interface{}) errorFindKnowledgeByCondition(ctx context.Context, opts *entity.WhereKnowledgeOption) ([]*model.Knowledge, int64, error)
}//go:generate mockgen -destination ../internal/mock/dal/dao/knowledge_document.go --package dao -source knowledge_document.go
type KnowledgeDocumentRepo interface {Create(ctx context.Context, document *model.KnowledgeDocument) errorUpdate(ctx context.Context, document *model.KnowledgeDocument) errorDelete(ctx context.Context, id int64) errorMGetByID(ctx context.Context, ids []int64) ([]*model.KnowledgeDocument, error)GetByID(ctx context.Context, id int64) (*model.KnowledgeDocument, error)FindDocumentByCondition(ctx context.Context, opts *entity.WhereDocumentOpt) ([]*model.KnowledgeDocument, int64, error)DeleteDocuments(ctx context.Context, ids []int64) errorSetStatus(ctx context.Context, documentID int64, status int32, reason string) errorCreateWithTx(ctx context.Context, tx *gorm.DB, document []*model.KnowledgeDocument) errorUpdateDocumentSliceInfo(ctx context.Context, documentID int64) error
}// 文档切片仓储接口
type KnowledgeDocumentSliceRepo interface {Create(ctx context.Context, slice *model.KnowledgeDocumentSlice) errorUpdate(ctx context.Context, slice *model.KnowledgeDocumentSlice) errorDelete(ctx context.Context, slice *model.KnowledgeDocumentSlice) errorBatchCreateWithTX(ctx context.Context, tx *gorm.DB, slices []*model.KnowledgeDocumentSlice) errorBatchCreate(ctx context.Context, slices []*model.KnowledgeDocumentSlice) errorBatchSetStatus(ctx context.Context, ids []int64, status int32, reason string) errorDeleteByDocument(ctx context.Context, documentID int64) errorMGetSlices(ctx context.Context, sliceIDs []int64) ([]*model.KnowledgeDocumentSlice, error)ListPhotoSlice(ctx context.Context, opts *entity.WherePhotoSliceOpt) ([]*model.KnowledgeDocumentSlice, int64, error)FindSliceByCondition(ctx context.Context, opts *entity.WhereSliceOpt) ([]*model.KnowledgeDocumentSlice, int64, error)GetDocumentSliceIDs(ctx context.Context, docIDs []int64) (sliceIDs []int64, err error)GetSliceBySequence(ctx context.Context, documentID int64, sequence int64) ([]*model.KnowledgeDocumentSlice, error)IncrementHitCount(ctx context.Context, sliceIDs []int64) errorGetSliceHitByKnowledgeID(ctx context.Context, knowledgeID int64) (int64, error)GetLastSequence(ctx context.Context, documentID int64) (float64, error)
}

接口功能特点

  1. 分层仓储设计:将知识库、文档和文档切片的操作分别封装为独立接口,实现关注点分离
  2. 完整的CRUD操作:提供知识库及其关联资源的创建、读取、更新和删除功能
  3. 事务支持:通过InitTxUpdateWithTx等方法支持复杂的事务操作,确保数据一致性
  4. 灵活的查询能力:通过FindKnowledgeByConditionFindDocumentByCondition等方法支持复杂条件查询
  5. 批量操作优化:提供批量查询、批量创建和批量删除等操作,提高数据处理效率
  6. 状态管理:专门的SetStatus方法用于管理文档状态,支持知识管理的生命周期控制
  7. 解耦设计:通过接口抽象实现业务层与数据访问层的解耦,便于测试和扩展
  8. 代码生成支持:使用go:generate指令支持自动生成mock实现,提高测试覆盖率
  9. 性能优化:提供增量更新、条件过滤等机制优化查询性能
  10. 完整的切片管理:专门的切片仓储接口支持知识文档的切片操作,包括批量创建、状态管理和序列控制

5.2 数据访问对象(DAO)

KnowledgeDAO 实现

KnowledgeDAO是知识库数据访问的核心实现,负责与数据库直接交互,处理知识库和文档的持久化操作。

// KnowledgeDAO 知识库数据访问对象
type KnowledgeDAO struct {DB *gorm.DB
}// NewKnowledgeDAO 创建知识库DAO实例
func NewKnowledgeDAO(db *gorm.DB) *KnowledgeDAO {return &KnowledgeDAO{DB: db,}
}// CreateKnowledge 创建知识库
func (dao *KnowledgeDAO) CreateKnowledge(ctx context.Context, knowledge *knowledgeEntity.Knowledge) (string, error) {result := dao.DB.WithContext(ctx).Create(knowledge)if result.Error != nil {logs.CtxErrorf(ctx, "create knowledge failed, err: %v", result.Error)return "", result.Error}return knowledge.ID, nil
}// UpdateKnowledge 更新知识库
func (dao *KnowledgeDAO) UpdateKnowledge(ctx context.Context, knowledgeID string, updates map[string]interface{}) error {result := dao.DB.WithContext(ctx).Model(&knowledgeEntity.Knowledge{}).Where("id = ?", knowledgeID).Updates(updates)if result.Error != nil {logs.CtxErrorf(ctx, "update knowledge failed, knowledgeID: %s, err: %v", knowledgeID, result.Error)return result.Error}if result.RowsAffected == 0 {return errors.New("knowledge not found")}return nil
}// GetKnowledge 获取知识库
func (dao *KnowledgeDAO) GetKnowledge(ctx context.Context, knowledgeID string) (*knowledgeEntity.Knowledge, error) {var knowledge knowledgeEntity.Knowledgeresult := dao.DB.WithContext(ctx).Where("id = ?", knowledgeID).First(&knowledge)if result.Error != nil {if errors.Is(result.Error, gorm.ErrRecordNotFound) {return nil, errors.New("knowledge not found")}logs.CtxErrorf(ctx, "get knowledge failed, knowledgeID: %s, err: %v", knowledgeID, result.Error)return nil, result.Error}return &knowledge, nil
}// CreateDocument 创建文档
func (dao *KnowledgeDAO) CreateDocument(ctx context.Context, document *knowledgeEntity.Document) (string, error) {result := dao.DB.WithContext(ctx).Create(document)if result.Error != nil {logs.CtxErrorf(ctx, "create document failed, err: %v", result.Error)return "", result.Error}return document.ID, nil
}// UpdateDocument 更新文档
func (dao *KnowledgeDAO) UpdateDocument(ctx context.Context, documentID string, updates map[string]interface{}) error {result := dao.DB.WithContext(ctx).Model(&knowledgeEntity.Document{}).Where("id = ?", documentID).Updates(updates)if result.Error != nil {logs.CtxErrorf(ctx, "update document failed, documentID: %s, err: %v", documentID, result.Error)return result.Error}if result.RowsAffected == 0 {return errors.New("document not found")}return nil
}// GetDocument 获取文档
func (dao *KnowledgeDAO) GetDocument(ctx context.Context, documentID string) (*knowledgeEntity.Document, error) {var document knowledgeEntity.Documentresult := dao.DB.WithContext(ctx).Where("id = ?", documentID).First(&document)if result.Error != nil {if errors.Is(result.Error, gorm.ErrRecordNotFound) {return nil, errors.New("document not found")}logs.CtxErrorf(ctx, "get document failed, documentID: %s, err: %v", documentID, result.Error)return nil, result.Error}return &document, nil
}// ListDocuments 获取文档列表
func (dao *KnowledgeDAO) ListDocuments(ctx context.Context, knowledgeID string, query map[string]interface{}, page, pageSize int32) ([]*knowledgeEntity.Document, int64, error) {var documents []*knowledgeEntity.Documentvar total int64// 构建查询条件db := dao.DB.WithContext(ctx).Model(&knowledgeEntity.Document{}).Where("knowledge_id = ?", knowledgeID)// 添加额外查询条件for key, value := range query {db = db.Where(key, value)}// 计算总数if err := db.Count(&total).Error; err != nil {logs.CtxErrorf(ctx, "count documents failed, err: %v", err)return nil, 0, err}// 计算偏移量offset := (page - 1) * pageSize// 执行查询if err := db.Order("created_at DESC").Offset(int(offset)).Limit(int(pageSize)).Find(&documents).Error; err != nil {logs.CtxErrorf(ctx, "list documents failed, err: %v", err)return nil, 0, err}return documents, total, nil
}

实现特点

  1. GORM集成:使用GORM框架进行数据库操作,简化CRUD操作
  2. 参数验证:在更新操作后检查受影响的行数,确保数据存在
  3. 错误处理:完善的错误捕获和日志记录,便于问题排查
  4. 上下文传递:通过context进行请求上下文传递,支持请求追踪
  5. 灵活查询:支持条件查询、分页查询和排序,满足各种查询需求
  6. 错误类型区分:区分记录不存在和其他数据库错误类型

5.3 仓库实现类

仓库实现类将领域服务的调用转换为数据访问层的操作,实现了业务实体与数据对象的转换。

// KnowledgeRepoImpl 知识库仓储实现
type KnowledgeRepoImpl struct {knowledgeDAO *KnowledgeDAOidGenerator  idgen.IDGenerator
}// NewKnowledgeRepo 创建知识库仓储实例
func NewKnowledgeRepo(knowledgeDAO *KnowledgeDAO, idGenerator idgen.IDGenerator) KnowledgeRepo {return &KnowledgeRepoImpl{knowledgeDAO: knowledgeDAO,idGenerator:  idGenerator,}
}// CreateKnowledge 创建知识库
func (r *KnowledgeRepoImpl) CreateKnowledge(ctx context.Context, knowledge *knowledgeEntity.Knowledge) (int64, error) {// 生成IDif knowledge.ID == 0 {knowledge.ID = r.idGenerator.GenID()}// 设置默认时间now := time.Now().Unix()if knowledge.CreatedAt == 0 {knowledge.CreatedAt = now}if knowledge.UpdatedAt == 0 {knowledge.UpdatedAt = now}return r.knowledgeDAO.CreateKnowledge(ctx, knowledge)
}// UpdateKnowledge 更新知识库
func (r *KnowledgeRepoImpl) UpdateKnowledge(ctx context.Context, knowledgeID int64, updates map[string]interface{}) error {return r.knowledgeDAO.UpdateKnowledge(ctx, knowledgeID, updates)
}// CreateDocument 创建文档
func (r *KnowledgeRepoImpl) CreateDocument(ctx context.Context, document *knowledgeEntity.Document) (int64, error) {// 生成IDif document.ID == 0 {document.ID = r.idGenerator.GenID()}// 设置默认时间now := time.Now().Unix()if document.CreatedAt == 0 {document.CreatedAt = now}if document.UpdatedAt == 0 {document.UpdatedAt = now}return r.knowledgeDAO.CreateDocument(ctx, document)
}// UpdateDocument 更新文档
func (r *KnowledgeRepoImpl) UpdateDocument(ctx context.Context, documentID int64, updates map[string]interface{}) error {return r.knowledgeDAO.UpdateDocument(ctx, documentID, updates)
}

实现特点

  1. ID生成:通过ID生成器为实体分配唯一ID
  2. 时间管理:自动设置创建和更新时间
  3. 数据转换:在领域实体和数据对象之间进行转换
  4. 依赖注入:通过构造函数注入必要的依赖组件
  5. 简洁实现:主要负责调用DAO层方法,保持实现简洁

5.4 数据模型

知识库相关的数据模型定义了数据库表结构和字段映射关系。

// Knowledge 知识库表模型
type Knowledge struct {ID             int64          `gorm:"primaryKey;autoIncrement" json:"id"`SpaceID        int64          `gorm:"not null;index" json:"space_id"`OwnerID        int64          `gorm:"not null;index" json:"owner_id"`Name           string         `gorm:"size:255;not null;index:idx_name,length:100" json:"name"`Description    string         `gorm:"type:text" json:"description"`CoverImage     string         `gorm:"size:255" json:"cover_image"`Tags           datatypes.JSON `gorm:"type:json" json:"tags"`Settings       datatypes.JSON `gorm:"type:json" json:"settings"`Version        string         `gorm:"size:255;index:idx_version" json:"version"`CreatedAt      int64          `gorm:"autoCreateTime" json:"created_at"`UpdatedAt      int64          `gorm:"autoUpdateTime;index:idx_updated_at" json:"updated_at"`LastEditorID   int64          `json:"last_editor_id"`EditCount      uint           `json:"edit_count"`LockStatus     int            `gorm:"default:0;index:idx_lock_status" json:"lock_status"`LockExpireTime int64          `json:"lock_expire_time"`
}// TableName 指定表名
func (Knowledge) TableName() string {return "knowledge"
}// Document 文档表模型
type Document struct {ID          int64          `gorm:"primaryKey;autoIncrement" json:"id"`KnowledgeID int64          `gorm:"not null;index:idx_knowledge_id" json:"knowledge_id"`DocumentID  string         `gorm:"size:64;not null;index:idx_document_id" json:"document_id"`Title       string         `gorm:"size:255;not null;index:idx_title,length:100" json:"title"`Content     string         `gorm:"type:longtext" json:"content"`ContentHash string         `gorm:"size:64" json:"content_hash"`Metadata    datatypes.JSON `gorm:"type:json" json:"metadata"`Version     string         `gorm:"size:255" json:"version"`CreatedAt   int64          `gorm:"autoCreateTime" json:"created_at"`UpdatedAt   int64          `gorm:"autoUpdateTime;index:idx_updated_at" json:"updated_at"`LastEditorID int64         `json:"last_editor_id"`
}// TableName 指定表名
func (Document) TableName() string {return "knowledge_document"
}// 确保知识库和文档的唯一约束
func (d *Document) TableName() string {// 知识库文档表有复合唯一索引: uniq_knowledge_document (knowledge_id, document_id)return "knowledge_document"
}

模型特点

  1. 编辑冲突控制:Version字段用于乐观锁和编辑冲突检测
  2. 锁定管理:LockStatus和LockExpireTime字段支持编辑锁定管理
  3. 编辑审计:LastEditorID和EditCount字段跟踪编辑历史
  4. 全文存储:Content字段使用longtext类型存储大型文档内容
  5. 变更检测:ContentHash字段用于快速检测文档内容变更
  6. JSON支持:Tags、Settings和Metadata字段使用JSON类型,支持灵活编辑
  7. 索引优化:为name、title、updated_at等常用查询字段添加索引
  8. 唯一约束:知识文档表有复合唯一索引(knowledge_id, document_id),防止编辑时冲突

5.5 数据库表结构

knowledge表

字段名数据类型约束描述
idbigintPRIMARY KEY AUTO_INCREMENT知识库ID
space_idbigintNOT NULL, INDEX工作空间ID
owner_idbigintNOT NULL, INDEX所有者ID
namevarchar(255)NOT NULL, INDEX(name(100))知识库名称
descriptiontext知识库描述
cover_imagevarchar(255)封面图片URL
tagsjson知识库标签
settingsjson知识库设置
versionvarchar(255)INDEX版本号(用于编辑冲突)
created_atbigintNOT NULL创建时间戳(毫秒)
updated_atbigintNOT NULL, INDEX更新时间戳(毫秒)
last_editor_idbigint最后编辑者ID
edit_countint unsigned编辑次数
lock_statusintDEFAULT 0, INDEX锁定状态(0=未锁定,1=已锁定)
lock_expire_timebigint锁定过期时间戳

knowledge_document表

字段名数据类型约束描述
idbigintPRIMARY KEY AUTO_INCREMENT文档ID
knowledge_idbigintNOT NULL, INDEX所属知识库ID
document_idvarchar(64)NOT NULL, INDEX文档标识
titlevarchar(255)NOT NULL, INDEX(title(100))文档标题
contentlongtext文档内容
content_hashvarchar(64)内容哈希(用于变更检测)
metadatajson文档元数据
versionvarchar(255)文档版本号
created_atbigintNOT NULL创建时间戳(毫秒)
updated_atbigintNOT NULL, INDEX更新时间戳(毫秒)
last_editor_idbigint最后编辑者ID

5.6 数据访问层编辑操作特点

知识库编辑操作特点

  1. 版本控制:使用version字段实现乐观锁,防止并发编辑冲突
  2. 编辑锁定:支持数据库级别的编辑锁定机制,避免编辑冲突
  3. 事务保证:所有编辑操作在事务中执行,确保数据一致性
  4. 内容哈希:通过content_hash字段快速检测文档内容变更
  5. 部分更新:支持字段级别的部分更新,提高编辑效率
  6. 索引优化:为常用编辑查询字段添加索引,提升性能
  7. 审计追踪:记录最后编辑者和编辑时间,支持操作审计
  8. 编辑统计:维护edit_count字段,跟踪编辑频率

编辑操作的数据访问流程

在编辑知识库的场景中,数据访问层的操作流程如下:

  1. 事务开始:开启数据库事务,确保操作原子性
  2. 版本检查:验证传入的version字段,检测编辑冲突
  3. 数据更新:更新知识库/文档数据,包括内容和元数据
  4. 版本递增:更新version字段,防止后续编辑冲突
  5. 编辑统计:更新last_editor_id和edit_count等统计信息
  6. 事务提交:所有操作成功后提交事务
  7. 错误处理:任何步骤失败时回滚事务并返回错误

数据访问层编辑操作总结

  1. 编辑事务性:所有编辑操作在事务中执行,确保数据一致性
  2. 多表协同:同时维护知识库和文档的编辑状态
  3. 冲突检测:通过版本控制和锁定机制防止编辑冲突
  4. 编辑安全:完善的权限验证和错误处理机制
  5. 内容完整性:通过content_hash确保编辑内容的一致性
  6. 编辑性能:合理的索引设计和部分更新支持,确保高效编辑
  7. 可扩展性:模块化设计支持未来编辑功能的扩展
  8. 事务更新:UpdateWithTX方法支持事务操作,确保数据一致性
  9. 参数构建:智能构建更新参数,优化数据库操作
  10. 数据验证:更新前进行数据验证,确保数据有效性
  11. 错误处理:完善的错误处理和日志记录
  12. 缓存管理:支持缓存的删除操作,保持数据一致性
http://www.dtcms.com/a/446434.html

相关文章:

  • 做移动网站点击软件吗网站后台管理系统安装
  • 网站统计排名哪家网站雅虎全球购做的好
  • 福彩体彩10月5号数据分享
  • Java——文件相关知识
  • Hadess入门到实战(7) - 如何管理Pypi(Python)制品
  • RDMA 技术解析(1):RDMA 技术三国志 ——IB、RoCE、iWARP 的选型博弈
  • wordpress文章提交江苏网站快速排名优化
  • 【自记】MaxCompute中的冒烟测试
  • Linux : 动静态库制作、ELF格式
  • 如何制作电脑公司网站关键词怎么优化到百度首页
  • seo的全称是什么广州关于进一步优化
  • 南京设计网站免费做网站tk
  • YOLO算法原理详解系列 第004期-YOLOv4 算法原理详解
  • 高层次综合的基础-vivado_hls第二章
  • 市面上常见显示屏接口与对应的引脚
  • 天津网站建设方案维护网站开发实践教程
  • 网站源码出售wordpress 3.2.1
  • 西安网站注册个人建设网站成本
  • 初识Protobuf
  • 网站排名首页前三位什么网站百度收录好
  • 现在做什么网站好易搭应用快速开发平台
  • 站长之家商城佛山网站建设十年乐云seo
  • 网站挂黑链工具适合做网站开发的电脑配置
  • 美食网站设计规划书分类网站建设与开发
  • 做网站代理需要办什么营业执照大型手机网站制作
  • 深入理解CAS
  • 响应式网站开发方法系统首页设计
  • 华清远见25072班C++学习假期10.5作业
  • 【系统分析师】2024年下半年真题:综合知识-答案及详解(回忆版)
  • 网站代码的重点内容是什么wordpress 批量建站