sql >> Database teknologi >  >> NoSQL >> MongoDB

Samtidig opdatering af array-elementer, som er indlejrede dokumenter i MongoDB

Processen her er egentlig ret simpel, den varierer kun i, hvor du vil "finde eller oprette" elementerne i arrayet.

For det første, forudsat at elementerne for hver nøgle allerede er på plads, så er det simple tilfælde at forespørge efter elementet og opdatere med indekset returneret via positional $ operatør:

db.collection.update(
   {
       "_id": docId, 
       "attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
   }
   { "$set": { "attrs.$.value": "20" }
)

Det vil kun ændre det element, der matches uden at påvirke andre.

I det andet tilfælde, hvor "find eller opret" er påkrævet, og den pågældende nøgle muligvis ikke eksisterer, så bruger du "to" opdateringssætninger. Men Bulk Operations API giver dig mulighed for at gøre dette i en enkelt anmodning til serveren med et enkelt svar:

var bulk = db.collection.initializeOrderedBulkOp();

// Try to update where exists
bulk.find({
    "_id": docId,
    "attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
    "$set": { "attrs.$.value": "30" }
});

// Try to add where does noes not exist
bulk.find({
    "_id": docId,
    "attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
    "$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});

bulk.execute();

Den grundlæggende logik er, at først opdateringsforsøget gøres for at matche et element med de krævede værdier ligesom før. Den anden betingelse tester, hvor elementet slet ikke findes ved at vende matchlogikken med $not .

I det tilfælde, hvor array-elementet ikke blev fundet, er et nyt gyldigt til tilføjelse via $push .

Jeg skal virkelig tilføje, at da vi specifikt leder efter negative matches her, er det altid en god idé at matche "dokumentet", som du har til hensigt at opdatere med en unik identifikator såsom _id nøgle. Selvom det er muligt med "multi" opdateringer, skal du være forsigtig med, hvad du laver.

Så i tilfælde af at køre "find eller opret"-processen, tilføjes element, der ikke blev matchet, til arrayet korrekt, uden at forstyrre andre elementer, også den tidligere opdatering for en forventet match anvendes på samme måde:

{
    "_id" : ObjectId("55b570f339db998cde23369d"),
    "attrs" : [
            {
                    "key" : "A1",
                    "type" : "T1",
                    "value" : "20"
            },
            {
                    "key" : "A2",
                    "type" : "T2",
                    "value" : "14"
            },
            {
                    "key" : "A1",
                    "type" : "T2",
                    "value" : "30"
            }
    ]
}

Dette er et simpelt mønster at følge, og selvfølgelig fjerner Bulk Operations her enhver overhead ved at sende og modtage flere anmodninger til og fra serveren. Alt dette fungerer heldigvis uden at forstyrre andre elementer, der måske eksisterer eller ikke.

Bortset fra det er der de ekstra fordele ved at holde dataene i et array for nem forespørgsel og analyse, som understøttes af standardoperatørerne uden at skulle vende tilbage til JavaScript-serverbehandling for at krydse elementerne.




  1. Er der en måde at få udsnit som resultat af Find()?

  2. Indsæt eller opdater underdokument sikkert i MongoDB

  3. Hvordan kan jeg rydde alle forekomster af type X i ServiceStack Redis Client

  4. $først i mongodb