MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como enviar para um array MongoDB com AngularJS?


Há algumas coisas aqui que não são ótimas, mas primeiro para cobrir o básico e começar.

A primeira coisa é corrigir o método que chama o lado angular do serviço. O endpoint da API certamente não espera a sintaxe de atualização do MongoDB que você está usando, mas apenas um objeto. Então, primeiro consertando isso:
$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);
    });
}

Agora o final da API do seu servidor tem algumas falhas, eu preferiria uma reformulação total, mas na falta de informações, apenas me concentrando em corrigir os principais problemas sem mudar muito.

Supondo que este seja o lodash biblioteca, o .merge() função aqui é implementada incorretamente. Ele precisa ser dito como "manipular" o conteúdo do array na "mesclagem" corretamente, e no momento o melhor que vai acontecer é uma "sobrescrever". Por isso, damos-lhe algumas espertezas:
// 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);
    });
  });
};`

Mas há um problema nisso, pois ele apenas "anexará" à matriz. Portanto, se você colocar algo em sua entrada que já estava lá, os itens originais e qualquer coisa na entrada do array serão adicionados.

Lidar com isso é outra questão a ser resolvida, dependendo de suas necessidades.

Da minha própria perspectiva, eu apenas enviaria a matriz sempre que possível e teria um ponto de extremidade "apenas" para anexar à matriz do documento, em vez de uma atualização de documento "genérica" ​​como você tem aqui.

Isso permite que você utilize melhor as funções de atualização do MongoDB, de acordo com as ações esperadas. Então, algo assim na chamada de serviço:
// comment can just be a singular object now
$http.put(path,{ 
    "words": "this that", 
    "userId": 123
}).success(function(stuff){

E no final da API do servidor:
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);
     }
  );
};

Então, isso simplesmente pegará o corpo de um "comentário" e o anexará à matriz. Mais importante, ele faz isso "atomicamente", para que nenhuma outra solicitação possível colida em fazer algo como o "merge" atual está fazendo. Outras solicitações para o mesmo endpoint apenas "anexarão" à matriz no estado atual de quando a solicitação é feita, e isso também.

É isso que o $push operador é para, então é aconselhável usá-lo.

Algum alimento para o pensamento.