如何使用Mongoose查找子文档?

时间:2014-07-11 08:36:54

标签: javascript node.js mongodb mongoose

我正在尝试使用mongoose在我的User集合中获取子文档。我在其官方网站上关注了Mongoose Sub Document。它写道:

每个文档都有一个_id。 DocumentArrays有一个特殊的id方法,用于通过_id查找文档。

var doc = parent.children.id(id);

这是我的代码:

exports.editAccount = function(req, res) {
    var user = new User(req.user);
    var newAccount = new Account(req.body);
    console.log("Account:" + newAccount._id); // Gave me 53bf93d518254f880c000009
    var account = user.accounts.id(newAccount._id);
    console.log("Account" + account); // Never been printed
};

console.log("Account" + account);从未打印过。我不知道发生了什么。我试过很多不同的方法,然而,仍然无法弄明白。任何帮助将不胜感激。


用户收藏:

{
    "__v" : 1,
    "_id" : ObjectId("53bcf3e6fbf5adf10c000001"),
    "accounts" : [
        {
            "accountId" : "123456789",
            "type" : "Saving account",
            "balance" : 100,
            "_id" : ObjectId("53bf93d518254f880c000009")
        }
    ]
}

1 个答案:

答案 0 :(得分:1)

不太清楚你是如何定义Schema的,或者甚至是模型实例,但实际上你需要的只是:

var accountSchema = new Schema({
    "accountId": String,
    "type": { "type": String, "enum": ["Saving Account", "Checking Account"] },
    "balance": { "type": Number, "default": 0 }
]);

var userSchema = new Schema({
    "accounts": [accountSchema]
]);

var User = mongoose.model( "User", userSchema );

然后,当您想要向用户添加一个帐户时,假设您的输入与第一个变量声明匹配:

var input = {
    "accountId": "123456789",
    "type": "Savings Account",
};

User.findByIdAndUpdate(
    userId,
    { "$push": { "accounts": input } },
    function(err,user) {
        // work with result in here
    }
);

这确实绕过了验证和其他钩子之类的东西,但在与MongoDB通信方面效率更高。

如果您确实需要验证和/或其他功能,那么您使用.find()变体并发布.save()方法。

User.findById(userId,function(err,user) {
    if (err) throw err;    // or handle better

    user.accounts.push( input );
    user.save(function(err, user) {
        // more handling
    });
]);

要修改文档,那么你也会做同样的事情。通过最有效的MongoDB方式:

var input = {
    accountId: "123456789",
    amount: 100
};

User.findOneAndUpdate(
    { "_id": userId, "accounts.accountId": input.accountId },
    { "$inc": { "accounts.$.balance": input.amount } },
    function(err,user) {
        // handle result
    }
);

或者再次需要Mongoose钩子和/或验证来应用:

User.findById(userId,function(err,user) {
    if (err) throw err;   // or handle otherwise

    user.accounts.forEach(function(account) {
        if ( account.accountId === input.accountId )
            account.balance += input.balance;
    });

    user.save(function(err,user) {
        // handle things
    });
);

请记住,这些东西都是"数组",您可以使用MongoDB方式或JavaScript方式处理它们。这取决于你选择的地方"验证"你的意见。


更多代码说明用法不正确的地方:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/child');


var accountSchema = new Schema({
  "accountId": String,
  "type": { "type": String },
  "balance": { "type": Number, "default": 0 }
});

var userSchema = new Schema({
  "accounts": [accountSchema]
});

var User = mongoose.model( "User", userSchema );

async.waterfall([

  function(callback) {
    User.create({},function(err,user) {
      if (err) throw err;
      console.log(
        "Created:\n%s\n",
        JSON.stringify( user, undefined, 4 )
      );
      callback(null,user);
    });
  },

  function(user,callback) {
    var account = user.accounts.create({
      "accountId": "123456789",
      "type": "Savings"
    });

    console.log(
      "Account is:\n%s\n",
      JSON.stringify( account, undefined, 4 )
    );

    console.log(
      "User is still:\n%s\n",
      JSON.stringify( user, undefined, 4 )
    );

    user.accounts.push( account );

    console.log(
      "User Changed:\n%s\n",
      JSON.stringify( user, undefined, 4 )
    );

    User.findById(user.id,function(err,saved) {
      if (err) throw err;
      console.log(
        "Persisted is still:\n%s\n",
        saved
      );
      user.save(function(err,user) {
        if (err) throw err;
        callback(null,user,account);
      });
    });

  },

  function(user,account,callback) {

    User.findById(user.id,function(err,saved) {
      if (err) throw err;
      console.log(
        "Persisted is now:\n%s\n",
        saved
      );

      var item = user.accounts.id(account.id);
      console.log(
        "Item is:\n%s\n",
        item
      );
      callback();
    });
  }
],function(err) {
  process.exit();
});

结果:

Created:
{
    "__v": 0,
    "_id": "53c08ab51083d1fe3852becc",
    "accounts": []
}

Account is:
{
    "accountId": "123456789",
    "type": "Savings",
    "_id": "53c08ab51083d1fe3852becd",
    "balance": 0
}

User is still:
{
    "__v": 0,
    "_id": "53c08ab51083d1fe3852becc",
    "accounts": []
}

User Changed: 
{
    "__v": 0,
    "_id": "53c08ab51083d1fe3852becc",
    "accounts": [
        {
            "accountId": "123456789",
            "type": "Savings",
            "_id": "53c08ab51083d1fe3852becd",
            "balance": 0
        }
    ]
}

Persisted is still:
{ _id: 53c08ab51083d1fe3852becc, __v: 0, accounts: [] }

Persisted is now:
{ _id: 53c08ab51083d1fe3852becc,
  __v: 1,
  accounts:
  [ { accountId: '123456789',
      type: 'Savings',
      _id: 53c08ab51083d1fe3852becd,
      balance: 0 } ] }

Item is:
{ accountId: '123456789',
  type: 'Savings',
  _id: 53c08ab51083d1fe3852becd,
  balance: 0 }