MongoDB如何使用重复值更新文档

时间:2015-12-15 06:33:10

标签: mongodb mongodb-query

我有一个像

这样的用户文档
[{uid:2,name:"Micheal",count:0},{uid:3,name:"Rubby",count:0}]

现在我有一个uids数组[2,2,2,3,3],如果文档的uid位于uidscount将会+1,现在我用

db.getCollection('users').update({ uid: { $in: [2,2,2,3,3] }},{ $inc:{count:1}})

问题是:

我发现count的值只添加uid 2一次,它应该添加三次,uid3如何解决?

2 个答案:

答案 0 :(得分:0)

您需要将multi设置为true,因为:

  

默认情况下,update()方法会更新单个文档。设置多参数以更新符合查询条件的所有文档。

db.getCollection('users').update(
    { 'uid': { $in: [ 2, 3 ] } },
    { $inc: { 'count': 1 }}, 
    { 'multi': true }
)

如果您想根据uids数组中出现的元素更新字段,则需要做更多的工作。

// Function to define sort order.
function compare(a, b) {
    return a < b ? -1 : ( a === b ? 0 : 1);
}

// Function to count occurrences of `uid` in the array.
function counter(arr) {
    arr.sort(compare); // optional
    var counts = {};
    for (var index = 0; index < arr.length; index++) {
        var n = arr[index];
        counts[n] = n in counts ? counts[n]+1 : 1;
    }
    return counts;
}

演示:

> var uids = [ 2, 2, 2, 3, 3 ];
> var myCounter = counter(uids);
> myCounter 
{ '2': 3, '3': 2 }

然后,您可以使用"bulk"操作来更新文档。

var bulkOp = db.users.initializeOrderedBulkOp();

db.users.find( { 'uid': { '$in': uids } ).forEach(function(doc) {
    var value = doc.uid;
    bulkOp.find( { 'uid': doc.uid } ).updateOne( {
        '$inc': { 'count': myCounter[value] }
    } );
} );

bulkOp.execute();

答案 1 :(得分:0)

  

我发现count的值只用uid 2添加一次,它   应该加三次,

这不是mongoDB处理其更新查询的方式。字段增加的数量取决于提供给$inc运算符的值,而不是其他值。

mongoDB查询选择器足够聪明,只能选择一次记录,即使它已多次匹配相同的查询条件

在客户端:您需要做的不仅仅是触发更新查询:

  • 维护count地图,该地图基本上存储numbercount需要增加给定uid的{​​{1}}。它取决于uid数组中uidArr发生的次数。

  • 过滤您稍后将在uid查询中使用的所有唯一update

示例代码:

var updateCountMap = {};
var uidArr = [2,2,2,3,3];
var filteredUniqueIdArr = [];
uidArr.forEach(function(i){
  if(updateCountMap.hasOwnProperty(i)){
    updateCountMap[i]++;
  }
  else{
    updateCountMap[i] = 1;
    filteredUniqueIdArr.push(i);
  }
})
  • 然后使用bulk API根据uiduid的出现次数更新所有唯一uidArray的条目。

示例代码:

var bulk = db.getCollection('users').initializeUnorderedBulkOp();
filteredUniqueIdArr.forEach(function(j){
  bulk.find({"uid":j}).update({$inc:{"count":updateCountMap[j]}},
                                    {"multi":true});
})
bulk.execute();

测试数据:

db.users.insert([{"uid":2,"count":0},{"uid":3,"count":0}])

测试结果:

{ "_id" : ObjectId("566fc583460ebfe7758f4fd5"), "uid" : 2, "count" : 3 }
{ "_id" : ObjectId("566fc583460ebfe7758f4fd6"), "uid" : 3, "count" : 2 }