Je zde pár věcí, které nejsou skvělé, ale nejprve pokrývají základy a rozběhnou vás.
První věcí je opravit metodu volající úhlovou stranu služby. Koncový bod API rozhodně neočekává syntaxi aktualizace MongoDB, kterou používáte, ale spíše jen objekt. Nejprve to tedy opravte:
$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);
});
}
Nyní má váš konec API serveru nějaké chyby, upřednostnil bych totální redesign, ale s nedostatkem informací se soustředím pouze na vyřešení hlavních problémů, aniž by se hodně změnily.
Za předpokladu, že se jedná o lodash
knihovna, .merge()
funkce je zde implementována nesprávně. Je třeba říci, jak správně „zacházet“ s obsahem pole ve „sloučení“ a v současnosti je nejlepší, co se stane, „přepsání“. Dáme tomu trochu chytrosti:
// 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);
});
});
};`
Má to ale háček, protože se pouze „připojí“ k poli. Pokud tedy do svého vstupu vložíte něco, co tam již bylo, budou přidány původní položky i cokoli ze vstupu pole.
Vypořádat se s tím je zcela jiný problém, který je třeba vyřešit v závislosti na vašich potřebách.
Z mého vlastního pohledu bych pole poslal tam, kde je to možné, a měl bych koncový bod, který je „pouze“ pro připojení k poli dokumentu, spíše než „obecnou“ aktualizaci dokumentu, jakou máte zde.
To vám umožní lépe využívat funkce aktualizace MongoDB podle očekávaných akcí. Takže něco takového v servisním volání:
// comment can just be a singular object now
$http.put(path,{
"words": "this that",
"userId": 123
}).success(function(stuff){
A na konci API serveru:
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);
}
);
};
Takže to jednoduše vezme tělo "komentáře" a připojí ho k poli. A co je nejdůležitější, dělá to "atomicky", takže žádný jiný možný požadavek nemůže kolidovat při provádění něčeho podobného, jako dělá současné "sloučení". Ostatní požadavky na stejný koncový bod se pouze „připojí“ k poli v aktuálním stavu, ve kterém byl požadavek vytvořen, a stejně tak bude i toto.
To je to, co $push
operátor je pro, takže je rozumné jej používat.
Něco k zamyšlení.