Inte möjligt med en enda atomuppdatering är jag rädd, du skulle behöva göra ett par uppdateringsoperationer som uppfyller båda villkoren.
Dela upp uppdateringslogiken i två distinkta uppdateringsoperationer, den första skulle kräva att du använder positionell $
operatör
för att identifiera elementet i history
array du vill ha och $set
för att uppdatera befintliga fält. Denna operation följer logiken uppdateringsfält OM namnet OCH organisationen matchar
Nu skulle du vilja använda findAndModify()
metod för denna operation eftersom den kan returnera det uppdaterade dokumentet. Som standard innehåller det returnerade dokumentet inte de ändringar som gjorts på uppdateringen.
Så, beväpnad med denna arsenal, kan du sedan undersöka din andra logik i nästa operation, dvs. uppdatera OM den kombinationen av "history.name" och "history.organisation" inte finns i arrayen em> . Med denna andra uppdateringsoperation måste du sedan använda $push
operatorn för att lägga till elementen.
Följande exempel visar konceptet ovan. Det förutsätter initialt att du har frågedelen och dokumentet som ska uppdateras som separata objekt.
Ta till exempel när vi har dokument som matchar den befintliga historikarrayen, den kommer bara att göra en enda uppdateringsoperation, men om dokumenten inte matchar, då findAndModify()
metod returnerar null, använd denna logik i din andra uppdateringsoperation för att skicka dokumentet till arrayen:
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 } }
);
}
Efter den här åtgärden för dokument som matchar, kommer frågan i samlingen att ge samma
db.users.find({ "email": "[email protected]" });
Utdata:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
}
]
}
Tänk nu på dokument som inte matchar:
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 } }
);
}
Frågar efter denna samling för detta dokument
db.users.find({ "email": "[email protected]" });
skulle ge efter
Utdata:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
},
{
"name" : "foo",
"organisation" : "bar"
}
]
}