Mongoose如何使用username等非_id字段实现populate关联查询
问题解答
可以指定_id以外的字段作为Mongoose的populate关联字段,从Mongoose 4.5版本开始官方就支持该能力,具体实现方式如下:
第一步:调整Product Schema字段属性
因为你要关联User的username字段,所以Product中存储关联值的user字段类型需要和username类型保持一致,示例修改如下:
// 修改前(原来关联_id的写法) const productSchema = new mongoose.Schema({ // 其余字段省略 user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } }) // 修改后(关联username的写法) const productSchema = new mongoose.Schema({ // 其余字段省略 user: { type: String, // 和User的username字段类型匹配 ref: 'User' } })
注意:如果已有历史数据,Product的
user字段存储的是User的_id值,需要先做数据迁移,将值替换为对应用户的username,否则关联会失败。
第二步:两种关联查询写法
写法1:单次查询时指定关联字段
每次populate时传入配置对象,明确指定关联的目标字段:
Product.find() .populate({ path: 'user', foreignField: 'username', // 指定User模型中用于关联的字段为username select: 'username email' // 可选,指定要返回的User字段 }) .exec()
写法2:定义虚拟字段实现复用
如果需要在多处用到该关联,可以提前在Product Schema中定义虚拟关联字段,后续查询时直接populate即可:
// 在Product Schema定义后添加虚拟关联 productSchema.virtual('userInfo', { ref: 'User', // 关联的模型名 localField: 'user', // Product中存储关联值的字段 foreignField: 'username', // User中用于关联的目标字段 justOne: true // 因为username唯一,仅返回单条匹配结果 }) // 查询时直接调用,无需重复写配置 Product.find().populate('userInfo').exec()
额外注意事项
- 必须保证User的
username字段有唯一索引,避免出现一个关联值匹配多条User数据的问题 - 关联字段的类型必须完全匹配,比如User的
username是字符串类型,Product中存储关联值的字段也必须是字符串类型,否则Mongoose会因为类型不匹配跳过关联
内容的提问来源于stack exchange,提问作者Sarkar
相关产品推荐
相关产品推荐

