Obawiam się, że nie jest to możliwe z pojedynczą aktualizacją atomową, musiałbyś wykonać kilka operacji aktualizacji, które spełniają oba warunki.
Podziel logikę aktualizacji na dwie odrębne operacje aktualizacji, z których pierwsza wymagałaby użycia pozycyjny $
operator
do identyfikacji elementu w history
wybraną tablicę i $set
aby zaktualizować istniejące pola. Ta operacja jest zgodna z logiką aktualizacji pól, JEŚLI nazwa ORAZ organizacja są zgodne
Teraz chciałbyś użyć findAndModify()
metoda dla tej operacji, ponieważ może zwrócić zaktualizowany dokument. Domyślnie zwracany dokument nie zawiera modyfikacji wprowadzonych podczas aktualizacji.
Tak więc, uzbrojony w ten arsenał, możesz następnie zbadać swoją drugą logikę w następnej operacji, tj. zaktualizuj JEŚLI ta kombinacja „history.name” i „history.organisation” nie istnieje w tablicy . W przypadku tej operacji drugiej aktualizacji musisz następnie użyć $push
operatora, aby dodać elementy.
Poniższy przykład ilustruje powyższą koncepcję. Początkowo zakłada się, że część zapytania i dokument mają być aktualizowane jako oddzielne obiekty.
Weźmy na przykład, gdy mamy dokumenty, które pasują do istniejącej tablicy historii, wykona tylko jedną operację aktualizacji, ale jeśli dokumenty nie pasują, wtedy findAndModify()
metoda zwróci null, użyj tej logiki w drugiej operacji aktualizacji, aby wypchnąć dokument do tablicy:
var doc = {
"name": "Test123",
"organisation": "Rat"
}, // document to update. Note: the doc here matches the existing array
query = { "email": "[email protected]" }; // query document
query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
"query": query,
"update": {
"$set": {
"history.$.name": doc.name,
"history.$.organisation": doc.organisation
}
}
}); // return the document modified, if there's no matched document update = null
if (!update) {
db.users.update(
{ "email": query.email },
{ "$push": { "history": doc } }
);
}
Po tej operacji dla dokumentów, które pasują, zapytanie kolekcji da to samo
db.users.find({ "email": "[email protected]" });
Wyjście:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
}
]
}
Rozważmy teraz dokumenty, które nie będą pasować:
var doc = {
"name": "foo",
"organisation": "bar"
}, // document to update. Note: the doc here does not matches the current array
query = { "email": "[email protected]" }; // query document
query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
"query": query,
"update": {
"$set": {
"history.$.name": doc.name,
"history.$.organisation": doc.organisation
}
}
}); // return the document modified, if there's no matched document update = null
if (!update) {
db.users.update(
{ "email": query.email },
{ "$push": { "history": doc } }
);
}
Wysyłam zapytanie do tej kolekcji dla tego dokumentu
db.users.find({ "email": "[email protected]" });
podda się
Wyjście:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
},
{
"name" : "foo",
"organisation" : "bar"
}
]
}