是否可以在多个匹配的结果上拉动所有

时间:2014-02-19 11:30:44

标签: node.js mongodb mongodb-query

我有以下文件:

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

是否可以从这些文件中提取项目,但仅限于所有项目都存在?

解释:

我需要从这些文档中提取“1a”,“1c”和“2b”elemnet,所以如果我发出如下查询:

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

比将返回成功并拉动物品。

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

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

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

2 个答案:

答案 0 :(得分:0)

我真的不知道你如何获得第一个查询的好结果,因为你没有任何匹配'1a'或'1c'或'2b'的ID。

我认为您的查询应如下所示: db.collection.update({items: {$in: updateObj}}, {$pullAll: {items: updateObj}}, {multi: true});

答案 1 :(得分:0)

好的,我花了一些时间来解决问题,但我相信我现在明白了。坚持下去,因为这是一个冗长的解释,我希望我不会把你与英语混淆。

正如你所说,鉴于$in你想要做的是$pullAll来自数组字段的元素,,只有 所有< / strong>找到的那些元素。 (您的问题可能已接受编辑,可能会在现在清除它。)

按照目前的情况,你会发现你的第二案例当​​然会从匹配的文档中拉出匹配元素('1a','1c')虽然你的'2z'元素与集合中的任何文档都不匹配。根据你想要达到的目标,我认为最后一句话是最重要的一点。

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

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

此处您的操作很简单(假设您使用multi更新),其中匹配两个文档,并且更新部分很简单。因此,对于匹配的文档,我们只想从提供的列表中拉出数组元素。这很好用。

第二个的情况下,我们可以看到“2z”不会在集合中的任何文档中看到。但是,由于我们跨越文档以及使用$in,我们发现第一个文档与条件匹配('1a'和' 1c'存在并匹配$ in)。那么这意味着$pullAll带有给出的参数将在此文档中行为。正如您将意识到的那样,$pullAll并不关心所有元素是否存在,它只会提取与给定列表匹配的所有内容。

所以在这里你可以看到问题,我们是在多个文档上,一个文档(或更多)将符合这些条件,但你想做一些不同的事情。 / p>

您可以用update表单执行此操作吗?好吧,不。但我们可以采取另一种方法。我们想要做的是测试所有元素匹配集合中的文档。因此,在我们做出更新决定之前,我们需要首先分析

小心,这有点做作。但忍受我:

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']}}}
])

那么这将做什么,(并通过逐步查看更好地解释)是查看可能匹配您的初始并将分组的文档>元素一起作为所有文档中的实际。然后我们终于提出问题,“ 所有在集合中找到的这些东西?

上面的过程中元素中的'2z'不会返回结果,但是'2b'会返回结果。因此,通过测试执行之前发布更新语句,您可以获得所需的结果。

更新时不是失败,但您可以检查失败 之前您是否发布更新并满足您想要的条件

唷!那是我的一杯酒?