Non è possibile con un singolo aggiornamento atomico, temo, dovresti eseguire un paio di operazioni di aggiornamento che soddisfino entrambe le condizioni.
Suddividi la logica di aggiornamento in due distinte operazioni di aggiornamento, la prima richiederebbe l'utilizzo di posizionale $
operatore
per identificare l'elemento nella history
array desiderato e $set
per aggiornare i campi esistenti. Questa operazione segue la logica aggiorna i campi SE il nome E l'organizzazione corrispondono
Ora, vorresti utilizzare il findAndModify()
metodo per questa operazione poiché può restituire il documento aggiornato. Per impostazione predefinita, il documento restituito non include le modifiche apportate all'aggiornamento.
Quindi, armato di questo arsenale, puoi quindi sondare la tua seconda logica nella prossima operazione, ad esempio aggiorna SE quella combinazione di "history.name" e "history.organisation" non esiste nell'array . Con questa seconda operazione di aggiornamento, dovresti quindi utilizzare il $push
operatore per aggiungere gli elementi.
L'esempio seguente mostra il concetto precedente. Inizialmente presuppone che la parte della query e il documento vengano aggiornati come oggetti separati.
Prendi ad esempio quando abbiamo documenti che corrispondono all'array della cronologia esistente, eseguirà solo una singola operazione di aggiornamento, ma se i documenti non corrispondono, allora findAndModify()
il metodo restituirà null, usa questa logica nella tua seconda operazione di aggiornamento per eseguire il push del documento nell'array:
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 } }
);
}
Dopo questa operazione per i documenti che corrispondono, interrogare la collezione produrrà lo stesso
db.users.find({ "email": "[email protected]" });
Risultato:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
}
]
}
Ora considera i documenti che non corrispondono:
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 } }
);
}
Interrogazione di questa raccolta per questo documento
db.users.find({ "email": "[email protected]" });
cederebbe
Risultato:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
},
{
"name" : "foo",
"organisation" : "bar"
}
]
}