Push items into mongo array via mongoose

2018-12-31 12:12发布

问题:

I\'ve scoured SO a good bit looking for the answer but I\'m sure that I\'m lost for the right words to describe what I\'m after.

Basically I have a mongodb collection called \'people\' The schema for that collection is as follows:

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

Now, I have a very basic express application that connects to the database and successfully creates \'people\' with an empty friends array.

In a secondary place in the application, a form is in place to add friends. The form takes in firstName and lastName and then POSTs with the name field also for reference to the proper people object.

What I\'m having a hard time doing is creating a new friend object and then \"pushing\" it into the friends array.

I know that when I do this via the mongo console I use the update function with $push as my second argument after the lookup criteria, but I can\'t seem to find the appropriate way to get mongoose to do this.

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

UPDATE: So, Adrian\'s answer was very helpful. The following is what I did in order to accomplish my goal.

in my app.js file, I set a temporary route using

app.get(\'/addfriend\', users.addFriend);

where in my users.js file I have

exports.addFriend = function (req, res, next)
{
var friend = {\"firstName\": req.body.fName, \"lastName\": req.body.lName};
Users.findOneAndUpdate({name: req.user.name}, {$push: {friends: friend}});
};

回答1:

Assuming, var friend = { firstName: \'Harry\', lastName: \'Potter\' };

There are two options you have:

Update the model in-memory, and save (plain javascript array.push):

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

or

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

I always try and go for the first option when possible, because it\'ll respect more of the benefits that mongoose gives you (hooks, validation, etc.).

However, if you are doing lots of concurrent writes, you will hit race conditions where you\'ll end up with nasty version errors to stop you from replacing the entire model each time and losing the previous friend you added. So only go to the latter when it\'s absolutely necessary.



回答2:

The $push operator appends a specified value to an array.

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

$push adds the array field with the value as its element.

Above answer fulfils all the requirements, but I got it working by doing the following

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


回答3:

Use $push to update document and insert new value inside an array.

find:

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

result:

{
    \"_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
}

update:

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

result:

{
    \"_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
}


回答4:

I ran into this issue as well. My fix was to create a child schema. See below for an example for your models.

---- Person model

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);

***Important: SingleFriend.schema -> make sure to use lowercase for schema

--- Child schema

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

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

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