2014-02-19 22 views
1

我有下列文件:是否有可能pullAll多個匹配結果

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

是否有可能從拉這些文件的項目,但只有當所有的項目存在嗎?

爲了解釋:

我需要拉 '1A', '1C',並從這些文件 '2B' elemnets,所以我如果問題查詢類似如下:

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沒有任何文件的存在。

+0

道歉的響應時間長度。我明白英語不是你的第一語言,但我認爲這是一個值得正確解釋的使用案例,至於爲什麼這些案例失敗以及如何測試你想要的更新條件。 –

回答

0

好吧,這我花了一些時間來圍繞讓我的頭,但我敢肯定,我現在明白了。堅持下去,因爲這是一個冗長的解釋,我希望我不會把你和英語混淆。

正如你說的,給定的參數來$in你想要做的是$pullAll從陣列領域,的元素,但這些元素的唯一所有地方發現的。 (有一個可能接受的編輯您的問題,現在可以清除)。

既然這樣,你就知道你的第二情況下當然會匹配的元素從匹配文件(「1A」,「1C」),即使你的「2Z」元素不匹配集合中的任何文檔。隨着你想達到的目標,我認爲最後的聲明是最重要的一點。

這個條件的主要問題,以及爲什麼它不起作用,是因爲你匹配的元素跨越不同的文檔

以您的第一個您希望匹配的情況。指定的元素('1a','1c','2b')與您作爲樣本提供的兩個文檔都匹配。這是因爲考慮到$in運營商,兩個文件都符合條件,其中第一個具有元素('1a','1c')和第二匹配('2b')作爲元素之一。

這裏您的操作很簡單(只要您使用multi更新),您有匹配兩個文件,並且更新部分很簡單。因此,對於匹配的文檔,我們只想從所提供的列表中拉出數組元素。這工作得很好。

在你第二情況下,我們可以看到,「2Z」不會是集合中的任何文件看到。但由於我們是跨越文件,並且還與$in的用法,我們發現第一個文件是匹配條件('1a'和'1c'存在並匹配$ in)。那麼這意味着$pullAll與給出的參數是行動對這個文件。如你所知,$pullAll並不關心如果所有的元素不存在,它只會拉動所有匹配列表的東西。

所以在這裏你可以看到這個問題,是我們在多個文件和一個的文件(或更多)將要符合這些條件,但你想做的不同。

那麼你能在你的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」它會。所以,用這個測試執行之前你發出update語句,就可以達到你想要的結果。

這不是一個失敗上更新,但你可以檢查失敗以前你甚至發出更新,滿足你想要的conditons。

唷!我的葡萄酒在哪裏?

+0

感謝您的回覆。它幫助到我 – Erik

0

我真的不知道如何獲得第一個查詢的好結果,因爲您沒有任何與'1a'或'1c'或'2b'匹配的ID。

我認爲你的查詢應該是這樣的: db.collection.update({items: {$in: updateObj}}, {$pullAll: {items: updateObj}}, {multi: true});

+0

第一個查詢將成功,因爲'1a','1c'和'2b'分別存在於第一個和第二個文檔中。關於你的查詢我有一個問題:如果在某些文檔中沒有第二個查詢中的元素,會發生什麼? – Erik

+0

我沒有看到第一個和第二個文檔字段_id等於'1a'或'1c'或'2b'。我想你在你的問題中有'item'字段的'_id'字段混淆。回答你的問題:如果某些文檔沒有像第二個查詢那樣的元素,它將不匹配update函數中的查詢並且不會被更新。 –

+0

@Erik我得到你所問的,但要正確回答將需要一點時間才能輸出。所以,如果你能耐心等待...... –

相關問題