Mongoose 添加到对象以填充猫鼬模型中的种群

Mongoose 添加到对象以填充猫鼬模型中的种群,mongoose,mongoose-populate,Mongoose,Mongoose Populate,我是刚接触猫鼬的,而且我的脑袋也不熟悉猫鼬的种群。我的模式看起来像 var ProjectSchema = new Schema({ name: { type: String, default: '', required: 'Please fill Project name', trim: true }, created: { type: Date, default: Date

我是刚接触猫鼬的,而且我的脑袋也不熟悉猫鼬的种群。我的模式看起来像

var ProjectSchema = new Schema({
    name: {
        type: String,
        default: '',
        required: 'Please fill Project name',
        trim: true
    },
    created: {
        type: Date,
        default: Date.now
    },
    topics: [{
        type: Schema.ObjectId,
        ref: 'Topic'
    }]
});
当我查询项目时,我使用.populate('topics'),它工作正常。填充项目时,“主题”属性将保存实际对象而不是引用

另外,该主题没有项目参考(我发现在MongoDB中很难维护resiprocal关系)


我的问题是:当我想向项目添加主题对象时。是否添加ObjectId或对象本身?

如果主题架构具有项目引用,则只需保存ObjectId,因为将引用保存到其他文档的方式与通常保存属性的方式相同,只需指定_id值:

var topicSchema = Schema({
    _author : { type: Schema.ObjectId, ref: 'Project' },
    title    : String    
});

var Topic  = mongoose.model('Topic', topicSchema);
var Project = mongoose.model('Project', projectSchema);

var my_project = new Project({ name: 'Test Project' });

my_project.save(function (err) {
    if (err) return handleError(err);

    var topic1 = new Topic({
        title: "My Topic",
        _author: my_project._id    // assign the _id from the project
    });

    topic1.save(function (err) {
        if (err) return handleError(err);
        // thats it!
    });
});
有关更多详细信息,请参阅


--编辑--

如果主题架构没有项目引用,则需要推送对象本身:

var Topic  = mongoose.model('Topic', topicSchema);
var Project = mongoose.model('Project', projectSchema);

var my_project = new Project({ name: 'Test Project' });
var topic1 = new Topic({
    title: "My Topic"    
});

my_project.stories.push(topic1);
my_project.save(callback);

我看到了这个问题和给出的答案,但我不认为它真的解释了你的问题,所以我认为这里有些东西是值得的

如所提供的模式所示,“topics”属性是一个“referenced array”,这基本上意味着它将保存对位于另一个集合中的文档的“reference”(或者本质上是一个
ObjectId
值)。mongoose的“模式”定义将其与对象所在的“关联”模型联系在一起,您应该知道

提出的问题是“我是推送对象,还是只推送
\u id
值”,这本身就引发了一些关于“您在这里真正想做什么”的问题

最后,以下面的代码示例为例(假定模型和模式都已定义):

var project=newproject({“name”:“something”});
var topic=新主题({“name”:“something”});
project.topics.push(主题);//这实际上只是添加了_id,因为它是一个ref
//更多用于在其集合中保存主题和项目的代码
因此,根据代码中的注释,mongoose实际上只将“_id”值添加到父文档中,即使您要求它“推送”整个“对象”。它只是通过提供给模型的模式接口来解决“这就是您想要做的”。在代码中真正做到这一点并不难,但只是为了让您了解底层机制

您也可以从创建的对象中“使用
\u id
值”(为了安全起见保存后),然后通过类似的方式将其添加到数组中。结果大致相同:

var project=newproject({“name”:“something”});
//是的,我们保存了项目对象,但后来。。。
var topic=新主题({“name”:“something”});
保存(函数(错误,主题){
if(err)throw(err)://或更好的处理
project.topics.push(topic.\u id);//显式
});
这种方法很好,当然前提是通过某种形式,在处理
项目
主题
时,您实际上拥有“内存中的对象”,以及适当的数据

另一方面,让我们假设
Project
表示集合中的对象,尽管您知道它是
\u id
值或其他表示属性的“唯一”值,但该对象数据实际上并未通过
.findOne()
操作类型或类似操作从数据库加载

然后,让我们假设您没有驻留在内存中的
项目
模型数据。那么如何添加新主题呢

这就是MongoDB的本机操作符发挥作用的地方。特别是,它当然类似于JavaScript中的
.push()
数组操作符,但具有特定的“服务器端”操作

如前所述,您没有加载
项目
模型数据,但希望通过将所需的
主题
对象“推”到
项目
对象集合中定义的某个对象(通过其标识符)来修改存储中的特定
项目
项:

var-topic=新主题({“name”:“something”});
保存(函数(错误,主题){
if(err)抛出err;//或更好的处理
Project.update(
{u id:projectd},
{“$push”:{
“主题”:主题。\u id
}},
功能(错误,未受影响){
//并在这里处理响应
}
);
})
“更新”机制可以是
.findOneAndUpdate()
或者甚至是
.findbyiandupdate()
,只要您认为合适(这些方法都会在默认情况下将修改过的对象返回到
.update()
不返回的位置),以实现您在此处操作的结果

与前面方法的主要区别在于,由于要修改的
项目
的对象不驻留在应用程序代码的内存中,因此您可以使用这些方法在服务器上对其进行修改。这可能是一件“好事”,因为您不需要仅为了修改而“加载”该数据。MongoDB操作符允许您
$push
数组内容,而无需先加载

这种方法实际上是在高事务处理系统中实现“并发更新”的最佳方法。原因是,在应用程序中的
.findOne()
或类似操作与最终的
.save()
操作的修改之间,“不能保证”在这些操作之间服务器存储上“没有数据被更改”

$push
操作符“确保”服务器上修改的数据在执行时保持“原样”,当然,添加到阵列中的新数据也是如此

这里的另一个显而易见的事情是,由于操作使用本地MongoDB操作符来实现这种效率,所以mongoose模式规则是以ByBased为基础的。所以你当然不能只是“p”