Quindi hai ragione nel dire che il $pull
l'operatore fa esattamente ciò che dice la documentazione in quanto i suoi argomenti sono in realtà una "query" utilizzata per abbinare gli elementi che devono essere rimossi.
Se il contenuto dell'array ha sempre l'elemento nella posizione "prima" mentre mostri, allora il $pop
l'operatore rimuove infatti quel primo elemento.
Con il driver del nodo di base:
collection.findOneAndUpdate(
{ "array.0": "bird" }, // "array.0" is matching the value of the "first" element
{ "$pop": { "array": -1 } },
{ "returnOriginal": false },
function(err,doc) {
}
);
Con mangusta l'argomento per restituire il documento modificato è diverso:
MyModel.findOneAndUpdate(
{ "array.0": "bird" },
{ "$pop": { "array": -1 } },
{ "new": true },
function(err,doc) {
}
);
Ma nessuno dei due è di grande utilità se la posizione dell'array del "primo" elemento da rimuovere non è nota.
Per l'approccio generale qui hai bisogno di "due" aggiornamenti, uno per abbinare il primo elemento e sostituirlo con qualcosa di unico da rimuovere, e il secondo per rimuovere effettivamente quell'elemento modificato.
Questo è molto più semplice se si applicano aggiornamenti semplici e non si richiede il documento restituito e può anche essere eseguito in blocco tra i documenti. Aiuta anche a usare qualcosa come async.series per evitare di annidare le tue chiamate:
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
}
);
Quindi usando il $unset
qui con il $
posizionale operatore consente di modificare il "primo" elemento in null
. Quindi la query successiva con $pull
rimuove semplicemente qualsiasi null
voce dall'array.
È così che rimuovi la "prima" occorrenza di un valore in modo sicuro da un array. Per determinare se quell'array contiene più di un valore che è lo stesso però è un'altra domanda.