MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB-Dokument einfügen oder Feld erhöhen, falls im Array vorhanden

Mit MongoDB 4.2 und höher kann die Aktualisierungsmethode jetzt ein Dokument oder eine aggregierte Pipeline wobei die folgenden Stufen verwendet werden können:

  1. $addFields und sein Alias ​​$set
  2. $project und sein Alias ​​$unset
  3. $replaceRoot und sein Alias ​​$replaceWith .

Ausgestattet mit dem Obigen besteht Ihr Aktualisierungsvorgang mit der Aggregatpipeline darin, die Tags zu überschreiben durch Verketten eines gefilterten tags Array und ein gemapptes Array der Eingabeliste mit einigen Datensuchen in der Map:

Zunächst einmal verwendet der Aggregatausdruck, der das Tags-Array filtert, den Code <>$filter und es folgt:

const myTags = ["architecture", "blabladontexist"];

{ 
    "$filter": { 
        "input": "$tags",
        "cond": { 
            "$not": [
                { "$in": ["$$this.t", myTags] } 
            ] 
        }
    } 
}

die das gefilterte Array von Dokumenten erzeugt

[  
    { "t" : "contemporary", "n" : 2 }, 
    { "t" : "creative", "n" : 1 }, 
    { "t" : "concrete", "n" : 3 }
]

Nun besteht der zweite Teil darin, das andere Array abzuleiten, das mit dem obigen verkettet wird. Dieses Array erfordert einen $map über die myTags Eingabearray als

{ 
    "$map": { 
        "input": myTags,
        "in": {
            "$cond": {
                "if": { "$in": ["$$this", "$tags.t"] },
                "then": { 
                    "t": "$$this", 
                    "n": { 
                        "$sum": [
                            { 
                                "$arrayElemAt": [
                                    "$tags.n", 
                                    { "$indexOfArray": [ "$tags.t", "$$this" ] } 
                                ] 
                            },
                            1
                        ]
                    } 
                },
                "else": { "t": "$$this", "n": 0 }
            }
        }
    } 
}

Der obige $map durchläuft im Wesentlichen das Eingabearray und prüft bei jedem Element, ob es in den tags enthalten ist Array, das t vergleicht Eigenschaft, falls vorhanden, dann der Wert von n Feld des Unterdokuments wird zu seinem aktuellen n Wert ausgedrückt mit

{ 
    "$arrayElemAt": [
        "$tags.n", 
        { "$indexOfArray": [ "$tags.t", "$$this" ] } 
    ] 
}

andernfalls fügen Sie das Standarddokument mit einem n-Wert von 0 hinzu.

Insgesamt sieht Ihr Aktualisierungsvorgang wie folgt aus

Ihr letzter Aktualisierungsvorgang wird zu:

const myTags = ["architecture", "blabladontexist"];

db.getCollection('coll').update(
    { "_id": "1234" },
    [
        { "$set": {
            "tags": {
                "$concatArrays": [
                    { "$filter": { 
                        "input": "$tags",
                        "cond": { "$not": [ { "$in": ["$$this.t", myTags] } ] }
                    } },
                    { "$map": { 
                        "input": myTags,
                        "in": {
                            "$cond": [
                                { "$in": ["$$this", "$tags.t"] },
                                { "t": "$$this", "n": { 
                                    "$sum": [
                                        { "$arrayElemAt": [
                                            "$tags.n", 
                                            { "$indexOfArray": [ "$tags.t", "$$this" ] } 
                                        ] },
                                        1
                                    ]
                                } },
                                { "t": "$$this", "n": 0 }
                            ]
                        }
                    } }
                ]
            }
        } }
    ],
    { "upsert": true }
);