MongoDB增量或Upsert

MongoDB增量或Upsert,mongodb,Mongodb,鉴于以下文件结构: { '_id': ObjectId("559943fcda2485a66285576e"), 'user': '70gw3', 'data': [ { 'date': ISODate("2015-06-29T00:00:00.0Z"), 'clicks': 1, }, {

鉴于以下文件结构:

{
         '_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,
            },
          ]
    }

如何增加
2015-06-30
点击次数
值,如果该值不存在[整个文档或特定日期],如何增加该值,使其等于
1

不幸的是,不可能在单个查询中实现您的目标。但是你可以做以下的事情

var exists = db.yourCollection.find(
    {'_id': ObjectId("559943fcda2485a66285576e"), 'data.date': <your date>}
).count()

正确的答案是,虽然您需要执行两个更新操作以实现逻辑,但不需要以某种方式查找和检查数据

你有两个基本条件

  • 如果元素存在,则更新它
  • 如果元素不在那里,则添加它
  • 这个过程基本上是两次更新。一个会成功,另一个不会。不需要检查

    实现这一点的最佳方法可能是使用操作API。这允许同时将两个update语句发送到服务器,并且响应将被发送到单个响应,从而减少行程。但逻辑是一样的,即使你不使用这个

    var bulk=db.collection.initializeOrderedBulkOp();
    //更新匹配的日期
    批量查找({“用户”:“70gw3”,“数据.日期”:新日期(“2015-06-30”)})
    .updateOne({“$inc”:{“数据.$.clicks”:1}});
    //在日期不匹配的位置推送新元素
    bulk.find({“user”:“70gw3”,“data.date”:{“$ne”:新日期(“2015-06-30”)})
    .updateOne({“$push”:{“数据”:{“日期”:新日期(“2015-06-30”),“点击”:1}}});
    bulk.execute();
    
    简而言之,在为任何文档发送的两个更新请求中,只有一个操作将实际修改任何内容。这是因为测试“date”的条件是相互“反向”的,即在存在的地方“更新”,在不存在匹配元素的地方“创建”


    这两种状态不可能同时存在,只要“创建”遵循“更新”逻辑,逻辑就是正确的。因此,首先尝试更新,然后尝试在没有找到匹配项的地方“创建”。

    你的意思是
    'data':[{'date':ISODate(“2015-06-29T00:00:00.0Z”),'clicks':1},{'date':ISODate(“2015-06-30T00:00:00.0Z”),'clicks':5,}]
    刚刚更新了我的问题OK,但重复的字段将被删除到
    日期
    子文档中。所以只有一个
    日期
    ,只有一个
    点击
    。这正是我想要的,每个日期只有一次计数。请看我更新的文档。不确定我是否理解这个问题,但是是的。但是我如何指定确切的日期?我刚更新了我的问题文档结构是否正确?
    data
    应该是一个数组吗?使用
    if(exists){…}else{…}
    您不能保证每个日期都不会出现重复的条目。您的意思是代码中有问题或存在并发问题?好的,用修复了这个问题。看一看?
    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}})
        }
    }