package store import "context" // 数据源清单查询(admin「数据源 & RAG」页做实用;此前该页图谱与权重全 mock)。 // 全平台口径 → WithoutTenant。Doc.KB 存的是 KB 名字(非 id),故按 (space_id, name) 关联。 // DatasourceKB 是一条知识库的清单行(含文档数与总字数、租户名)。 type DatasourceKB struct { ID string `json:"id"` Name string `json:"name"` // SpaceID 是检索作用域键的前半段:向量/全文/图谱三库里的库名是 "/" // (见 handler.scopedKB)。admin 检索试验台要按这个完整键定位库,故必须带出来。 SpaceID string `json:"space_id"` Kind string `json:"kind"` TenantID string `json:"tenant_id"` TenantName string `json:"tenant_name"` Owner string `json:"owner"` DocCount int64 `json:"doc_count"` TotalWords int64 `json:"total_words"` } // AllDatasources 列出全平台知识库 + 各库文档数/总字数(admin 数据源清单)。 func (p *Postgres) AllDatasources(ctx context.Context) []DatasourceKB { if p.db == nil { return nil } var out []DatasourceKB p.db.WithContext(WithoutTenant(ctx)).Table("sundynix_kb k"). Select("k.id, k.name, k.space_id, k.kind, k.tenant_id, coalesce(t.name,'') as tenant_name, k.owner, "+ "count(d.id) as doc_count, coalesce(sum(d.size),0) as total_words"). Joins("left join sundynix_doc d on d.kb = k.name and d.space_id = k.space_id and d.deleted_at is null"). Joins("left join sundynix_tenant t on t.id = k.tenant_id"). Where("k.deleted_at is null"). Group("k.id, k.name, k.space_id, k.kind, k.tenant_id, t.name, k.owner"). Order("doc_count desc, k.created_at desc"). Scan(&out) return out }