Więc masz rację, że $pull
operator robi dokładnie to, co mówi dokumentacja, ponieważ jego argumenty są w rzeczywistości „zapytanie” używane do dopasowania elementów, które mają zostać usunięte.
Jeśli zawartość tablicy zawsze miała element na "pierwszej" pozycji, jak pokazano, wtedy $pop
operator faktycznie usuwa ten pierwszy element.
Z podstawowym sterownikiem węzła:
collection.findOneAndUpdate(
{ "array.0": "bird" }, // "array.0" is matching the value of the "first" element
{ "$pop": { "array": -1 } },
{ "returnOriginal": false },
function(err,doc) {
}
);
W przypadku mangusty argument zwracania zmodyfikowanego dokumentu jest inny:
MyModel.findOneAndUpdate(
{ "array.0": "bird" },
{ "$pop": { "array": -1 } },
{ "new": true },
function(err,doc) {
}
);
Ale żadne z nich nie są zbyt przydatne, jeśli pozycja tablicy „pierwszego” elementu do usunięcia nie jest znana.
Dla ogólnego podejścia tutaj potrzebujesz "dwóch" aktualizacji, z których jedna pasuje do pierwszego elementu i zastępuje go czymś unikalnym do usunięcia, a druga do faktycznego usunięcia zmodyfikowanego elementu.
Jest to o wiele prostsze, jeśli stosujesz proste aktualizacje i nie prosisz o zwrócony dokument, a także można to zrobić zbiorczo w różnych dokumentach. Pomaga również użyć czegoś takiego jak async.series, aby uniknąć zagnieżdżania połączeń:
async.series(
[
function(callback) {
collection.update(
{ "array": "bird" },
{ "$unset": { "array.$": "" } },
{ "multi": true }
callback
);
},
function(callback) {
collection.update(
{ "array": null },
{ "$pull": { "array": null } },
{ "multi": true }
callback
);
}
],
function(err) {
// comes here when finished or on error
}
);
Używając $unset
tutaj z pozycyjnym $
operator umożliwia zmianę „pierwszego” elementu na null
. Następnie kolejne zapytanie z $pull
po prostu usuwa wszystkie null
wpis z tablicy.
W ten sposób można bezpiecznie usunąć „pierwsze” wystąpienie wartości z tablicy. Inną kwestią jest ustalenie, czy ta tablica zawiera więcej niż jedną taką samą wartość.