MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come eseguire il push su un array MongoDB con AngularJS?

Ci sono un paio di cose qui che non sono eccezionali, ma prima di tutto riguardano le basi e ti fanno andare avanti.

La prima cosa è correggere il metodo che chiama il lato angolare del servizio. L'endpoint API certamente non si aspetta la sintassi di aggiornamento di MongoDB che stai utilizzando, ma piuttosto solo un oggetto. Quindi prima aggiustandolo:

$scope.saveComment = function(i){
    console.log("id is " + i);

    // Split these out so they are easy to log and debug
    var path = '/api/its' + i;

    // This must mirror the structure expected in your document for the element
    // Therefore "comments" is represented as an array of objects, even
    // where this is only one.
    var data = { 
       comments: [{ 
         words: $scope.comment,
         userId: $scope.getCurrentUser().name 
       }]
    };

    // Call service with response
    $http.put(path,data).success(function(stuff){
      document.location.reload(true);
    });
}

Ora l'estremità dell'API del tuo server ha alcuni difetti, preferirei una riprogettazione totale, ma in mancanza di informazioni, mi concentrerei solo sulla risoluzione dei problemi principali senza cambiare molto.

Supponendo che questo sia il lodash libreria, il .merge() funzione qui è implementata in modo errato. Deve essere detto come "gestire" il contenuto dell'array nell'"unione" in modo corretto, e al momento il meglio che accadrà è una "sovrascrittura". Quindi gli diamo un po' di intelligenza:

// Updates an existing it in the DB.
exports.update = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  It.findById(req.params.id, function (err, it) {
    if (err) { return handleError(res, err); }
    if(!it) { return res.send(404); }
    var updated = _.merge(it, req.body,function(a,b) {
        if (_.isArray(a)) {
            return a.concat(b);    // join source and input
        }
    });
    updated.save(function (err) {
      if (err) { return handleError(res, err); }
      return res.json(200, updated);
    });
  });
};`

Ma c'è un problema, in quanto verrà "aggiunto" solo all'array. Quindi, se inserisci qualcosa nel tuo input che era già lì, verranno aggiunti sia gli elementi originali che qualsiasi cosa nell'input dell'array.

Affrontarlo è tutta un'altra questione da risolvere, a seconda delle tue esigenze.

Dal mio punto di vista, invierei semplicemente l'array ove possibile e avrei un endpoint che è "solo" da aggiungere all'array del documento, piuttosto che un aggiornamento del documento "generico" come quello che hai qui.

Ciò ti consente di utilizzare meglio le funzioni di aggiornamento di MongoDB, in base alle azioni previste. Quindi qualcosa del genere nella chiamata di servizio:

// comment can just be a singular object now
$http.put(path,{ 
    "words": "this that", 
    "userId": 123
}).success(function(stuff){

E all'estremità dell'API del server:

exports.addComment = function(req, res) {
  if(req.body._id) { delete req.body._id; }
  It.findByIdAndUpdate(req.params.id,
     { "$push": { "comments": req.body } },
     { "new": true },
     function(err,it) {
      if (err) { return handleError(res, err); }
      if(!it) { return res.send(404); }
      return res.json(200, it);
     }
  );
};

Quindi prenderà semplicemente il corpo di un "commento" e lo aggiungerà all'array. Soprattutto, lo fa "atomicamente", in modo che nessun'altra possibile richiesta possa entrare in conflitto nel fare qualcosa come sta facendo l'attuale "unione". Altre richieste allo stesso endpoint verranno semplicemente "aggiunte" all'array nello stato corrente come al momento della richiesta, e così anche questo.

Questo è ciò che il $push operatore è per, quindi è saggio usarlo.

Alcuni spunti di riflessione.