MongoDB: Jak zaktualizować wiele dokumentów za pomocą jednego polecenia?

145

Zaskoczyło mnie, że poniższy przykładowy kod aktualizuje tylko jeden dokument:

> db.test.save({"_id":1, "foo":"bar"});
> db.test.save({"_id":2, "foo":"bar"});

> db.test.update({"foo":"bar"}, {"$set":{"test":"success!"}});

> db.test.find({"test":"success!"}).count();
1

Wiem, że mogę przeglądać i aktualizować, dopóki wszystkie nie zostaną zmienione, ale wydaje się to strasznie nieefektywne. Czy jest lepszy sposób?

Luke Dennis
źródło

Odpowiedzi:

247

Ostatnio dodano wiele aktualizacji, więc jest dostępna tylko w wersjach rozwojowych (1.1.3). Z powłoki wykonujesz aktualizację wielokrotną, przekazując truejako czwarty argument do update(), gdzie trzeci argument jest argumentem upsert:

db.test.update({foo: "bar"}, {$set: {test: "success!"}}, false, true);

W przypadku wersji mongodb 2.2+ musisz ustawić opcję multi true, aby aktualizować wiele dokumentów naraz.

db.test.update({foo: "bar"}, {$set: {test: "success!"}}, {multi: true})

W przypadku wersji mongodb 3.2+ możesz również użyć nowej metody updateMany()do aktualizacji wielu dokumentów jednocześnie, bez potrzeby oddzielnej multiopcji.

db.test.updateMany({foo: "bar"}, {$set: {test: "success!"}})
mdirolf
źródło
3
Nie jestem pewien, kiedy nastąpiła ta zmiana, ale Mongodb v2.2.2 robi to trochę inaczej. db.collection.update (<query>, <update>, <options>), gdzie opcje to zestaw par klucz-wartość. Zobacz dokumentację: docs.mongodb.org/manual/applications/update
TechplexEngineer
3
co jeśli chcę ustawić różne wartości dla innego dokumentu? czy jest na to uczciwy sposób?
zach
Jak to zrobić dla oldvalue + "jakiś ciąg"
Mahesh K
34

Począwszy od wersji 3.3 możesz użyć updateMany

db.collection.updateMany(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

W wersji 2.2 funkcja aktualizacji ma następującą postać:

 db.collection.update(
   <query>,
   <update>,
   { upsert: <boolean>, multi: <boolean> }
)

https://docs.mongodb.com/manual/reference/method/db.collection.update/

user602525
źródło
16

W przypadku wersji Mongo> 2.2 dodaj pole multi i ustaw je na true

db.Collection.update({query}, 
                 {$set: {field1: "f1", field2: "f2"}},
                 {multi: true })
Kartik Singh
źródło
7

Stworzyłem sposób, aby to zrobić za pomocą lepszego interfejsu.

  • db.collection.find({ ... }).update({ ... }) - wielokrotna aktualizacja
  • db.collection.find({ ... }).replace({ ... }) - pojedyncza wymiana
  • db.collection.find({ ... }).upsert({ ... }) - pojedynczy wzrost
  • db.collection.find({ ... }).remove() - usuwanie wielu

Możesz także zastosować ograniczanie, pomijać, sortować aktualizacje i usuwać, łącząc je wcześniej.

Jeśli jesteś zainteresowany, sprawdź Mongo-Hacker

Tyler Brock
źródło
1
TypeError: db.getCollection (...). Find (...). Update nie jest funkcją:?
Anthony
nie działało db.userActivity.find({ 'appId' : 1234, 'status' : 1}).update({ $set: { 'status': 1 } }); 2017-06-05T17:47:10.038+0530 E QUERY [thread1] TypeError: db.userActivity.find(...).update is not a function :
Prakash Pandey
4

W kliencie MongoDB wpisz:

db.Collection.updateMany({}, $set: {field1: 'field1', field2: 'field2'})

Nowość w wersji 3.2

Parametry:

{}:  select all records updated

Argument słowa kluczowego multinie jest zajęty

Boseam
źródło
3

MongoDB znajdzie tylko jeden pasujący dokument, który spełnia kryteria zapytania podczas wydawania polecenia aktualizacji, niezależnie od tego, który dokument pasuje jako pierwszy, zostanie zaktualizowany, nawet jeśli istnieje więcej dokumentów spełniających kryteria, zostanie zignorowany.

aby temu zaradzić, możemy określić opcję „MULTI” w instrukcji aktualizacji, co oznacza aktualizację wszystkich zestawów dokumentów, które spełniają kryteria zapytania. przeszukaj wszystkie zestawy dokumentów w kolekcji, znajdując te, które spełniają kryteria i zaktualizuj:

db.test.update({"foo":"bar"},{"$set":{"test":"success!"}}, {multi:true} )
Yathish Manjunath
źródło
2

Następujące polecenie może zaktualizować wiele rekordów w kolekcji

db.collection.update({}, 
{$set:{"field" : "value"}}, 
{ multi: true, upsert: false}
)
Sachintha Nayanajith
źródło
1

Miałem ten sam problem i znalazłem rozwiązanie, które działa jak urok

po prostu ustaw flagę multi na true w ten sposób:

 db.Collection.update(
                {_id_receiver: id_receiver},
               {$set: {is_showed: true}},
                {multi: true}   /* --> multiple update */
            , function (err, updated) {...});

Mam nadzieję że to pomogło :)

Amine_Dev
źródło
1

Aby zaktualizować całą kolekcję,

db.getCollection('collection_name').update({},
{$set: {"field1" : "value1", "field2" : "value2", "field3" : "value3"}},
{multi: true })
Isuru Amarathunga
źródło
0

Możesz użyć. "

        Model.update({
            'type': "newuser"
        }, {
            $set: {
                email: "[email protected]",
                phoneNumber:"0123456789"
            }
        }, {
            multi: true
        },
        function(err, result) {
            console.log(result);
            console.log(err);
        })  `
Jitendra
źródło
0

Wszystkie najnowsze wersje mongodb updateMany () działają poprawnie

db.getCollection('workers').updateMany({},{$set: {"assignedVehicleId" : "45680"}});
KARTHIKEYAN.A
źródło
-1

Dzięki za udostępnienie tego, użyłem z 2.6.7 i następujące zapytanie właśnie działało,

dla wszystkich dokumentów:

db.screen.update({stat:"PRO"} , {$set : {stat:"pro"}}, {multi:true})

dla pojedynczego dokumentu:

db.screen.update({stat:"PRO"} , {$set : {stat:"pro"}}, {multi:false})
Athar
źródło