Nie możesz odwoływać się do wartości dokumentu, który chcesz zaktualizować, więc będziesz potrzebować jednego zapytania, aby pobrać dokument, a drugiego, aby go zaktualizować. Wygląda na to, że istnieje żądanie funkcji
w tym celu w OPEN
stan od 2016 roku.
Jeśli masz kolekcję z dokumentami, które wyglądają następująco:
{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name" : "bar" }
Używając powłoki MongoDB, możesz zrobić coś takiego:
db.test.find({ name: "bar" }).snapshot().forEach((doc) => {
doc.name = "foo-" + doc.name;
db.test.save(doc);
});
Dokument zostanie zaktualizowany zgodnie z oczekiwaniami:
{ "_id" : ObjectId("590a4aa8ff1809c94801ecd0"), "name": "foo-bar" }
Zwróć uwagę na .snapshot()
call.Gwarantuje to, że zapytanie nie zwróci dokumentu wielokrotnie, ponieważ interweniująca operacja zapisu przenosi go z powodu wzrostu rozmiaru dokumentu.
Zastosuj to do twojego przykładu Mongoose, jak wyjaśniono w tym oficjalnym przykładzie :
Cat.findById(1, (err, cat) => {
if (err) return handleError(err);
cat.name = cat.name + "bar";
cat.save((err, updatedCat) => {
if (err) return handleError(err);
...
});
});
Warto wspomnieć, że istnieje $concat
operatora w ramach agregacji, ale niestety nie można go użyć w update
zapytanie.
W każdym razie, w zależności od tego, co musisz zrobić, możesz użyć tego razem z $out
operatora, aby zapisać wyniki agregacji w nowej kolekcji.
Z tym samym przykładem zrobisz:
db.test.aggregate([{
$match: { name: "bar" }
}, {
$project: { name: { $concat: ["foo", "-", "$name"] }}
}, {
$out: "prefixedTest"
}]);
Oraz nową kolekcję prefixedTest
zostaną utworzone z dokumentami, które wyglądają tak:
{ "_id" : ObjectId("XXX"), "name": "foo-bar" }
Jako odniesienie, jest jeszcze inne interesujące pytanie na ten sam temat z kilkoma odpowiedziami, które warto przeczytać:Aktualizuj pole MongoDB przy użyciu wartości innego pola