如何在查询Mongoose的Item时用Category名称替换存储的ID?
解决方案:将Item的categories ID替换为Category名称
下面提供几种可行的实现方式,无论是否使用mongoose-autopopulate都能满足需求:
方法一:优化现有mongoose-autopopulate配置
你当前已经配置了自动填充categories的name字段,此时查询返回的categories是包含_id和name的对象数组。如果要直接转为名称字符串数组,可以通过Schema的transform钩子在序列化时处理:
const schema = new Schema<Item>({ // 其他字段定义 categories: [ { type: Schema.Types.ObjectId, ref: 'Category', autopopulate: { select: 'name' } } ] }, { // 转JSON时自动转换categories为名称数组 toJSON: { transform(doc, ret) { ret.categories = ret.categories.map(cat => cat.name); return ret; } }, // 转JS对象时也生效(可选) toObject: { transform(doc, ret) { ret.categories = ret.categories.map(cat => cat.name); return ret; } } }); schema.plugin(autopopulate);
配置后,查询得到的Item对象在转为JSON或直接作为JS对象使用时,categories字段会自动变为对应的名称数组。
方法二:使用聚合查询(无需mongoose-autopopulate)
如果不想依赖自动填充插件,可以用Mongoose的聚合查询完成关联和字段转换:
Item.aggregate([ // 关联Category集合(注意:from的值是集合的实际名称,通常为模型名的小写复数形式) { $lookup: { from: 'categories', localField: 'categories', foreignField: '_id', as: 'categories' } }, // 将关联后的对象数组提取为名称数组 { $addFields: { categories: '$categories.name' } } ]).exec();
聚合查询的结果中,categories字段直接就是Category名称的数组。
方法三:定义虚拟字段
通过给Item Schema添加虚拟字段,也可以实现名称数组的获取,需要手动触发关联填充:
const schema = new Schema<Item>({ // 其他字段定义 categories: [ { type: Schema.Types.ObjectId, ref: 'Category' } ] }); // 定义返回名称数组的虚拟字段 schema.virtual('categoryNames', { ref: 'Category', localField: 'categories', foreignField: '_id', justOne: false, // 转换关联结果为名称数组 transform: (docs) => docs.map(doc => doc.name) }); // 查询时需要填充虚拟字段 Item.find().populate('categoryNames').exec().then(items => { items.forEach(item => { // 直接获取名称数组 console.log(item.categoryNames); // 若要替换原categories字段,可手动赋值 item.categories = item.categoryNames; }); });
内容的提问来源于stack exchange,提问作者Riadh Adrani
相关产品推荐
相关产品推荐

