arrays - 如何使用 MongoDB 将对象 $addToSet 设置为数组并 $sort ?

标签 arrays mongodb

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

因为我需要数组中的对象是唯一的,所以我使用 $addToSet 而不是 $push。这是我正在尝试的示例:

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

然而,这将失败并出现以下 Mongo 错误:

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 16837,
        "errmsg" : "Cannot update 'propiedades' and 'propiedades' at the same time"
    }
})

当你考虑 sets 时,这是显而易见的,但是 $push 操作甚至不关心数组内部的内容......如何在不使用 $push< 的情况下实现这一点?

最佳答案

通过正确识别您需要执行的操作,您已经完成了部分工作。但当然$sort不是 $addToSet 的有效修饰符因为 MongoDB 的格言是“集合不被认为是有序的”:

$addToSet does not guarantee a particular ordering of elements in the modified set.

此处错误指示的另一个问题是您不能在同一属性的同一路径上同时使用多个更新运算符(例如 $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();

所以这实际上仍然只是对服务器的一次请求和一次响应。它仍然是“两个”操作,但是某些线程获取更新的临时状态的开销和可能性可以忽略不计。

这种方法还有一个替代方法,就是将“设置检测”逻辑移动到更新语句的 .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 就非常简单,对于多个条目,使用带有 $addToSet 的“第一个”模式可能是更短的路径$push 一个空数组来“排序”结果,因为应用第二个模式意味着无论如何都要进行多次更新测试。

关于arrays - 如何使用 MongoDB 将对象 $addToSet 设置为数组并 $sort ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31351572/

相关文章:

arrays - 如何仅使用 Bash 数组反向打印目录的内容?

javascript - 有没有一种简单的方法可以在 Javascript 中完全卡住对象及其子对象(Deep Freeze)?

javascript - MongoDB map-reduce(通过nodejs): How to include complex modules (with dependencies) in scopeObj?

node.js - 如何在单个液滴上将不同的 MERN 应用程序部署到 digital ocean ?

MongoDB:内存不足

c - 如何将数组作为函数调用?

arrays - Julia中的共享数组用法

javascript - 文档数据库 : How to filter document on array within array?

mongodb - Golang 和 MongoDb 远程访问失败(服务器在 SASL 身份验证步骤 : Authentication failed. 上返回错误)

node.js - NodeJS/MongoDB - 错误 : Can't set headers after they are sent