mongo $ push覆盖而不是添加到文档中的数组

时间:2018-10-04 22:09:50

标签: node.js mongodb

我正在尝试创建历史记录,以通过NodeJS更新Mongo DB中的文档。文档更新仅位于文档中的一个对象中,因此创建一系列历史值似乎很有意义。

但是,当我将$ push函数与db.collection.update()一起使用时,它只会更新索引为0的数组,而不会添加到数组中。

这是我所拥有的:

{
  _id: ID,
  odds: {
    spread: CURRENTSPREAD,
    total: CURRENTTOTAL,
    history: [
      0: {
        spread: PREVIOUSSPREAD1,
        total: PREVIOUSTOTAL1,
        date: DATEENTERED
      }
    ]
  }
}

这就是我想要的:

{
  _id: ID,
  odds: {
    spread: CURRENTSPREAD,
    total: CURRENTTOTAL,
    history: [
      0: {
        spread: PREVIOUSSPREAD1,
        total: PREVIOUSTOTAL1,
        date: DATEENTERED1
      },
      1: {
        spread: PREVIOUSSPREAD2,
        total: PREVIOUSTOTAL2,
        date: DATEENTERED2
      },
      ...,
      n: {
        spread: PREVIOUSSPREAD-N,
        total: PREVIOUSTOTAL-N,
        date: DATEENTERED-N
      }
    ]
  }
}

添加之前无需检查先前的值是否存在。

这是我的代码:

var oddsHistoryUpdate = { 
  $push: { 
    'odds.history': { 
      spread: game.odds.spread, 
      total: game.odds.total, 
      date: Date.now() 
    } 
  } 
}
db.collection('games').update({"_id": ID}, oddsHistoryUpdate).
.then(finish executing)

为什么它只推送到0索引而不是添加到数组?我该如何解决?

3 个答案:

答案 0 :(得分:1)

Bigga_HD的答案是关于$push运算符的正确答案。但是,可能有一个替代解决方案与MongoDB的工作方式更加契合。

MongoDB中的单个文档的硬限制为16MB,如果文档经常更新,则阵列可能会变得很大而达到此限制。

或者,您可以仅将新文档插入集合中,而不必将旧文档推入数组中。新旧文件可以通过插入日期来区分。例如:

{
  _id: ID,
  name: <some identification>
  insert_date: ISODate(...),
  odds: {
    spread: CURRENTSPREAD,
    total: CURRENTTOTAL
  }
}

然后,您可以使用例如其nameinsert_date,按日期降序排序,并限制为1以获取最新版本:

db.collection.find({name: ...}).sort({insert_date: -1}).limit(1)

或删除限制以查找所有版本:

db.collection.find({name: ...}).sort({insert_date: -1})

要支持此查询,您可以基于nameinsert_date降序创建索引(请参见Create Indexes to Support Your Queries

db.collection.createIndex({name: 1, insert_date: -1})

作为奖励,您可以在insert_date字段上使用TTL index自动删除旧文档版本。

答案 1 :(得分:0)

$ push

$ push运算符将指定的值附加到数组。 $ push运算符的格式为:

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

如果文档中不存在要更新的字段,则$ push将以值作为元素的数组字段添加。

如果该字段不是数组,则操作将失败。

如果该值为数组,则$ push将整个数组作为单个元素附加。要分别添加值的每个元素,请使用 $ each 修饰符和$push

$each-将多个值添加到数组字段。


这应该为您解决问题。显然,这是一个非常简化的示例。

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

let oddsHistoryUpdate = {
      spread: game.odds.spread, 
      total: game.odds.total, 
      date: Date.now() 
    }


 db.games.update(
      { _id: ID },
      { $push: { odds.history: oddsHistoryUpdate} }
   )

我建议尝试将 Mongoose 用于您的 NodeJS - MongoDB 交互。

答案 2 :(得分:0)

答案dnickless未被发现。

在上一个调用中,我更新了我没有意识到要清除历史记录数组的主要赔率对象。

更新来自的上一个呼叫

update($set: {odds: { spread: SPREAD, total: TOTAL }})

update($set: {"odds.spread": SPREAD, "odds.total": TOTAL})

然后以书面形式进行$ push调用,一切正常。