Biorąc pod uwagę ten dokument zapisany w MongoDB
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Obiekt z nowymi informacjami pochodzącymi ze świata zewnętrznego param2
i param3
ze świata zewnętrznego musi zostać uratowany
var new_info = {
param2 : "val2_new",
param3 : "val3_new"
};
Chcę scalić / nałożyć nowe pola na istniejący stan obiektu, aby parametr param1 nie został usunięty
Robiąc to
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Prowadzi do MongoDB robi dokładnie to, o co go proszono, i ustawia some_key na tę wartość. wymiana starego.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Jaki jest sposób, aby MongoDB aktualizował tylko nowe pola (bez ich jawnego podawania jeden po drugim)? aby uzyskać to:
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2_new",
param3 : "val3_new"
}
}
Używam klienta Java, ale każdy przykład będzie mile widziany
mongodb
mongodb-java
Eran Medan
źródło
źródło
Odpowiedzi:
Jeśli dobrze rozumiem pytanie, chcesz zaktualizować dokument o zawartość innego dokumentu, ale tylko te pola, których już nie ma, i całkowicie zignorować pola, które są już ustawione (nawet jeśli na inną wartość).
Nie da się tego zrobić jednym poleceniem.
Musisz najpierw
$set
wysłać zapytanie do dokumentu, dowiedzieć się, co chcesz, a następnie zaktualizować go (używając starych wartości jako pasującego filtru, aby upewnić się, że nie otrzymasz między nimi równoczesnych aktualizacji).Innym sposobem odczytania Twojego pytania byłoby to, że jesteś zadowolony
$set
, ale nie chcesz jawnie ustawiać wszystkich pól. Jak wtedy przekazałbyś dane?Wiesz, że możesz wykonać następujące czynności:
źródło
db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } )
Rozwiązałem to własną funkcją. Jeśli chcesz zaktualizować określone pole w dokumencie, musisz to wyraźnie rozwiązać.
Przykład:
Jeśli chcesz zaktualizować tylko param2, to źle:
Musisz użyć:
Napisałem więc taką funkcję:
źródło
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Możesz użyć notacji kropkowej, aby uzyskać dostęp do pól w głębi obiektów i ustawić je bez wpływu na inne właściwości tych obiektów.
Biorąc pod uwagę przedmiot, który podałeś powyżej:
Aktualizujemy tylko
some_key.param2
isome_key.param3
:Możesz zagłębiać się tak głęboko, jak chcesz. Jest to również przydatne przy dodawaniu nowych właściwości do obiektu bez wpływu na już istniejące.
źródło
Najlepszym rozwiązaniem jest wyodrębnienie właściwości z obiektu i utworzenie z nich płaskich par klucz-wartość w notacji kropkowej. Możesz na przykład użyć tej biblioteki:
https://www.npmjs.com/package/mongo-dot-notation
Posiada
.flatten
funkcję, która pozwala na zmianę obiektu na płaski zestaw właściwości, które można następnie przekazać modyfikatorowi $ set, bez obaw, że jakakolwiek właściwość istniejącego obiektu DB zostanie usunięta / nadpisana bez potrzeby.Zaczerpnięte z
mongo-dot-notation
dokumentów:A potem tworzy doskonały selektor - zaktualizuje TYLKO podane właściwości. EDYCJA: Czasami lubię być archeologiem;)
źródło
Mongo pozwala aktualizować zagnieżdżone dokumenty przy użyciu
.
konwencji. Spójrz: Aktualizowanie zagnieżdżonych dokumentów w mongodb . Oto kolejne pytanie z przeszłości dotyczące aktualizacji scalającej, takiej jak ta, której szukasz, jak sądzę: Atomowa aktualizacja MongoDB za pośrednictwem dokumentu „scalającego”źródło
Udało mi się to zrobić w ten sposób:
Mam funkcję, która dynamicznie obsługuje aktualizacje mojego profilu
Uwaga: „profil” jest specyficzny dla mojej implementacji, jest to tylko ciąg klucza, który chcesz zmodyfikować.
źródło
Wygląda na to, że możesz ustawić isPartialObject, który może osiągnąć to, co chcesz.
źródło
Jeśli masz wiele pól do zaktualizowania
źródło
Zaczynając
Mongo 4.2
,db.collection.update()
może zaakceptować potok agregacji, który pozwala na użycie operatorów agregacji, takich jak$addFields
, który wyprowadza wszystkie istniejące pola z dokumentów wejściowych i nowo dodanych pól:Pierwsza część
{}
to kwerenda dopasowująca, filtrująca dokumenty do zaktualizowania (w tym przypadku wszystkie dokumenty).Druga część
[{ $addFields: { some_key: new_info } }]
to potok agregacji aktualizacji:$addFields
.$addFields
wykonuje dokładnie to, czego potrzebujesz: aktualizuje obiekt, aby nowy obiekt nałożył się / scalił z istniejącym:{ param2: "val2_new", param3: "val3_new" }
zostanie scalony z istniejącymsome_key
, pozostawiającparam1
nietknięty i dodając lub zastępując obaparam2
iparam3
.Nie zapomnij
{ multi: true }
, w przeciwnym razie zaktualizowany zostanie tylko pierwszy pasujący dokument.źródło
do
Mam nadzieję, że to pomoże!
źródło
Możesz raczej zrobić upsert, ta operacja w MongoDB jest wykorzystywana do zapisywania dokumentu w kolekcji. Jeśli dokument spełnia kryteria zapytania, wykona operację aktualizacji, w przeciwnym razie wstawi nowy dokument do kolekcji.
coś podobnego jak poniżej
źródło
użyj $ set wykonaj ten proces
źródło
Utwórz obiekt aktualizacji z nazwami właściwości, w tym wymaganą ścieżką kropki. („jakiś klucz.” + z przykładu OP), a następnie użyj go do aktualizacji.
źródło
Tak, najlepszym sposobem jest przekonwertowanie notacji obiektu na płaską reprezentację ciągu klucz-wartość, jak wspomniano w tym komentarzu: https://stackoverflow.com/a/39357531/2529199
Chciałem podkreślić alternatywną metodę wykorzystującą tę bibliotekę NPM: https://www.npmjs.com/package/dot-object, która umożliwia manipulowanie różnymi obiektami za pomocą notacji kropkowej.
Użyłem tego wzorca, aby programowo utworzyć zagnieżdżoną właściwość obiektu, akceptując klucz-wartość jako zmienną funkcji, w następujący sposób:
Ten wzorzec pozwala mi zamiennie używać zarówno właściwości zagnieżdżonych, jak i właściwości jednopoziomowych i wstawiać je czysto do Mongo.
Jeśli potrzebujesz bawić się obiektami JS poza tylko Mongo, szczególnie po stronie klienta, ale zachowujesz spójność podczas pracy z Mongo, ta biblioteka zapewnia więcej opcji niż wspomniany wcześniej
mongo-dot-notation
moduł NPM.PS Początkowo chciałem tylko wspomnieć o tym jako komentarz, ale najwyraźniej mój przedstawiciel S / O nie jest wystarczająco wysoki, aby opublikować komentarz. Tak więc, nie próbując wtrącać się w komentarz Szybkiego Saszzy, chciałem tylko podkreślić, że zapewniam alternatywny moduł.
źródło
Próbowałem
findAndModify()
zaktualizować określone pole we wcześniej istniejącym obiekcie.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
źródło
Powinieneś pomyśleć o aktualizowaniu obiektu zamiennie, a następnie po prostu przechowywać obiekt ze zaktualizowanymi polami. Coś jak zrobiono poniżej
źródło
Musisz użyć osadzonych dokumentów (określ obiekt ścieżki)
I tak, w JavaScript możesz użyć operatora Spread (...) do aktualizacji
źródło