0

我对 mongodb 非常陌生,并且遇到了一个基本问题。如何获取已创建文档的 ID 字段?我需要 ID,以便可以更新/添加新字段到文档。

//newProfile is an object, one string it holds is called school
if(Schools.find({name: newProfile.school}).fetch().length != 1){
    var school = {
        name: newProfile.school
    }
    Meteor.call('newSchool', school);

    //Method 1 (doesn't work)
    var schoolDoc = Schools.findOne({name: newProfile.school});
    Schools.update({_id: schoolDoc._id}, {$set: {enrolledStudents: Meteor.user()}});

    //Method 2?
    //Schools.update(_id: <what goes here?>, {$push: {enrolledStudents: Meteor.user()}});
}
else {
    //Schools.update... <add users to an existing school>
}

如果列出的学校尚不存在,我将创建一个新的学校文档。学校需要保存一个学生数组/列表(这是我遇到麻烦的地方)。如何将学生添加到新字段(称为注册学生)?

谢谢!

4

3 回答 3

0

对于您要执行的操作,无需获取_id. 当您使用 时,只需使用您的查询update切换。{_id: schoolDoc._id}看起来 using{name: newProfile.school}将起作用,假设您的其余代码执行您希望它执行的操作。

虽然这适用于普通的 Mongo 驱动程序,但我看到 Meteor 不允许您的更新查询是_idMeteor throws throwIfSelectorIsNotId exception

首先,确保你拉取了正确的文档,你可以尝试这样的事情:

var school_id = Schools.findOne({name: newProfile.school})._id;
Schools.update({_id: school_id}, { $push: { enrolledStudents: Meteor.user()}});

如果这不起作用,您将不得不进行一些调试以查看它不起作用的特别之处。

于 2013-11-08T21:18:15.783 回答
0

我相信由于客户端上 Meteor.call 的异步特性,您遇到了麻烦。

尝试做这样的事情:

// include on both server and client
Meteor.methods({
  newSchool: function (school) {
    var newSchoolId,
        currentUser = Meteor.user();
    if (!currentUser) throw new Meteor.Error(403, 'Access denied');

    // add some check here using the Meteor check/match function to ensure 'school'
    // contains proper data

    try {
      school.enrolledStudents = [currentUser._id];
      newSchoolId = Schools.insert(school);
      return newSchoolId;
    } catch (ex) {
      // handle appropriately
    }
  }
});


// on client
var schoolExists = false;

if (Schools.findOne({name: newProfile.school})) {
  schoolExists = true;
}

if (schoolExists) {
  var school = {
        name: newProfile.school
      };
  Meteor.call('newSchool', school, function (err, result) {
    if (err) {
      alert('An error occurred...');
    } else {
      // result is now the _id of the newly inserted record
    }
  })
} else {

}

在客户端和服务器上都包含该方法允许 Meteor 进行延迟补偿并立即在客户端上“模拟”插入,而无需等待服务器往返。但是您也可以只将方法保留在服务器端。

您应该在服务器上执行注册学生部分,以防止恶意用户弄乱您的数据。此外,您可能不希望实际将整个用户对象存储在注册学生数组中,而只是存储用户 _id。

于 2013-11-08T22:54:27.960 回答
0

我无法准确理解您要做什么。到目前为止,这是我的分析和理解,并提出了一些建议:

if(Schools.find({name: newProfile.school}).fetch().length != 1){

这会更有效率

if(Schools.find({name: new Profile.school}).count() != 1) {

Meteor.call('newSchool', school);

不知道你在这里做什么,除非你这将异步运行,这意味着当这个代码块的其余部分已经执行时,这个Meteor.call()函数很可能还没有在服务器端完成。

//Method 1 (doesn't work)
var schoolDoc = Schools.findOne({name: newProfile.school});
Schools.update({_id: schoolDoc._id}, {$set: {enrolledStudents: Meteor.user()}});

从代码顶部的 if 语句判断,数据库中有不止一所具有此名称的学校。所以我不确定schoolDoc变量是否是你所追求的记录。

于 2013-11-08T22:01:37.937 回答