简体   繁体   中英

Mongoose: How to update an existing element in array?

I was wondering if there is a better way to update an existing element in an array instead of fetching database three times. If you have any ideas I would appreciate it. Thank you!

    const creatStock = async (symbol, webApiData) => {
      try {
        // reversed array
        const webApiDataReversed = webApiData.reverse();

        const query = { symbol };
        const update = { $addToSet: { data: webApiDataReversed } };
        const options = { upsert: true, new: true };
        // create/update Stock
        const stockResult = await Stock.findOneAndUpdate(query, update, options);
        const lastElement = stockResult.data.length - 1;

        const updatePull = {
          $pull: { data: { date: stockResult.data[lastElement].date } },
        };
        // removes last date from data array
        await Stock.findOneAndUpdate(query, updatePull);
        // update Stock
        await Stock.findOneAndUpdate(query, update);
      } catch (ex) {
        console.log(`creatStock error: ${ex}`.red);
      }
    };

Schema

const ChildSchemaData = new mongoose.Schema({
  _id: false,
  date: { type: mongoose.Types.Decimal128 },
  open: { type: mongoose.Types.Decimal128 },
  high: { type: mongoose.Types.Decimal128 },
  low: { type: mongoose.Types.Decimal128 },
  close: { type: mongoose.Types.Decimal128 },
  volume: { type: mongoose.Types.Decimal128 },
});

const ParentSchemaSymbol = new mongoose.Schema({
  symbol: {
    type: String,
    unique: true,
  },
  // Array of subdocuments
  data: [ChildSchemaData],
});

module.exports.Stock = mongoose.model('Stock', ParentSchemaSymbol);

Output

在此处输入图像描述

Well, if you don't need to return the updated document, Please try this one - this will just return a write result, with this things can be achieved in one DB call:

const creatStock = async (symbol, webApiData) => {
    try {
        // reversed array
        const webApiDataReversed = webApiData.reverse();
        const query = { symbol };

        await Stock.bulkWrite([
            {
                updateOne:
                {
                    "filter": query,
                    "update": { $pop: { data: 1 } }
                }
            }, {
                updateOne:
                {
                    "filter": query,
                    "update": {
                        $addToSet: {
                            data: webApiDataReversed
                        }
                    }
                }
            }
        ])
    } catch (ex) {
        console.log(`creatStock error: ${ex}`.red);
    }
};

Ref: mongoDB bulkWrite

you can do like this way:

  const creatStock = async (symbol, webApiData) => {
  try {
    // reversed array
    const webApiDataReversed = webApiData.reverse();

    const query = { symbol };

    let stock =  await Stock.findOne(query);
    if(stock){
       let stockData = JSON.parse(JSON.stringify(stock.data));
       if(stockData.length>0){
          stockData.pop(); 
       }
       stockData.concat(webApiDataReversed);
       stock.data = stockData;
       await stock.save();
    }
  } catch (ex) {
      console.log(`creatStock error: ${ex}`.red);
  }

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