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

Hvordan skubber man til et MongoDB-array med AngularJS?

Der er et par ting herinde, som ikke er gode, men først for at dække det grundlæggende og komme i gang.

Den første ting er at rette den metode, der kalder tjenesten vinkelside. API-endepunktet forventer bestemt ikke den MongoDB-opdateringssyntaks, du bruger, men snarere blot et objekt. Så først retter du 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-ende nogle fejl, jeg ville foretrække et totalt redesign, men i mangel på information, koncentrerer jeg mig om at løse hovedproblemerne uden at ændre meget.

Forudsat at dette er lodash biblioteket, .merge() funktion her er implementeret forkert. Det skal fortælles, hvordan man "håndterer" array-indholdet i "fletningen" korrekt, og på nuværende tidspunkt er det bedste, der vil ske, en "overskrivning". Så vi giver det nogle smarte ting:

// 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 der er en hake ved det, da det kun vil "føjes" til arrayet. Så hvis du lægger noget i dit input, der allerede var der, så ville både de originale elementer og alt i array-inputtet blive tilføjet.

At håndtere det er et helt andet problem at løse, afhængigt af dine behov.

Fra mit eget perspektiv ville jeg bare sende arrayet, hvor det var muligt og have et slutpunkt, der "bare" er til at tilføje til arrayet af dokumentet, snarere end en "generisk" dokumentopdatering, som du har her.

Dette giver dig mulighed for bedre at udnytte MongoDB-opdateringsfunktionerne i henhold til forventede handlinger. Så sådan noget i servicekaldet:

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

Og på serverens API-ende:

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 vil blot tage brødteksten af ​​en "kommentar" og tilføje den til arrayet. Vigtigst af alt gør den dette "atomisk", så ingen anden mulig anmodning kan kollidere ved at gøre noget, som den nuværende "fusion" gør. Andre anmodninger til det samme slutpunkt vil bare "tilføje" til arrayet i den aktuelle tilstand, som da anmodningen blev foretaget, og det vil dette også gøre.

Det er hvad $push operator er til, så det er klogt at bruge det.

Lidt stof til eftertanke.




  1. Returnering af brugerdefinerede felter i MongoDB

  2. Mongo:samle $geoNear og $text ingen resultater

  3. MongoDB-projektion af indlejrede arrays

  4. Eksponering af Redis med Ingress Nginx-controller