MongoDB嵌套Lookup查询返回空数组,求问题原因与解决方法
问题:MongoDB聚合Lookup查询返回空数组
我有new_users和workspaces两个集合,执行Lookup查询时,userData字段始终返回空数组。
集合实体定义
new_users集合(UserEntity)
export class UserEntity { @Prop({ required: false, type: Types.ObjectId, default: () => new ObjectId() }) _id?: Types.ObjectId; @Expose() @Prop({ default: '', trim: true, text: true }) firstName: string; @Expose() @Prop({ default: '', trim: true, text: true }) lastName: string; }
workspaces集合(WorkspaceEntity)
export class WorkspaceUsers { @Expose() @Prop({ type: () => [WorkspaceUserGroup] }) groups: WorkspaceUserGroup[]; @Expose() @Prop({ required: true, type: String, enum: WorkspaceRoleEnum }) workSpaceRole: WorkspaceRoleEnum; @Expose() @Prop({ required: true, type: String, ref: () => UserEntity }) userID: string; } export class WorkspaceEntity { @Prop({ required: false, type: Types.ObjectId, default: () => new ObjectId() }) _id?: Types.ObjectId; @Expose() @IsString() @IsDefined() @Prop({ required: true, trim: true }) name: string; @Expose() @IsOptional() @IsArray() @ValidateNested({ each: true }) @Type(() => WorkspaceUsers) @Prop({ required: false, type: () => [WorkspaceUsers], default: [] }) users: WorkspaceUsers[]; }
执行的聚合查询
const aggregationQuery: PipelineStage[] = []; aggregationQuery.push({ $unwind: '$users', }); aggregationQuery.push({ $lookup: { from: 'new_users', localField: 'users.userID', foreignField: '_id', as: 'userData', }, });
问题原因与解决办法
核心问题:类型不匹配
new_users集合的_id是ObjectId类型,但workspaces集合中users.userID被定义为String类型。MongoDB的$lookup是严格匹配,字符串格式的ID和ObjectId类型无法匹配,导致返回空数组。
解决步骤
1. 修正数据类型定义
把WorkspaceUsers中的userID类型改为Types.ObjectId,确保和UserEntity的_id类型一致:
export class WorkspaceUsers { // ...其他字段 @Expose() @Prop({ required: true, type: Types.ObjectId, ref: () => UserEntity }) userID: Types.ObjectId; }
2. 处理已有数据(如果存在历史数据)
如果数据库中已经存储了字符串格式的userID,需要将其转换为ObjectId:
// 执行这个更新操作,将字符串userID转为ObjectId db.workspaces.updateMany( {}, [ { $set: { "users.userID": { $map: { input: "$users", as: "user", in: { $toObjectId: "$$user.userID" } } } } } ] )
3. 可选:如果暂时无法修改类型,在查询中转换
如果不能直接修改数据类型,可以在聚合查询中把users.userID转换为ObjectId后再执行$lookup:
const aggregationQuery: PipelineStage[] = []; aggregationQuery.push({ $unwind: '$users', }); // 添加类型转换步骤 aggregationQuery.push({ $addFields: { "users.userID": { $toObjectId: "$users.userID" } } }); aggregationQuery.push({ $lookup: { from: 'new_users', localField: 'users.userID', foreignField: '_id', as: 'userData', }, });
内容的提问来源于stack exchange,提问作者Raju Ahmed
相关产品推荐
相关产品推荐

