我怎样才能$ addToSet对象到一个数组和$排序也使用MongoDB的? [英] How can I $addToSet an object to an array and $sort too using MongoDB?

查看:2573
本文介绍了我怎样才能$ addToSet对象到一个数组和$排序也使用MongoDB的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个对象添加到在MongoDB中收集文档数组,将其插入后,我需要确保所有的数组元素得到由他们的属性之一订购。

I need to add an object to an array in a MongoDB collection document, after inserting it I need to make sure all array's elements get ordered by one of their properties.

当我需要的数组对象是唯一的,我用 $ addToSet 而不是 $推。这是我想要什么的例子:

As I need objects in array to be unique, I use $addToSet instead of $push. This is an example of what I'm trying:

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

然而,这将失败,出现以下错误蒙哥:

However this will fail with the following Mongo error:

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

这是显而易见的,当你想到的设置的,但是$压栈操作甚至不关心什么是数组里面......怎么能做到这一点,而无需使用 $推

And this is obvious when you think about sets, however $push operation doesn't even care what's inside of array ... How could achieve this without having to use $push?

推荐答案

您正确识别你需要做的是操作的方式的一部分出现。但当然 $排序 不是 <一个有效的调节剂STRONG> $ addToSet 因为MongoDB的口头禅是的不被视为套订购的:

You were part of the way there by correctly identifying the operations you need to do. But of course $sort is not a valid modifier for $addToSet since the MongoDB mantra is "sets are not considered to be ordered":

<青霉> $ addToSet不保证在改性元素集合中的特定排序。的

下面的错误指示的另一个问题是,你不能使用多个更新运营商(如 $ addToSet $推 )上相同的路径在同一时间的属性。其实也有无秩序,以不同的更新操作的执行,所以他们不能保证在 $ addToSet 之前发生 $推。事实上,他们很可能作用在平行的,这就是为什么该错误并且这是不允许的。

The other problem here as indicated by the error is that you cannot use multiple update operators ( such as $addToSet and $push ) on the same path to a property at the same time. There is in fact "no order" to the execution of different update operators, so their is no guarantee that the $addToSet occurs before the $push. In fact they are likely acting in parallel, which is why the error and that this is not allowed.

答案当然是二的更新语句。一个是 $ addToSet 和一个应用 $排序通过通过的 $每个

The answer of course is "two" update statements. One for the $addToSet and one to apply the $sort by "pushing" an empty array via $each,

但是,由于我们真的不希望等待每次更新来完成,这是批量操作的API是什么。所以,你可以在发送两个指令到服务器的有一个发送和获取的有一个响应:

But since we really don't want to "wait" for each update to complete, this is what the "Bulk" operations API is for. So you can sent both instructions to the server in one send and get one response:

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临时状态的开销,可能是微不足道的。

So this really is still only one request to the server and one response. It is still "two" operations but the overhead and possibility of some thread grabbing the interim state of the upadte is negligable.

有就是这种方法也就是套检测逻辑移动到 .find()更新语句的一部分,然后只适用<$替代C $ C> $推,其中成员(们)被添加到设置不存在:

There is an alternative to this approach which is to move the "set detection" logic into the .find() portion of the update statement and then just apply $push where the member(s) to be added to the "set" do not already exist:

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();

当然并发症有,如果你在这里将多的数组元素,你需要这些包装的 $不是 和的 $ elemMacth 在测试中的 $和 条件,然后如果只有一个元素都是有效的,然后它不能被单独添加。

Of course the complication there is that if you are adding "multiple" array elements here you would need to wrap those $not and $elemMacth tests in an $and condition, and then if "only one" of those elements was valid then it could not be added alone.

您可以在尝试那种以多项第一的经营,但你的的有每个数组元素具有相同逻辑的回退的执行为上面测试推为每一位的possibilty。

You can "try" that sort of operation with "multiple" items "first", but then you should have a "fallback" execution of each individual array element with the same logic as above to "test" the possibilty of "pushing" for each one.

所以 $ addToSet 使得这第二部分容易与多个数组项。对于一个条目它很简单,只是查询和 $推,超过一它可能是使用带有<$ C $第一的格局较短的路径C> $ addToSet 和 $推一个空数组之类的,因为将第二模式的结果意味着多个更新测试无妨。

So $addToSet makes that second part easy with multiple array entries. For one entry it's quite simple to just "query" and $push, for more than one it is probably the shorter path to use the "first" pattern with $addToSet and $push an empty array to "sort" the result since applying the second pattern means multiple update tests anyway.

这篇关于我怎样才能$ addToSet对象到一个数组和$排序也使用MongoDB的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