2014-06-15 161 views
0

我正在嘗試更新MongoDB中與下面類似的嵌套文檔(縮寫爲簡潔)。在MongoDB中更新嵌套對象

{ 
    "cols": "20", 
    "saveTime": "2014-06-15-10:44:09", 
    "rows": "20", 
    "gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8", 
    "players": [ 
    { 
     "id": "Inhuman", 
     "num": "1", 
     "color": "00ff00ff", 
     "name": "badComputer", 
     "type": "1" 
    }, 
    <...> 
    ], 
    "nodes": [ 
    { 
     "g": "1", 
     "c": "0", 
     "r": "0", 
     "a": "0", 
     "o": "" 
    }, 
    { 
     "g": "1", 
     "c": "0", 
     "r": "1", 
     "a": "0", 
     "o": "" 
    } 
    <...> 
    ], 
} 

我所要做的是更新的節點之一。例如,我想改變的節點:(。)

{ "g": "1", "c": "0", "r": "0", "a": "0", "o": ""} 

{ "g": "1", "c": "0", "r": "0", "a": "5", "o": ""} 

我已經使用點嘗試符號,用$ set命令,鼻翼:

db.game.update({"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8"}, { $set: {"nodes.r":"0", "nodes.c":"0", "nodes.a":"5"}}), 

但是這並沒有給我預期的行爲,因爲我正在使用相同的r和c值更新所有節點。這顯然不是我想要的,但我不知道如何更新此文檔的特定部分。有沒有人有任何想法如何做到這一點?

回答

1

如果您正在尋找在你的「節點」數組,你不知道的位置,以更新的具體項目,但你知道的「標準」,以配合該項目,那麼你需要的$elemMatch運營商一起在positional $運營商在更新方面:

db.game.update(
    { 
     "gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8", 
     "nodes": { "$elemMatch": { "g": 1, "r": 0 } } 
    }, 
    { "$set": { "nodes.$.c":"0", "nodes.$.a":"5" } } 
) 

positional $操作包含匹配的「指數」由您查詢條件「匹配」的第一個元素的位置。如果您不使用$elemMatch並使用「點符號」形式,則匹配僅對包含值爲真的整個文檔有效,並且不反映匹配兩個字段條件的元素的「位置」 。

必須注意,這是「第一次」匹配,並且通常被認爲是唯一的匹配。原因在於位置運算符將僅包含有多個匹配的「第一」位置。要以這種方式更新符合條件的多個數組項目,則需要多次發佈更新,直到文檔不再被修改。

對於「知」的位置,你總是可以直接使用「點號」的形式,包括元素,你要更新的位置:

db.game.update(
    { 
     "gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8", 
    }, 
    { "$set": { "nodes.0.c":"0", "nodes.0.a":"5" } } 
) 

所以索引位置爲0爲第一個元素,1第二個元素等等。

注意到在這兩種情況下,您只需要傳遞給$set您實際想要更改的字段。所以除非你不確定是否存在一個值(如果這是你的查詢,情況並非如此),那麼你不需要將字段設置爲它們已經包含的值。

+0

感謝您的信息,但一個問題。只有給定r和c(行和列)值的節點數組中只有一個元素。是否仍然有必要這樣做,或者orepor的答案在上面工作? – unaligned

+0

@unaligned不,它不會工作,這就是爲什麼我向他們評論以及他們的理解。假設你正在尋找'{「g」:,「r」:1}'。除非使用'$ elemMatch',否則它確實匹配陣列中與條件匹配的元素的「文檔」。但是,除非使用'$ elemMatch',否則他實際上並不匹配數組的正確位置。鏈接的文檔顯示了其他示例。但是兩個屬性幾乎不會以這種方式匹配,除非偶然。 –

+0

這工作完美。標記爲正確的答案。 – unaligned

0

要更新特定節點 - 您需要將其放入搜索的查詢部分。

正如

db.game.update({"gameID" : "66f2497c-7a2b-4210-a06b-80be0e6a8fd8","nodes.r":"0", 

    "nodes.c":"0", "nodes.a":"5" }, { $set: {"nodes.$.r":"0", "nodes.$.c":"0", "nodes.$.a":"5"}}) 

你看$ sign採取它發現呼叫的第一部分(查詢)匹配的節點對象,並有向你調用的第二部分(投影)的一部分。 也check out this question

+0

實際上,這隻會在提供的數據上完全匹配,因爲元素是數組中的「第一個」項。要正確匹配多個條件,您需要'$ elemMatch'由於文檔本身包含各種數組元素,因此此處指定的條件與「文檔」本身相匹配,並且只返回數組的第一個位置。 –

+0

是的,你是對的!這實際上是不正確的 – orepor