Jest tu kilka rzeczy, które nie są świetne, ale najpierw omówię podstawy i nauczysz się.
Pierwszą rzeczą jest naprawienie metody wywołującej stronę kątową usługi. Punkt końcowy API z pewnością nie oczekuje składni aktualizacji MongoDB, której używasz, ale raczej obiektu. Więc najpierw napraw to:
$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);
});
}
Teraz twój serwer API ma pewne wady, wolałbym całkowicie przeprojektować, ale z powodu braku informacji, skoncentrowałem się tylko na naprawieniu głównych problemów bez większych zmian.
Zakładając, że jest to lodash
biblioteka .merge()
tutaj funkcja jest zaimplementowana nieprawidłowo. Trzeba powiedzieć, jak prawidłowo „obsługiwać” zawartość tablicy w „scalaniu”, a obecnie najlepszym, co się stanie, jest „nadpisanie”. Dlatego dajemy mu trochę sprytu:
// 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);
});
});
};`
Ale jest w tym pewien haczyk, ponieważ zostanie on tylko "dołączony" do tablicy. Więc jeśli umieścisz w swoim wejściu coś, co już tam było, wtedy zostaną dodane zarówno oryginalne elementy, jak i wszystko z danych wejściowych tablicy.
Radzenie sobie z tym to zupełnie inny problem, w zależności od Twoich potrzeb.
Z mojej perspektywy po prostu wysłałbym tablicę tam, gdzie to możliwe, i miałbym punkt końcowy, który jest „tylko” do dołączenia do tablicy dokumentu, a nie „ogólną” aktualizację dokumentu, jak tutaj.
Pozwala to na lepsze wykorzystanie funkcji aktualizacji MongoDB zgodnie z oczekiwanymi działaniami. Czyli coś takiego w zgłoszeniu serwisowym:
// comment can just be a singular object now
$http.put(path,{
"words": "this that",
"userId": 123
}).success(function(stuff){
A na końcu API serwera:
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);
}
);
};
To po prostu pobierze treść „komentarza” i dołączy go do tablicy. Co najważniejsze, robi to „atomowo”, aby żadne inne możliwe żądanie nie kolidowało z robieniem czegoś, co robi obecne „scalanie”. Inne żądania do tego samego punktu końcowego będą po prostu „dołączane” do tablicy w bieżącym stanie, tak jak w momencie wysłania żądania, i tak będzie.
To właśnie $push
operator jest dla, więc mądrze jest go używać.
Trochę do myślenia.