简体   繁体   中英

Accessing a sub-document ID after save - mongoose

When a user is created on my app their details are saved on the MongoDB using mongoose. The user schema contains sub-documents and I am trying to access the _id if the sub-document after using the user.save function.

The schema is below:

{
  name: String,
  email: String,
  address: String,
  phone:[
     {landLine: Number,
      mobile: Number}
   ]
}

I can access the name, email and address easily like so:

console.log(user.name + user.email + user.address)

I tried user.phone._id but it returns undefined . I think because phone is an array of objects.

 user.save(function(err) {
                if (err)
                    throw err;
                else {
                    console.log("user ID " + user._id); // SUCCESS!!
                    console.log("user sub-document ID " + user.phone._id); // UNDEFINED!!
                    return (null, user);
                }
            });

How can I access the _id of the sub-document inside the save function right after the user is created and saved into mongoDB?

There are a couple of approaches to getting this information, but personally I prefer the "atomic" modification method using$push .

The actual implementation here is helped by mongoose automatically including an ObjectId value which is "monotonic" and therefore always increasing in value. So this means that my method for handling this even works with a $sort modifier applied to the$push .

For example:

// Array of objects to add
var newNumbers = [
  { "landline": 55555555, "mobile": 999999999 },
  { "landline": 44455555, "mobile": 888888888 }
];

User.findOneAndUpdate(
  { "email": email },
  { "$push": { "phone": { "$each": newNumbers } } },
  { "new": true },
  function(err,user) {
    // The trick is to sort() on `_id` and just get the
    // last added equal to the length of the input
    var lastIds = user.phone.concat().sort(function(a,b) {
      return a._id > b._id
    }).slice(-newnumbers.length);
  }
)  

And even if you used a $sort modifier:

User.findOneAndUpdate(
  { "email": email },
  { "$push": { "phone": { "$each": newNumbers, "$sort": { "landline": 1 }  } } },
  { "new": true },
  function(err,user) {
    var lastIds = user.phone.concat().sort(function(a,b) {
      return a._id > b._id
    }).slice(-newnumbers.length);
  }
)  

That little trick of "sorting" a temporary copy on the _id value means that the "newest" items are always at the end. And you just need to take as many off the end as you added in the update.

The arguable point here is that it's actually mongoose that is inserting the _id values in the first place. So in fact those are being submitted in the request made to the server for each array item.

You "could" get fancy and use "hooks" to record those ObjectId values that were actually added to the new array members in the update statement. But it's really just a simple process of returning the last n "greatest" _id values from the array items anyway, so the more complex approach is not needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM