sql >> Database >  >> NoSQL >> MongoDB

Hoe push je naar een MongoDB-array met AngularJS?

Er zijn een paar dingen die niet geweldig zijn, maar eerst om de basis te behandelen en je op weg te helpen.

Het eerste is om de methode te repareren die de hoekzijde van de service aanroept. Het API-eindpunt verwacht zeker niet de MongoDB-updatesyntaxis die u gebruikt, maar eerder slechts een object. Dus eerst dat oplossen:

$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 uw server-API-uiteinde enkele fouten heeft, zou ik liever een totaal herontwerp hebben, maar bij gebrek aan informatie, alleen concentreren op het oplossen van de belangrijkste problemen zonder veel te veranderen.

Ervan uitgaande dat dit de lodash is bibliotheek, de .merge() functie is hier onjuist geïmplementeerd. Er moet worden verteld hoe de array-inhoud in de "samenvoeging" correct moet worden "afhandeld", en op dit moment is het beste dat kan gebeuren een "overschrijven". Dus we geven het wat slimheid:

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

Maar daar zit een addertje onder het gras, omdat het alleen aan de array wordt "toegevoegd". Dus als je iets in je invoer invoert dat er al was, dan worden zowel de originele items als alles in de array-invoer toegevoegd.

Om daarmee om te gaan, is een heel andere kwestie om uit te werken, afhankelijk van uw behoeften.

Vanuit mijn eigen perspectief zou ik de array gewoon waar mogelijk verzenden en een eindpunt hebben dat "alleen" is om aan de array van het document toe te voegen, in plaats van een "algemene" documentupdate zoals je hier hebt.

Hierdoor kunt u de MongoDB-updatefuncties beter gebruiken, volgens verwachte acties. Dus zoiets als dit in de serviceoproep:

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

En aan het einde van de server-API:

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

Dus dat neemt gewoon de hoofdtekst van een "opmerking" en voegt deze toe aan de array. Het belangrijkste is dat het dit "atomisch" doet, zodat geen ander mogelijk verzoek kan botsen bij het doen van iets zoals de huidige "samenvoeging" doet. Andere verzoeken aan hetzelfde eindpunt worden gewoon "toegevoegd" aan de array in de huidige staat als toen het verzoek werd gedaan, en dit ook.

Dat is wat de $push operator is voor, dus het is verstandig om het te gebruiken.

Wat stof tot nadenken.




  1. Machinepools en cloudprofielen voor MongoDB

  2. Hoe krijg je toegang tot een specifiek array-item in MongoDB-projectie-aggregatie?

  3. Wat is profiel? en Web en Worker

  4. Aan de slag met Node.js, angular.js en MongoDB, modelleringsrelaties en andere opstaptips