sql >> Databasteknik >  >> NoSQL >> MongoDB

Hur pushar man till en MongoDB-array med AngularJS?

Det finns ett par saker här som inte är bra, men först för att täcka grunderna och komma igång.

Det första är att fixa metoden som kallar tjänsten vinkelsida. API-slutpunkten förväntar sig verkligen inte MongoDB-uppdateringssyntaxen du använder, utan snarare bara ett objekt. Så först fixa det:

$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);
    });
}

Nu har din server API-ände några fel, jag skulle föredra en total omdesign, men i brist på information, bara koncentrera sig på att fixa huvudproblemen utan att ändra mycket.

Förutsatt att detta är lodash biblioteket, .merge() funktionen här är felaktigt implementerad. Det måste berättas hur man "hanterar" arrayinnehållet i "sammanslagningen" ordentligt, och för närvarande är det bästa som kommer att hända en "överskrivning". Så vi ger det några smarta tips:

// 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);
    });
  });
};`

Men det finns en hake med det, eftersom det bara "läggs till" i arrayen. Så om du lägger in något i din inmatning som redan fanns där, så skulle både originalobjekten och allt i matrisinmatningen läggas till.

Att hantera det är en helt annan fråga att lösa, beroende på dina behov.

Ur mitt eget perspektiv skulle jag bara skicka arrayen där det är möjligt och ha en slutpunkt som är "bara" för att lägga till i arrayen av dokumentet, snarare än en "generisk" dokumentuppdatering som du har här.

Detta gör att du bättre kan använda MongoDB-uppdateringsfunktionerna, per förväntade åtgärder. Så något sånt här i servicesamtalet:

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

Och på serverns API-ände:

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);
     }
  );
};

Så det tar helt enkelt brödtexten av en "kommentar" och lägger till den i arrayen. Viktigast av allt gör den detta "atomärt", så att ingen annan möjlig begäran kan kollidera när man gör något som den nuvarande "sammanslagningen" gör. Andra förfrågningar till samma slutpunkt kommer bara att "läggas till" till arrayen i det aktuella tillståndet som när förfrågan gjordes, och det kommer även detta att göra.

Det är vad $push operatorn är för, så det är klokt att använda det.

Lite tankeställare.




  1. Försenad exekvering / schemaläggning med Redis?

  2. Hur ändrar man replikuppsättningskonfigurationen?

  3. Använder memcached eller Redis på aws-elasticache

  4. kapslat undantag är redis.clients.jedis.exceptions.JedisConnectionException:Kunde inte hämta en resurs från poolen