【问题标题】:Mongoose: findOneAndUpdate does not update an existing fieldMongoose:findOneAndUpdate 不更新现有字段
【发布时间】:2019-11-23 01:14:50
【问题描述】:

我正在尝试每分钟获取一个 Web API 数据到 MongoDB,保存它并在有任何更改时更新。问题是volume(每个字段)字段仅在新的date 添加到ChildSchemaData 时才更新(在新交易日开始后发生) - 子文档。所有这些数据都用于在前端构建每日(不是每小时/分钟)股票图表。而且我正在尝试从数据库中流式传输它,但是由于volume(以及子文档中的所有其他字段)未在数据库中更新,因此前端没有任何变化。我正在尝试实现更改 Streams MongoDB(来自数据库的数据流),所以我坚持从数据库中获取数据。任何帮助表示赞赏。谢谢!

Edit1$addToSet 运算符将一个值添加到数组中,除非该值已经存在,在这种情况下,$addToSet 对该数组没有任何作用。看起来这就是问题所在。我想知道是否有不同的运算符可以更新已经存在的值。

Edit2:我正在使用以下语法,但不确定它是否正确

const update = {
      $addToSet: { data: webApiData },
      $set: { 'data[0].$.volume': webApiData[0].volume },
    };  

因为它进入了相同的path,所以它不会工作

控制器

const creatStock = async (symbol, webApiData) => {
  try {
    const query = { symbol };
    const update = { $addToSet: { data: webApiData } };
    const options = { upsert: true, new: true };

    await Stock.findOneAndUpdate(query, update, options);
  } catch (ex) {
    console.log(`creatStock error: ${ex}`.red);
  }
};

架构

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,
  },
  // Array of subdocuments
  data: [ChildSchemaData],
});

【问题讨论】:

  • 那么你想更新子集合数组中的同一个元素吗?您如何确定要更新的元素?
  • 我想更新任何将要更改的元素。例如,如果卷保存为 100,然后下次获取 webApi 时,相同的卷将更新为 200,依此类推。我希望我没有让你太困惑
  • 我为我的问题发布了一个解决方案,但该解决方案的问题在于它会更新丢失旧数据的所有内容,我需要的是附加到现有数据。

标签: javascript node.js mongodb mongoose


【解决方案1】:

如果要更新数组中的元素,可以考虑positional operator: $ 并将该字段添加到更新查询中。

这标识了数组中要根据条件更新的元素。

使用等于 100 并设置为 200 的 volume 字段更新嵌入数组的示例:

db.getCollection("collection").findOneAndUpdate({
    id: 1,
    "data.volume": 100
}, 
    { $set: { "data.$.volume": 200 } 
});

【讨论】:

  • 我猜它会在当天工作,但到了第二天,我们需要在数组中附加一个新日期并更新当天的交易量,直到交易结束一天结束
  • 我想知道这是否可能const update = { $addToSet: { data: webApiData }, $set: { 'data[0].$.volume': webApiData[0].volume }, };
【解决方案2】:

此解决方案由srinivasy在以下链接link提供

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

    const position = await Stock.findOne(query);

    if (!position) {
      console.log('New stock'.green);
      return Stock.create({
        symbol,
        data: webApiDataReversed,
      });
    }

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

【讨论】:

  • 找到了解决方案。需要写一个答案来解释这个过程 - 将在早上更新。
猜你喜欢
  • 2018-01-15
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多