我正在配置Mongoose以在现有的MongoDB上工作,该数据库具有以下两个集合:
用户-带有字段:
_id: ObjectId
name: String
org_id: ObjectId
组织-带有字段:
_id: ObjectId
name: String
我希望能够通过组织数据填充用户文档。
所以我创建了这两个模型:
const userSchema = new Schema({
name: String,
org_id: {
type: Schema.Types.ObjectId,
ref: 'Organization',
},
});
const User = mongoose.model('User', userSchema);
const organizationSchema = new Schema({
name: String,
code: String,
});
const Organization = mongoose.model('Organization', organizationSchema);
由于历史上从用户到组织的引用字段称为org_id
(而不只是organization
),因此组织代码中的用户总数为:
const user = await User.findById('5b213a69acef4ac0f886cdbc')
.populate('org_id')
.exec();
其中user.org_id
将由组织数据填充。当然,在填充方法和路径(即organization
)中都使用org_id
而不是user.organizationd
会更快乐。
在不更改现有文档的情况下实现此目标的正确方法是什么?
我可以创建Schema方法(而不是填充方法)和别名,但是我正在寻找更通用,更优雅的解决方案。
答案 0 :(得分:1)
我了解到您不想更改现有文档,但是对我来说,如果此字段名称没有任何意义,则需要进行重构。
更改字段名称,组织而不是org_id。
为此,您可以使用$ rename命令:MongoDB $rename
db.getCollection('users').updateMany({},{$rename: { "org_id": "organization" }});
此后,您可以呼叫 .populate('organization')。
如果不可能,我相信您会找到比 aliases 更好的解决方案。
猫鼬文档:Aliases
答案 1 :(得分:0)
我将按照您的代码进行操作。看起来您应用了以下代码:mongoose.Schema=Schema
您将组织模型嵌入到用户中。首先让我们提取每个用户的组织详细信息。
///导入用户和组织模型
const main=async ()=>{
const user=await User.findById("placeUserId")//we get the user
const populated=await user.populate("org_id").execPopulate()//we populated organization with all properties
console.log(populated.org_id) }
在上面的代码中,在userSchema中已经引用了org_id。我们刚刚到达org_id属性并提取了。这很简单。接下来,无需更改userSchema和organizationSchema中的任何代码,我将找到哪个用户属于哪个具有虚拟属性的组织。
虚拟属性允许我们在数据库中创建虚拟字段。之所以称为虚拟的,是因为我们什么都不会改变。这只是了解两个模型之间关系的一种方式。
为此,我们将在定义页面的页面上添加一些代码,然后定义了我在models / organization.js中假设的organizationSchema文件。此代码将描述虚拟字段。这是虚拟字段的一种模式。
// models / organization.js
organizationSchema.virtual('anyNameForField',{
ref:"User", //Organization is in relation with User
localField:"_id"//field that Organization holds as proof of relation
foreignField:"org_id"//field that User holds as proof of relation
})
现在是时候编写该功能以在组织内部查找用户了。
const reverse=async ()=>{
const organization=await Organization.findById("")
const populated=await organization.populate("anyNameForField").execPopulate()
console.log(populated.anyNameForField) //i gave a stupid name to bring your attention.
}
非常简单而优雅!