我正在尝试创建历史记录,以通过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索引而不是添加到数组?我该如何解决?
答案 0 :(得分:1)
Bigga_HD的答案是关于$push
运算符的正确答案。但是,可能有一个替代解决方案与MongoDB的工作方式更加契合。
MongoDB中的单个文档的硬限制为16MB,如果文档经常更新,则阵列可能会变得很大而达到此限制。
或者,您可以仅将新文档插入集合中,而不必将旧文档推入数组中。新旧文件可以通过插入日期来区分。例如:
{
_id: ID,
name: <some identification>
insert_date: ISODate(...),
odds: {
spread: CURRENTSPREAD,
total: CURRENTTOTAL
}
}
然后,您可以使用例如其name
和insert_date
,按日期降序排序,并限制为1以获取最新版本:
db.collection.find({name: ...}).sort({insert_date: -1}).limit(1)
或删除限制以查找所有版本:
db.collection.find({name: ...}).sort({insert_date: -1})
要支持此查询,您可以基于name
和insert_date
降序创建索引(请参见Create Indexes to Support Your Queries)
db.collection.createIndex({name: 1, insert_date: -1})
作为奖励,您可以在insert_date
字段上使用TTL index自动删除旧文档版本。
答案 1 :(得分:0)
$ 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调用,一切正常。