Inserire gli articoli nell'array mongo tramite mangusta


185

Ho cercato così bene la ricerca della risposta, ma sono sicuro di aver perso le parole giuste per descrivere ciò che sto cercando.

Fondamentalmente ho una collezione mongodb chiamata 'people' Lo schema per quella collezione è il seguente:

people: {
         name: String, 
         friends: [{firstName: String, lastName: String}]
        }

Ora ho un'applicazione express di base che si collega al database e crea con successo "persone" con un array di amici vuoto.

In un posto secondario nell'applicazione, è presente un modulo per aggiungere amici. Il modulo accetta firstName e lastName e quindi i POST con il campo name anche per riferimento all'oggetto people corretto.

Quello che sto facendo fatica a fare è creare un nuovo oggetto amico e poi "spingerlo" nella matrice degli amici.

So che quando lo faccio tramite la console mongo uso la funzione di aggiornamento con $ push come secondo argomento dopo i criteri di ricerca, ma non riesco a trovare il modo appropriato per ottenere mongoose per farlo.

db.people.update({name: "John"}, {$push: {friends: {firstName: "Harry", lastName: "Potter"}}});

AGGIORNAMENTO: Quindi, la risposta di Adrian è stata molto utile. Quello che segue è quello che ho fatto per raggiungere il mio obiettivo.

nel mio file app.js, ho impostato un percorso temporaneo utilizzando

app.get('/addfriend', users.addFriend);

dove ho nel mio file users.js

exports.addFriend = function (req, res, next)
{
var friend = {"firstName": req.body.fName, "lastName": req.body.lName};
Users.findOneAndUpdate({name: req.user.name}, {$push: {friends: friend}});
};

Vedo che potrei potenzialmente usare collections.findOneAndUpdate (), ma non sono sicuro di dove lo implementerei? Nel mio modello?
Neurax,

Risposte:


282

assumendo, var friend = { firstName: 'Harry', lastName: 'Potter' };

Sono disponibili due opzioni:

Aggiorna il modello in memoria e salva (javascript array.push semplice):

person.friends.push(friend);
person.save(done);

o

PersonModel.update(
    { _id: person._id }, 
    { $push: { friends: friend } },
    done
);

Cerco sempre di scegliere la prima opzione, quando possibile, perché rispetterà maggiormente i vantaggi che ti offre la mangusta (ganci, validazione, ecc.).

Tuttavia, se stai facendo molte scritture simultanee, raggiungerai le condizioni di gara in cui finirai con cattivi errori di versione per impedirti di sostituire l'intero modello ogni volta e perdere l'amico precedente che hai aggiunto. Quindi vai al primo solo quando è assolutamente necessario.


1
Pensavo che la seconda opzione fosse effettivamente la più sicura in termini di protezione da scrittura concorrente? Hai detto per caso l'ultima volta quando intendevi dire prima?
Will Brickner,

37
Sì, ho appena controllato e (nel novembre 2017), si IS sicuri di utilizzare la mangusta updatedi funzione, mentre si NON E ' sicuro di trovare un documento, modificarlo in memoria, e quindi chiamare il .save()metodo sul documento. Quando dico che un'operazione è "sicura", significa che anche se uno, due o 50 cambiamenti vengono applicati a un documento, verranno tutti applicati con successo e il comportamento degli aggiornamenti sarà come previsto. La manipolazione essenzialmente in memoria non è sicura perché potresti lavorare su un documento obsoleto, quindi quando salvi, le modifiche che si sono verificate dopo il passaggio di recupero vengono perse.
Will Brickner,

2
@Will Brickner un flusso di lavoro comune per questo è avvolgere la logica in un ciclo di tentativi: (riprovabile contiene recupero, modifica, salvataggio). Se viene restituito un VersionError (eccezione di blocco ottimistico), è possibile riprovare a eseguire l'operazione alcune volte e recuperare una nuova copia ogni volta. Preferisco comunque gli aggiornamenti atomici quando possibile!
Adrian Schneider,

