Tatsächlich das zu tun, was Sie zu tun scheinen, ist keine einzelne Operation, aber ich werde die Teile durchgehen, die dazu erforderlich sind, oder auf andere mögliche Situationen eingehen.
Was Sie suchen, ist teilweise der Positionscode $
Operator. Sie benötigen einen Teil Ihrer Abfrage, um auch das gewünschte Element des Arrays zu "finden".
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Also das $
steht für die übereinstimmende Position im Array, sodass der Aktualisierungsteil weiß, welches Element im Array aktualisiert werden soll. Sie können auf einzelne Felder des Dokuments im Array zugreifen oder einfach das gesamte Dokument angeben, das an dieser Position aktualisiert werden soll.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Wenn sich die Felder tatsächlich nicht ändern und Sie nur ein neues Array-Element einfügen möchten, wenn genau dasselbe nicht vorhanden ist, können Sie $addToSet
verwenden
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
$addToSet:{
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Wenn Sie jedoch nur nach einem "Push" in ein Array durch einen singulären Schlüsselwert suchen, wenn dieser nicht vorhanden ist, müssen Sie etwas mehr manuelle Handhabung vornehmen, indem Sie zuerst prüfen, ob das Element im Array vorhanden ist, und dann die $push
Anweisung, wo dies nicht der Fall ist.
Dabei helfen Ihnen die Mongoose-Methoden, indem Sie die Anzahl der von der Aktualisierung betroffenen Dokumente verfolgen:
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) {
}
);
}
}
);
Die einzige Warnung hier ist, dass es eine kleine Implementierungsänderung in den writeConcern-Meldungen von MongoDB 2.6 zu früheren Versionen gibt. Ich bin mir jetzt nicht sicher, wie die Mungo-API die Rückgabe von numAffected
tatsächlich implementiert Argument im Callback könnte der Unterschied etwas bedeuten.
In früheren Versionen wurde der "geänderte" Betrag als 1
zurückgegeben, selbst wenn die Daten, die Sie bei der ersten Aktualisierung gesendet haben, genau mit einem vorhandenen Element übereinstimmten und keine wirkliche Änderung erforderlich war obwohl eigentlich nichts aktualisiert wurde.
Ab MongoDB 2.6 enthält die Write Concern Response zwei Teile. Ein Teil zeigt das geänderte Dokument und der andere zeigt die Übereinstimmung. Während also die Übereinstimmung vom Abfrageteil zurückgegeben würde, der mit einem vorhandenen Element übereinstimmt, würde die tatsächliche Anzahl der geänderten Dokumente als 0
zurückgegeben wenn tatsächlich keine Änderung erforderlich war.
Je nachdem, wie die Rückgabenummer tatsächlich in Mungo implementiert ist, ist es möglicherweise sicherer, $addToSet
zu verwenden Bediener auf dieser inneren Aktualisierung, um sicherzustellen, dass, wenn der Grund für die null betroffenen Dokumente nicht nur darin bestand, dass das genaue Element bereits existierte.