我有一个叫做people的mongodb集合 其架构如下:

people: {
         name: String, 
         friends: [{firstName: String, lastName: String}]
        }

现在,我有一个非常基本的快速应用程序连接到数据库,并成功地创建“人”与一个空的朋友数组。

在应用程序的次要位置,有一个添加好友的表单。表单接收firstName和lastName,然后是带有名称字段的POSTs,同样用于引用适当的people对象。

我有一个困难的时间做的是创建一个新的朋友对象,然后“推”到朋友数组。

我知道当我通过mongo控制台这样做时,我使用$push作为查找标准后的第二个参数的更新函数,但我似乎找不到合适的方法让猫鼬这样做。

db.people.update({name: "John"}, {$push: {friends: {firstName: "Harry", lastName: "Potter"}}});

当前回答

$push操作符将指定的值附加到数组中。

{ $push: { <field1>: <value1>, ... } }

$push将数组字段的值添加为其元素。

上面的答案满足所有的要求,但我通过做以下工作

var objFriends = { fname:"fname",lname:"lname",surname:"surname" };
People.findOneAndUpdate(
   { _id: req.body.id }, 
   { $push: { friends: objFriends  } },
  function (error, success) {
        if (error) {
            console.log(error);
        } else {
            console.log(success);
        }
    });
)

其他回答

使用$push更新文档并在数组中插入新值。

发现:

db.getCollection('noti').find({})

查找结果:

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

更新:

db.getCollection('noti').findOneAndUpdate(
   { _id: ObjectId("5bc061f05a4c0511a9252e88") }, 
   { $push: { 
             graph: {
               "date" : ISODate("2018-10-24T08:55:13.331Z"),
               "count" : 3.0
               }  
           } 
   })

更新结果:

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }, 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 3.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

我也遇到过这个问题。我的解决办法是创建一个子模式。请参见下面的模型示例。

----人物模型

const mongoose = require('mongoose');
const SingleFriend = require('./SingleFriend');
const Schema   = mongoose.Schema;

const productSchema = new Schema({
  friends    : [SingleFriend.schema]
});

module.exports = mongoose.model('Person', personSchema);

* * *重要:SingleFriend。Schema ->确保模式使用小写

——子图式

const mongoose = require('mongoose');
const Schema   = mongoose.Schema;

const SingleFriendSchema = new Schema({
  Name: String
});

module.exports = mongoose.model('SingleFriend', SingleFriendSchema);

推到嵌套字段-使用点符号

对于任何想知道如何推到嵌套字段时,例如这个Schema。

const UserModel = new mongoose.schema({
  friends: {
    bestFriends: [{ firstName: String, lastName: String }],
    otherFriends: [{ firstName: String, lastName: String }]
  }
});

你只需使用点符号,像这样:

const updatedUser = await UserModel.update({_id: args._id}, {
  $push: {
    "friends.bestFriends": {firstName: "Ima", lastName: "Weiner"}
  }
});

另一种使用Mongoose将项目推入数组的方法是- $addToSet,如果你只想将唯一的项目推入数组。$push操作符只是简单地将对象添加到数组中,无论该对象是否已经存在,而$addToSet仅在对象不存在于数组中时才这样做,以免合并重复。

PersonModel.update(
  { _id: person._id }, 
  { $addToSet: { friends: friend } }
);

这将查找您要添加到数组中的对象。如果发现,则不执行任何操作。如果不是,则将其添加到数组中。

引用:

$addToSet MongooseArray.prototype.addToSet()

假设,var friend = {firstName: 'Harry', lastName: 'Potter'};

你有两个选择:

更新内存中的模型,并保存(简单的javascript array.push):

person.friends.push(friend);
person.save(done);

or

PersonModel.update(
    { _id: person._id }, 
    { $push: { friends: friend } },
    done
);

在可能的情况下,我总是尝试选择第一个选项,因为它会尊重mongoose给你的更多好处(钩子、验证等)。

然而,如果你正在进行大量的并发写操作,你就会遇到竞态条件,你最终会出现讨厌的版本错误,阻止你每次替换整个模型,并失去你之前添加的朋友。所以只有在绝对必要的情况下才会选择后者。