8
@ZackOfAllTrades Anche me mi ha confuso, ma credo che sia fatta la funzione di callback. let done = function(err, result) { // this runs after the mongoose operation }
utente

come ottenere l'id dell'oggetto amico nel callback?
Dee Nix,

41

L' operatore $ push aggiunge un valore specificato a un array.

{ $push: { <field1>: <value1>, ... } }

$ push aggiunge il campo array con il valore come elemento.

La risposta sopra soddisfa tutti i requisiti, ma l'ho fatto funzionare nel modo seguente

var objFriends = { fname:"fname",lname:"lname",surname:"surname" };
Friend.findOneAndUpdate(
   { _id: req.body.id }, 
   { $push: { friends: objFriends  } },
  function (error, success) {
        if (error) {
            console.log(error);
        } else {
            console.log(success);
        }
    });
)

Questo è quello che ho trovato per funzionare, quindi penso che sia il più aggiornato dal 2019. Quello che è la migliore risposta penso che manchi in qualche modo e forse incompleto / non aggiornato.
Cheesus Toast

Vorrei solo sottolineare che potresti avere un leggero errore nel codice. Ho funzionato perché ho inserito la variabile corretta per il mio progetto. Dove hai Friend.findOneAndUpdate () Penso che dovrebbe essere People.findOneAndUpdate (). Ciò sarebbe più conforme alla domanda originale. Potrei modificarlo per te ma preferirei semplicemente ricontrollarlo nel caso in cui mi sbaglio (sono un po 'nuovo nel nodo / espresso).
Cheesus Toast

@CheesusToast Penso che, se sbaglio, puoi cambiare la risposta. ho messo questa risposta che funzionava bene per me. ma se trovi questa risposta sbagliata, puoi cambiare questa risposta e sarò felice se mi correggerai signore :-).
Parth Raval,

1
OK, nessun problema, è stata comunque solo una piccola modifica. È un po 'schizzinoso da parte mia perché gli spettatori (come me) avrebbero comunque capito dove era stato spinto l'array. Penso ancora che questa dovrebbe essere la migliore risposta :)
Cheesus Toast,

10

Utilizzare $pushper aggiornare il documento e inserire un nuovo valore all'interno di un array.

trova:

db.getCollection('noti').find({})

risultato per trovare:

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

aggiornare:

db.getCollection('noti').findOneAndUpdate(
   { _id: ObjectId("5bc061f05a4c0511a9252e88") }, 
   { $push: { 
             graph: {
               "date" : ISODate("2018-10-24T08:55:13.331Z"),
               "count" : 3.0
               }  
           } 
   })

risultato per l'aggiornamento:

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }, 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 3.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

2

Un modo semplice per farlo è utilizzare quanto segue:

var John = people.findOne({name: "John"});
John.friends.push({firstName: "Harry", lastName: "Potter"});
John.save();

0

Nel mio caso, l'ho fatto

  const eventId = event.id;
  User.findByIdAndUpdate(id, { $push: { createdEvents: eventId } }).exec();

-3

Ho riscontrato anche questo problema. La mia correzione era quella di creare uno schema figlio. Vedi sotto per un esempio per i tuoi modelli.

---- Modello di persona

const mongoose = require('mongoose');
const SingleFriend = require('./SingleFriend');
const Schema   = mongoose.Schema;

const productSchema = new Schema({
  friends    : [SingleFriend.schema]
});

module.exports = mongoose.model('Person', personSchema);

*** Importante: SingleFriend.schema -> assicurarsi di utilizzare lettere minuscole per lo schema

--- Schema figlio

const mongoose = require('mongoose');
const Schema   = mongoose.Schema;

const SingleFriendSchema = new Schema({
  Name: String
});

module.exports = mongoose.model('SingleFriend', SingleFriendSchema);

Forse il motivo del downvote è perché questo non sembra necessario. La risposta di Parth Raval è abbastanza sufficiente.
Cheesus Toast
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.