Na verdade, fazer o que parece que você diz que está fazendo não é uma operação singular, mas vou percorrer as partes necessárias para fazer isso ou cobrir outras situações possíveis.
O que você está procurando é, em parte, o
$
posicional operador. Você precisa de parte da sua consulta para também "encontrar" o elemento da matriz que deseja. db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Portanto, o
$
representa a posição correspondente na matriz para que a parte de atualização saiba qual item da matriz atualizar. Você pode acessar campos individuais do documento na matriz ou apenas especificar o documento inteiro para atualizar nessa posição. db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Se os campos não mudarem de fato e você quiser apenas inserir um novo elemento de array se o mesmo não existir, então você pode usar
$addToSet
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
$addToSet:{
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
No entanto, se você estiver apenas procurando por "empurrar" para uma matriz por um valor de chave singular, se isso não existir, precisará fazer mais manipulação manual, primeiro vendo se o elemento na matriz existe e, em seguida, fazendo o
$push
declaração onde não. Você obtém ajuda dos métodos do mangusto para fazer isso, rastreando o número de documentos afetados pela atualização:
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) {
}
);
}
}
);
A única palavra de cautela aqui é que há uma pequena mudança de implementação nas mensagens writeConcern do MongoDB 2.6 para versões anteriores. Não tendo certeza agora de como a API do mangusto realmente implementa o retorno do
numAffected
argumento no retorno de chamada a diferença pode significar algo. Nas versões anteriores, mesmo que os dados enviados na atualização inicial correspondessem exatamente a um elemento existente e não houvesse nenhuma alteração real necessária, o valor "modificado" seria retornado como
1
mesmo que nada foi realmente atualizado. A partir do MongoDB 2.6, a resposta de preocupação de gravação contém duas partes. Uma parte mostra o documento modificado e a outra mostra a correspondência. Portanto, embora a correspondência seja retornada pela parte da consulta que corresponde a um elemento existente, a contagem real do documento modificado retornaria como
0
se de fato não houvesse nenhuma mudança necessária. Portanto, dependendo de como o número de retorno é realmente implementado no mangusto, pode ser mais seguro usar o
$addToSet
operador nessa atualização interna para garantir que, se o motivo dos zero documentos afetados não fosse apenas que o elemento exato já existia.