Ve skutečnosti dělat to, co se zdá, jako říkáte, není ojedinělá operace, ale projdu si části potřebné k tomu, abych to udělal, nebo jinak pokryjem další možné situace.
To, co hledáte, je částečně poziční $
operátor. Potřebujete část svého dotazu, abyste také „našli“ prvek pole, který chcete.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Takže $
znamená odpovídající pozici v poli, takže aktualizační část ví, kterou položku v poli má aktualizovat. Můžete přistupovat k jednotlivým polím dokumentu v poli nebo pouze určit celý dokument, který se má na dané pozici aktualizovat.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Pokud se pole ve skutečnosti nemění a chcete pouze vložit nový prvek pole, pokud přesně stejný prvek neexistuje, můžete použít $addToSet
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
$addToSet:{
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Pokud však pouze hledáte „zatlačení“ do pole pomocí singulární hodnoty klíče, pokud taková neexistuje, musíte provést další ruční manipulaci, nejprve zjistit, zda prvek v poli existuje, a poté vytvořit $push
prohlášení tam, kde tomu tak není.
Při provádění tohoto postupu vám pomohou metody mongoose sledováním počtu dokumentů ovlivněných aktualizací:
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
},
function(err,numAffected) {
if (numAffected == 0) {
// Document not updated so you can push onto the array
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095")
},
{
"$push": {
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
},
function(err,numAffected) {
}
);
}
}
);
Jediné varovné slovo je, že došlo k mírné změně implementace ve zprávách writeConcern z MongoDB 2.6 do dřívějších verzí. Nejste si právě teď jisti, jak mongoose API skutečně implementuje návrat numAffected
argument ve zpětném volání rozdíl by mohl něco znamenat.
V předchozích verzích, i když data, která jste odeslali v úvodní aktualizaci, přesně odpovídala existujícímu prvku a nebyla nutná žádná skutečná změna, bude „upravená“ částka vrácena jako 1
i když ve skutečnosti nebylo nic aktualizováno.
Od MongoDB 2.6 obsahuje odpověď na obavy o zápis dvě části. Jedna část zobrazuje upravený dokument a druhá zobrazuje shodu. Takže zatímco by shoda byla vrácena částí dotazu odpovídající existujícímu prvku, skutečný počet upravených dokumentů by se vrátil jako 0
pokud ve skutečnosti nebyla vyžadována žádná změna.
Takže v závislosti na tom, jak je návratové číslo skutečně implementováno v mongoose, může být skutečně bezpečnější použít $addToSet
operátora na této vnitřní aktualizaci, abyste se ujistili, že pokud důvodem nulových ovlivněných dokumentů nebylo jen to, že přesný prvek již existoval.