是否可以对多个匹配结果进行pullAll [英] Is it possible to pullAll on multiple matched results

查看:143
本文介绍了是否可以对多个匹配结果进行pullAll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下文件:

{
   _id: 1
   items: ['1a', '1b', '1c']
},
{
   _id: 2,
   items: ['2a', '2b', '2c']
}

是否可以从这些文档中提取项目,但前提是所有项目都存在?

Is it possible to pull items from these documents but only if all the items exist?

说明:

我需要从这些文档中提取'1a','1c'和'2b'元素网,因此,如果发出如下查询,则该问题:

I need to pull '1a', '1c' and '2b' elemnets from these documents, so I if issue the query like the following:

var updateObj = ['1a', '1c', '2b'];
db.collection.update({_id : {$in updateObj}}, {$pullAll: {items: updateObj}});

比将返回成功并拉出物品.

Than will return success and pull the items.

但是,如果发出以下查询:

However if issue the following query:

var updateObj = ['1a', '1c', '2z'];
db.collection.update({_id : {$in updateObj}}, {$pullAll: {items: updateObj}});

然后我希望更新失败,因为任何文档中都不存在2z.

Then I want the update to fail, because 2z does not exist in any of the documents.

推荐答案

好吧,这花了我一些时间才得以解决,但我确定我现在已经明白了.请稍等,因为这是一个冗长的解释,我希望我不要将英语与您混淆.

Okay, this took me a few moments to get my head around but I'm sure I understand now. Hold on because this is a lengthy explanation, and I hope I am not confusing you with the english.

正如您所说的,给出 $ in 的参数您想要做的是 $ pullAll 数组字段中的元素,但仅(当找到这些元素的所有时). (您的问题可能已经接受了修改,目前可能已经解决了.)

As you are saying, given the arguments to $in what you want to do is $pullAll the elements from the array field, but only when all of those elements where found. (There is a possible accepted edit to your question that may clear that up by now).

按现状,您会意识到,您的 second 案例当​​然也会 pull 匹配文档中的匹配元素("1a","1c")尽管您的"2z"元素与集合中的任何文档都不匹配.对于您要实现的目标,我认为最后的陈述是最重要的.

As it stands, you would be aware that your second case will of course pull the matching elements ('1a', '1c') from the matching document even though your '2z' element does not match any document in the collection. With what you want to achieve I think that last statement is the most important point.

此条件的主要问题以及为什么它不起作用,是因为您要匹配跨越不同文档的元素.

The main problem with this condition, and hence why it does not work, is because you are matching elements that span over different documents.

采取您希望匹配的第一案例.指定的元素("1a","1c","2b")与您作为示例提供的两个文档都匹配.这是因为给定$in运算符,两个文档都满足条件,其中 first 具有元素('1a','1c')和 second 匹配(' 2b')作为元素之一.

Take your first case that you expect to match. The specified elements ('1a', '1c', '2b') matches both of the documents you give as a sample. This is because given the $in operator, both documents meet the condition, where the first has elements ('1a', '1c') and the second matches ('2b') as one of the elements.

在这里,您的操作很简单(前提是您使用multi更新),只要您匹配两个文档,并且更新部分很简单.因此,对于匹配的文档,我们只想从提供的列表中拉出数组元素.这样就可以了.

Here your operation is simple (provided you use a multi update) where you have matched two documents, and the update portion is simple. So for the documents that match, we just want to pull the array elements out from the list provided. And this works just fine.

在您的第二情况下,我们可以看到在集合的任何文档中不会看到"2z".但是,由于我们是 spanning 文档,并且还使用了$in,因此我们发现 first 文档与条件("1a"和"1c"存在并匹配$ in).因此,这意味着带有给定参数的$pullAll将在此文档上执行 act .您会知道,$pullAll并不关心所有元素是否不存在,它只会提取与给定列表匹配的所有内容.

In your second case, we can see that '2z' is not going to be seen in any document in the collection. But as we are spanning documents and also with the usage of $in, we find that the first document is a match for the condition ('1a' and '1c' are present and match the $in). So what this means is that $pullAll with the arguments given is going to act on this document. And as you will be aware, $pullAll does not care if all the elements do not exist, it will just pull everything that matches the list given.

因此,在这里您可以看到问题所在,就是我们已经处理了多个文档,并且一个文档(或更多)要符合这些条件,但是您想做些不同的事情.

So here you can see the problem, is that we are over multiple documents and one of the documents (or more) is going to match these conditions, but you want to do something different.

那么您可以以update表单执行此操作吗?好吧,不.但是我们可以采取另一种方法.我们要做的是测试集合文档中的所有 all 元素匹配.因此,为此,我们需要先分析,然后再决定要进行更新.

So can you do this in your update form? Well, no. But we can take another approach. What we want to do is test if all the elements match within documents in the collection. So for this we need to analyse first before we make the decision to update.

保重,这有点人为.但是,请忍受我:

Take care, this is a little contrived. But bear with me:

db.collection.aggregate([
    // Look for "just what we are expecting to match"
    {$match: {items: {$in: ['1a','1c', '2z']}} },

    // Unwind the array for matching
    {$unwind: "$items"},

    // Pool this back into "one document"
    {$group: { _id: null, items: {$addToSet: "$items"}}}

    // Now ask the question again "Do you match **all**?"
    {$match: {items: {$all: ['1a', '1c', '2z']}}}
])

所以这是要做的(最好通过逐步浏览来更好地解释)是浏览可能与您的初始设置匹配的文档并将分组>元素一起作为所有文档的实际 set 集.然后,我们最后问一个问题,"集合中是否找到了所有这些东西?"

So what this will do, (and better explained by looking through it in steps) is look through the documents that may match your initial set and group the elements all together as an actualt set across all documents. Then we finally ask the question, "Are all of these things found within the collection?"

上面在元素中带有"2z"的过程将不会返回结果,但是带有"2b"的结果将返回结果.因此,通过在发布更新语句之前进行测试,就可以实现所需的结果.

The process above with '2z' in the elements will not return a result, but with '2b' it will. And so, with this test performed before you issue the update statement, you can achieve the result you want.

更新不是失败,但是您甚至可以在发布更新并满足所需条件之前检查失败 .

It's not a fail on update, but you can check for the fail before you even issue the update and meet the conditons you want.

Ph!我的酒在哪里?

Phew! Where's my glass of wine?

这篇关于是否可以对多个匹配结果进行pullAll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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