简体   繁体   中英

MongoDB array of objects update

I'm trying to update array of user information objects in mongoose. I've stored the user core information in the login process, I want to update some of user information when user tries to make an order. Here is the code for the model

const mongoose = require('mongoose');
const { ObjectId } = mongoose.Schema;

const userSchema = new mongoose.Schema(
  {
    name: String,
    email: {
      type: String,
      required: true,
      index: true,
    },
    role: {
      type: String,
      default: 'subscriber',
    },

    info: [
      { country: String },
      { city: String },
      { address: String },
      { phone: String },
      { birthdate: Date },
      { gender: { type: String, enum: ['Male', 'Female'] } },
    ],
    //   wishlist: [{ type: ObjectId, ref: "Product" }],
  },
  { timestamps: true }
);

module.exports = mongoose.model('User', userSchema);

In my controller I'm getting the data from front-end react app as JSON format, I want to push some data to info which is an array of objects in the users model above.

exports.createOrder = async (req, res) => {
  // Here I constract the data
  const { plan, service, fullName, country, city, address } = req.body.order;
  const { user_id } = req.body;

  // This the method I tried
  try {
    const user = await User.updateOne(
      {
        _id: user_id,
      },
      {
        $set: {
          'info.$.country': country,
          'info.$.city': city,
          'info.$.address': address,
        },
      },
      { new: true }
    );
    if (user) {
      console.log('USER UPDATED', user);
      res.json(user);
    } else {
      res.json((err) => {
        console.log(err);
      });
    }
    const newOrder = await new Order({
      orderPlan: plan,
      orderService: service,
      orderUser: user_id,
    }).save();
    console.log(newOrder);
    console.log(req.body);
  } catch (error) {
    console.log(error);
  }
};

I tired other solutions like

 const user = await User.updateOne(
      {
        _id: user_id,

        info: { $elemMatch: { country, city, address } },
      },
      { new: true }
    );

So do I need to reformat my model or there is a way to update this array of objects?

Option 1

Use $[]

db.collection.update(
  {},
  { $set: { "info.$[i].country": "a1" }} ,
  { arrayFilters: [ { "i.country": "a" } ] }
)

Demo - https://mongoplayground.net/p/UMxdpyiKpa9


Option 2

  • if you know the index

Demo - https://mongoplayground.net/p/41S7qs6cYPT

db.collection.update({},
{
  $set: {
    "info.0.country": "a1",
    "info.1.city": "b1",
    "info.2.address": "c1",
    "info.3.phone": "d1"
  }
})

Suggestions -

  • Change info schema to object instead of an array

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