请教站内各位专家:Typegoose 中如何使用 arrayFilters 筛选并更新深度嵌套的子文档数组信息
技术栈:NestJs + Typegoose
以下为:TS 类型定义及Typegoose 配置代码
@modelOptions({
schemaOptions: {
collection: 'xs',
strict: 'throw',
toJSON: { virtuals: true },
toObject: { virtuals: true },
},
})
export class X {
@prop({ required: true })
public _id!: Types.ObjectId;
@prop()
public name!: string;
@prop({
type: () => Array<Y>,
})
public ys: Array<Y>;
}
export class Y {
@prop({ required: true })
public _id!: Types.ObjectId;
@prop()
public name!: string;
@prop({
type: () => Array<Z>,
})
public zs: Array<Z>;
}
export class Z {
@prop({ required: true })
public _id!: Types.ObjectId;
@prop()
public name!: string;
}
以下为:Mongodb 数据库中的数据
x: {
_id: {
"$oid": '666a71e0e338f61c15dca0b4'
},
name: '...',
ys: [{
_id: {
"$oid": '674d7e35ddbff7015c1dc6b6'
},
name: '...',
zs: [{
_id: {
"$oid": '674f0131e6ebadbddd7636ac'
},
name: '...',
}]
}]
}
以下为:Typegoose 导入模型
import { ReturnModelType } from '@typegoose/typegoose';
constructor(@InjectModel(X) private readonly ModuleX: ReturnModelType<typeof X>) {}
我的第一个需求是:通过主文档 x、子文档ys的ID 号,修改子文档的名称(代码执行正确)
await this.ModuleX.findOneAndUpdate(
{ _id: new mongodb.Types.ObjectId('666a71e0e338f61c15dca0b4') },
{ $set: { 'ys.$[y].name': 'name' } },
{
arrayFilters: [
{ 'y._id': new mongodb.Types.ObjectId('674d7e35ddbff7015c1dc6b6') } }
],
},
);
我的第二个需求是:通过主文档 x、子文档ys 和孙文档zs 的ID 号,修改孙文档的名称
await this.ModuleX.findOneAndUpdate(
{ _id: new mongodb.Types.ObjectId('666a71e0e338f61c15dca0b4') },
{ $set: { 'ys.$[y].zs.$[z].name': 'name' } },
{
arrayFilters: [
{ 'y._id': new mongodb.Types.ObjectId('674d7e35ddbff7015c1dc6b6') }, { 'z._id': new mongodb.Types.ObjectId('674f0131e6ebadbddd7636ac') }
],
},
);
// 以上代码报以下错误:
[Nest] 19956 - 12/03/2024, 12:37:04 PM ERROR [ExceptionsHandler] Could not find path "ys.0.zs.0._id" in schema
注意:经检查,确认以下条件
数据路径实际是存在的,也就是 ys.0.zs.0._id 路径是正确的。因为以下代码在 Mongodb Compass 命令行中执行是正确的
db.xs.findOneAndUpdate( { _id: new mongodb.Types.ObjectId('666a71e0e338f61c15dca0b4') }, { $set: { 'ys.$[y].zs.$[z].name': 'xxx' } }, { arrayFilters: [{ 'y._id': new mongodb.Types.ObjectId('674d7e35ddbff7015c1dc6b6') }, { 'z._id': new mongodb.Types.ObjectId('674f0131e6ebadbddd7636ac') }] }, );使用以下方式,也可以执行成功
await this.ModuleX.collection.findOneAndUpdate( { _id: new mongodb.Types.ObjectId('666a71e0e338f61c15dca0b4') }, { $set: { 'ys.$[y].zs.$[z].name': 'xxx' } }, { arrayFilters: [{ 'y._id': new mongodb.Types.ObjectId('674d7e35ddbff7015c1dc6b6') }, { 'z._id': new mongodb.Types.ObjectId('674f0131e6ebadbddd7636ac') }] }, );只有以下方式不能成功
await this.ModuleX.findOneAndUpdate( { _id: new mongodb.Types.ObjectId('666a71e0e338f61c15dca0b4') }, { $set: { 'ys.$[y].zs.$[z].name': 'name' } }, { arrayFilters: [ { 'y._id': new mongodb.Types.ObjectId('674d7e35ddbff7015c1dc6b6') }, { 'z._id': new mongodb.Types.ObjectId('674f0131e6ebadbddd7636ac') }] }, );第一个需求中的代码已经证明了,通过 ys ID 单一条件可以正确的找到并修改
Typegoose 已经升级到最新版本:v 12.9.1