返回 AiToEarn
base.repository.ts
根目录 / project / aitoearn-backend / libs / channel-db / src / repositories / base.repository.ts
1 import { Pagination } from '@yikart/common'
2 import { DeleteOptions } from 'mongodb'
3 import {
4 FilterQuery,
5 FlattenMaps,
6 Model,
7 MongooseBaseQueryOptions,
8 QueryOptions,
9 Require_id,
10 UpdateQuery,
11 } from 'mongoose'
12
13 export type LeanDoc<T> = FlattenMaps<Require_id<T>>
14
15 export interface PaginationParams<TDocument> extends Pagination {
16 filter?: FilterQuery<TDocument>
17 options?: QueryOptions<TDocument>
18 }
19
20 export type CreateDocumentType<TDocument> = Partial<TDocument>
21
22 export type UpdateDocumentType<TDocument> = UpdateQuery<TDocument>
23
24 export class BaseRepository<TDocument> {
25 constructor(
26 protected readonly model: Model<TDocument>,
27 ) {}
28
29 /**
30 * 根据ID获取单个文档
31 */
32 async getById(id: string, options?: QueryOptions<TDocument>): Promise<LeanDoc<TDocument> | null> {
33 return await this.model.findById(id, undefined, options).lean({ virtuals: true }).exec() as LeanDoc<TDocument> | null
34 }
35
36 /**
37 * 创建新文档
38 */
39 async create(data: CreateDocumentType<TDocument>): Promise<LeanDoc<TDocument>> {
40 const created = new this.model(data)
41 const saved = await created.save()
42 return saved.toObject() as LeanDoc<TDocument>
43 }
44
45 /**
46 * 批量创建文档
47 */
48 async createMany(data: CreateDocumentType<TDocument>[]): Promise<LeanDoc<TDocument>[]> {
49 const docs = await this.model.insertMany(data, { lean: true })
50 return docs.map(doc => ({ ...doc, id: String(doc._id) })) as unknown as LeanDoc<TDocument>[]
51 }
52
53 /**
54 * 根据ID更新文档
55 */
56 async updateById(
57 id: string,
58 update: UpdateDocumentType<TDocument>,
59 options?: QueryOptions<TDocument>,
60 ): Promise<LeanDoc<TDocument> | null> {
61 return await this.model.findByIdAndUpdate(id, update, { new: true, ...options }).lean({ virtuals: true }).exec() as LeanDoc<TDocument> | null
62 }
63
64 /**
65 * 更新单个文档
66 */
67 protected async updateOne(
68 filter: FilterQuery<TDocument>,
69 update: UpdateDocumentType<TDocument>,
70 options?: QueryOptions<TDocument>,
71 ): Promise<LeanDoc<TDocument> | null> {
72 return await this.model.findOneAndUpdate(filter, update, { new: true, ...options }).lean({ virtuals: true }).exec() as LeanDoc<TDocument> | null
73 }
74
75 /**
76 * 根据ID删除文档
77 */
78 async deleteById(id: string, options?: QueryOptions<TDocument>): Promise<LeanDoc<TDocument> | null> {
79 return await this.model.findByIdAndDelete(id, options).lean({ virtuals: true }).exec() as LeanDoc<TDocument> | null
80 }
81
82 /**
83 * 删除单个文档
84 */
85 protected async deleteOne(filter: FilterQuery<TDocument>, options?: (DeleteOptions & MongooseBaseQueryOptions<TDocument>)) {
86 return await this.model.deleteOne(filter, options).exec()
87 }
88
89 /**
90 * 批量删除文档
91 */
92 protected async deleteMany(filter: FilterQuery<TDocument>): Promise<void> {
93 await this.model.deleteMany(filter).exec()
94 }
95
96 /**
97 * 分页查询
98 */
99 protected async findWithPagination(params: PaginationParams<TDocument>): Promise<readonly [LeanDoc<TDocument>[], number]> {
100 const { page, pageSize, filter = {}, options = {} } = params
101 const skip = (page - 1) * pageSize
102
103 const findOptions = { ...options, skip, limit: pageSize }
104
105 const [items, total] = await Promise.all([
106 this.model.find(filter, undefined, findOptions).lean({ virtuals: true }).exec() as Promise<LeanDoc<TDocument>[]>,
107 this.model.countDocuments(filter).exec(),
108 ])
109
110 return [items, total] as const
111 }
112
113 /**
114 * 查找单个文档
115 */
116 protected async findOne(filter: FilterQuery<TDocument>, options?: QueryOptions<TDocument>): Promise<LeanDoc<TDocument> | null> {
117 return await this.model.findOne(filter, undefined, options).lean({ virtuals: true }).exec() as LeanDoc<TDocument> | null
118 }
119
120 /**
121 * 查找多个文档
122 */
123 protected async find(filter: FilterQuery<TDocument> = {}, options?: QueryOptions<TDocument>): Promise<LeanDoc<TDocument>[]> {
124 return await this.model.find(filter, undefined, options).lean({ virtuals: true }).exec() as LeanDoc<TDocument>[]
125 }
126
127 /**
128 * 统计文档数量
129 */
130 protected async count(filter: FilterQuery<TDocument> = {}): Promise<number> {
131 return await this.model.countDocuments(filter).exec()
132 }
133
134 /**
135 * 检查文档是否存在
136 */
137 protected async exists(filter: FilterQuery<TDocument>): Promise<boolean> {
138 const result = await this.model.exists(filter).exec()
139 return result !== null
140 }
141 }
142
142 lines TYPESCRIPT