在MongoDB数组中使用addToSet

时间:2013-01-06 17:50:25

标签: json mongodb

我正在尝试跟踪个人的每日统计数据。

我很难在“历史记录”中添加新的一天,并且在新数据进入时也可以使用指针更新“walkingSteps”。

我的架构如下:

{
"_id": {
    "$oid": "50db246ce4b0fe4923f08e48"
},
"history": [
    {
        "_id": {
            "$oid": "50db2316e4b0fe4923f08e12"
        },
        "date": {
            "$date": "2012-12-24T15:26:15.321Z"
        },
        "walkingSteps": 10,
        "goalStatus": 1
    },
    {
        "_id": {
            "$oid": "50db2316e4b0fe4923f08e13"
        },
        "date": {
            "$date": "2012-12-25T15:26:15.321Z"
        },
        "walkingSteps": 5,
        "goalStatus": 0
    },
    {
        "_id": {
            "$oid": "50db2316e4b0fe4923f08e14"
        },
        "date": {
            "$date": "2012-12-26T15:26:15.321Z"
        },
        "walkingSteps": 8,
        "goalStatus": 0
    }
]

}

db.history.update(?)

我一直在浏览(并尝试)mongodb文档,但是它们并没有完全打破像我这样的假人......我无法将他们的示例翻译成我的设置。

感谢您的帮助。

E = noob尝试学习编程

3 个答案:

答案 0 :(得分:4)

添加一天:

user = {_id: ObjectId("50db246ce4b0fe4923f08e48")}
day = {_id: ObjectId(), date: ISODate("2013-01-07"), walkingSteps:0, goalStatus: 0}
db.users.update(user, {$addToSet: {history:day}})

更新walkingSteps:

user = ObjectId("50db246ce4b0fe4923f08e48")
day = ObjectId("50db2316e4b0fe4923f08e13") // second day in your example
query = {_id: user, 'history._id': day}

db.users.update(query, {$set: {"history.$.walkingSteps": 6}})

这使用$ positional operator

虽然可能更容易拥有单独的历史收藏。

<小时/> [编辑]在单独的集合中:

  • 添加天数会使文档大小增加,并且可能需要在磁盘上重新定位。这可能会导致性能问题和碎片化。
  • 删除天数不会缩小磁盘上的文档大小。
  • 它使查询更容易/更直接(例如搜索一段时间)

答案 1 :(得分:1)

尽管@Justin Case提出了正确的答案,但他并没有很好地解释一些事情。

首先你会注意到他在日期上摆脱了决议,并将其格式仅仅改为日期而不是日期和时间:

day = {_id: ObjectId(), date: ISODate("2013-01-07"), walkingSteps:0, goalStatus: 0}

这意味着您所有的约会时间都是00:00:00,而不是您使用atm的确切时间。这增加了每天查询的难易程度,因此您可以执行以下操作:

db.col.update(
    {"_id": ObjectId("50db246ce4b0fe4923f08e48"), 
    "history.date": ISODate("2013-01-07")}, 
    {$inc: {"history.$.walkingSteps":0}}
)

和其他类似的查询。

这也使得$ addToSet实际上强制执行其规则,但是由于此子文档中的数据可能会发生变化,即walkingSteps将增加$addToSet无论如何都无法正常运行。

我会从勾选的答案中改变这一点。我可能会使用$push或其他内容,因为$addToSet更重,并且在这里不会做任何有用的事情。

在我看来,单独收集历史记录的原因将是您之前所说的:

  

是,当天的历史记录项数。

所以这个数组包含一组天,这很好,但听起来你希望得到walkingSteps的数字,一组历史项,应该在另一个集合中,并设置{{1根据今天其他集合中的项目数量计算:

walkingSteps

答案 2 :(得分:0)

参考MongoDB Manual$是位置运算符,它标识要更新的数组字段中的元素,而不显式指定数组中元素的位置。位置$运算符,当与update()方法一起使用时,充当更新查询选择器的第一个匹配的占位符。

因此,如果您发出命令来更新您的集合,请执行以下操作:

db.history.update(
   {someCriterion: someValue },
   { $push: { "history": 
               {"_id": {
                   "$oid": "50db2316e4b0fe4923f08e12"
               },
              "date": {
                   "$date": "2012-12-24T15:26:15.321Z"
               },
           "walkingSteps": 10,
           "goalStatus": 1
           } 
   } 
)

Mongodb可能会尝试将$oid$date识别为一些位置参数。 $也是$set$push等原子运算符的一部分。因此,最好避免在Mongodb中使用这个特殊字符。