sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB infoga dokument eller inkrementfält om det finns i array

Med MongoDB 4.2 och nyare kan uppdateringsmetoden nu ta ett dokument eller en samlad pipeline där följande steg kan användas:

  1. $addFields och dess alias $set
  2. $project och dess alias $unset
  3. $replaceRoot och dess alias $replaceWith .

Beväpnad med ovanstående kommer din uppdateringsoperation med den aggregerade pipelinen att vara att åsidosätta taggarna genom att sammanfoga en filtrerad taggar array och en mappad array av inmatningslistan med viss datauppslagning i kartan:

Till att börja med använder det aggregerade uttrycket som filtrerar taggarrayen $filter och det följer:

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

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

som producerar den filtrerade uppsättningen av dokument

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

Nu kommer den andra delen att vara att härleda den andra arrayen som kommer att sammanfogas med ovanstående. Denna array kräver en $map över myTags input array som

{ 
    "$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 }
            }
        }
    } 
}

Ovanstående $map går i huvudsak över inmatningsmatrisen och kontrollerar med varje element om det finns i taggarna array som jämför t egenskapen, om den finns är värdet på n fältet i underdokumentet blir dess nuvarande n värde uttryckt med

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

annars lägg till standarddokumentet med n-värdet 0.

Sammantaget kommer din uppdatering att se ut som följer

Din sista uppdateringsåtgärd blir:

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 }
);


  1. Reactivemongo serialiserar en karta till ett BSONDocument

  2. Redis zrevrangebyscore, sortering annat än lexikografisk ordning

  3. Hur ska jag strukturera mina kapslade reactivemongo-anrop i min play2-applikation?

  4. Grupp efter summa mongodb