我怎么能使用MongoDB $ addToSet一个对象到一个数组和$ sort?

时间:2015-07-10 23:01:26

标签: arrays mongodb

我需要在MongoDB集合文档中的数组中添加一个对象,插入后我需要确保所有数组的元素都按其属性排序。

由于我需要数组中的对象是唯一的,我使用<!-- The title of the ion-view will be shown on the navbar--> <ion-view view-title="Home"> <ion-content> <!-- The the content of the page --> <a href="#/music">Go to music page!</a> </ion-content> </ion-view> 而不是$addToSet。这是我尝试的一个例子:

$push

但是,这将因以下Mongo错误而失败:

db.perros.update(
    {name: "Risas"}, 
    {
        $addToSet: {propiedades: {name: "cola", cantidad: 1}}, 
        $push: { propiedades: { $each: [ ], $sort: {cantidad: -1} }}
    });

当您考虑 sets 时,这是显而易见的,但是$ push操作甚至不关心数组内部的内容......如何在不必使用的情况下实现此目的WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 16837, "errmsg" : "Cannot update 'propiedades' and 'propiedades' at the same time" } })

1 个答案:

答案 0 :(得分:10)

通过正确识别您需要执行的操作,您就是其中的一部分。但当然$sort不是$addToSet的有效修饰符,因为MongoDB的口头禅是“集合不被认为是有序的”

  

$ addToSet不保证修改集中元素的特定排序。

错误表明此处的另一个问题是您不能在同一个属性的同一路径上使用多个更新运算符(例如$addToSet$push)。事实上,执行不同的更新运算符“没有顺序”,因此它们无法保证$addToSet出现在$push之前。实际上它们可能并行运行,这就是错误和不允许的原因。

答案当然是“两个”更新声明。一个用于$addToSet,另一个用于通过$each“推送”空数组来应用$sort

但是因为我们真的不想“等待”每个更新完成,所以这就是“批量”操作API的用途。因此,您可以在一个发送中向服务器发送这两个说明并获取一个响应:

var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({ "name": "Risas" }).update({ 
   "$addToSet": { 
       "propiedades": { "name": "cola", "cantidad": 1 }
   }
});
bulk.find({ "name": "Risas" }).update({ 
   "$push": { 
       "propiedades": { 
           "$each": [ ], "$sort": { "cantidad": -1 } 
        }
   }
});
bulk.execute();

所以这仍然只是服务器的一个请求和一个响应。它仍然是“两个”操作,但一些线程抓住upadte的临时状态的开销和可能性是可以忽略不计的。

这种方法有一种替代方法,即将“设置检测”逻辑移动到更新语句的.find()部分,然后将$push应用于要添加的成员的位置到“集”还不存在:

var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({ 
    "name": "Risas", 
    "propiedades": { 
        "$not": { "$elemMatch": { "name": "cola", "cantidad": 1 } } 
    } 
}).update({ 
   "$push": { 
       "propiedades": { 
           "$each": [{ "name": "cola", "cantidad": 1 }], "$sort": { "cantidad": -1 } 
        }
   }
});
bulk.execute();

当然复杂的是,如果你在这里添加“多个”数组元素,你需要将这些$not$elemMacth测试包装在$and条件下,然后如果“这些元素中只有一个”是有效的,然后无法单独添加。

您可以“先尝试”使用“多个”项目进行那种操作,但是应该应该执行每个单独数组元素的“回退”执行,并使用与上面相同的逻辑“测试”每个人“推”的可能性。

所以$addToSet使多个数组条目使第二部分变得容易。对于一个条目,仅仅“查询”和$push非常简单,对于多个,可能是使用“{1}}和$addToSet为空数组的”第一个“模式的较短路径“排序”结果,因为应用第二个模式意味着无论如何都要进行多次更新测试。