鉴于以下文件结构:
{
'_id': ObjectId("559943fcda2485a66285576e"),
'user': '70gw3',
'data': [
{
'date': ISODate("2015-06-29T00:00:00.0Z"),
'clicks': 1,
},
{
'date': ISODate("2015-06-30T00:00:00.0Z"),
'clicks': 5,
},
]
}
我如何增加clicks
的{{1}}值,如果它不存在则会增加[整个文档或特定日期],使其等于到2015-06-30
?
答案 0 :(得分:2)
不幸的是,无法在单个查询中实现您的目标。但相反,你可以做以下
var exists = db.yourCollection.find(
{'_id': ObjectId("559943fcda2485a66285576e"), 'data.date': <your date>}
).count()
此查询将返回具有指定_id
的文档数和具有data
数组中指定日期的对象。由于_id
字段是唯一的,因此您最多只能得到一个结果。如果data
数组中不存在此元素,则不会得到任何结果。因此,您有以下情况:
然后这可能成为你的条件:
if (exists) {
db.yourCollection.update({_id: <your id>, 'data.date': <your date>}, {$inc: {'data.$.clicks': 1}})
} else {
if (db.runCommand({findAndModify: 'yourCollection', query: {_id: <your id>, 'data.date': {$ne: <your date>}}, update: {$push: {data: {date: <your date>, clicks: 1}}}}).value) {
db.yourCollection.update({_id: <your id>, 'data.date': <your date>}, {$inc: {'data.$.clicks': 1}})
}
}
答案 1 :(得分:1)
正确的答案是,虽然您需要执行两个更新操作才能实现逻辑,但无需以某种方式查找和检查数据。
您有两个基本条件
这个过程基本上是两次更新。一个会成功,另一个则不会。无需检查。
实现此功能的最佳方法可能是使用"Bulk"操作API。这允许将两个更新语句同时发送到服务器,并且响应它是单个响应,因此行程较少。但即使你不使用它,逻辑也是一样的。
var bulk = db.collection.initializeOrderedBulkOp();
// Update the date where it matched
bulk.find({ "user": "70gw3", "data.date": new Date("2015-06-30") })
.updateOne({ "$inc": { "data.$.clicks": 1 } });
// Push a new element where date does not match
bulk.find({ "user": "70gw3", "data.date": { "$ne": new Date("2015-06-30") } })
.updateOne({ "$push": { "data": { "date": new Date("2015-06-30"), "clicks": 1 } }});
bulk.execute();
简而言之,在为任何文档发送的两个更新请求中,只有一个操作实际上会修改任何内容。这是因为测试“日期”的条件是彼此的“反向”,因为你“更新”当前存在,并且“创建”匹配元素不存在。
两个状态不能同时存在,只要“创建”跟随“更新”逻辑就是声音。所以首先尝试更新,然后尝试“创建”,找不到匹配项。