W poniższym przykładzie załóżmy, że dokument znajduje się w kolekcji db.people .
Jak usunąć trzeci element tablicy zainteresowań według jego indeksu ?
{
"_id" : ObjectId("4d1cb5de451600000000497a"),
"name" : "dannie",
"interests" : [
"guitar",
"programming",
"gadgets",
"reading"
]
}
Oto moje obecne rozwiązanie:
var interests = db.people.findOne({"name":"dannie"}).interests;
interests.splice(2,1)
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});
Czy jest bardziej bezpośredni sposób?
Odpowiedzi:
Nie ma prostego sposobu pobierania / usuwania przez indeks tablicy. W rzeczywistości jest to sprawa otwarta http://jira.mongodb.org/browse/SERVER-1014 , możesz na nią głosować.
Sposób obejścia problemu polega na użyciu $ unset, a następnie $ pull:
Aktualizacja: jak wspomniano w niektórych komentarzach, to podejście nie jest atomowe i może powodować pewne sytuacje wyścigu, jeśli inni klienci czytają i / lub zapisują między dwiema operacjami. Jeśli potrzebujemy atomowej operacji, możemy:
źródło
Możesz użyć
$pull
modyfikatoraupdate
operacji do usunięcia określonego elementu z tablicy. W przypadku, gdy podane zapytanie będzie wyglądać następująco:Możesz również rozważyć użycie
$pullAll
do usunięcia wszystkich wystąpień. Więcej na ten temat na oficjalnej stronie dokumentacji - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pullNie używa to indeksu jako kryterium usuwania elementu, ale nadal może pomóc w przypadkach podobnych do Twojego. IMO, używanie indeksów do adresowania elementów wewnątrz tablicy nie jest zbyt niezawodne, ponieważ mongodb nie jest spójny w kolejności elementów tak fas, jak wiem.
źródło
Zamiast używać nieustawionego (jak w zaakceptowanej odpowiedzi), rozwiązuję to, ustawiając pole na unikalną wartość (tj. Nie NULL), a następnie natychmiast wyciągając tę wartość. Trochę bezpieczniejsze z asynchronicznego punktu widzenia. Oto kod:
Miejmy nadzieję, że mongo rozwiąże ten problem, być może poprzez rozszerzenie modyfikatora $ position tak, aby obsługiwał zarówno $ pull, jak i $ push.
źródło
Zalecałbym użycie pola GUID (zwykle używam ObjectID) lub pola automatycznego zwiększania wartości dla każdego dokumentu podrzędnego w tablicy.
Dzięki temu identyfikatorowi GUID łatwo jest wydać polecenie $ pull i upewnić się, że zostanie wyciągnięty właściwy. To samo dotyczy innych operacji tablicowych.
źródło
Począwszy
Mongo 4.4
od$function
operator agregacji umożliwia zastosowanie niestandardowej funkcji javascript w celu zaimplementowania zachowania nieobsługiwanego przez język zapytań MongoDB.Na przykład, aby zaktualizować tablicę poprzez usunięcie elementu o podanym indeksie:
$function
przyjmuje 3 parametry:body
, która jest funkcją do zastosowania, której parametrem jest tablica do zmodyfikowania. Funkcja tutaj polega po prostu na użyciu splotu do usunięcia 1 elementu o indeksie 2.args
, który zawiera pola z rekordu, którebody
funkcja przyjmuje jako parametr. W naszym przypadku"$interests"
.lang
, czyli język, w którymbody
napisana jest funkcja. Tylkojs
jest obecnie dostępne.źródło
w Mongodb 4.2 możesz to zrobić:
P to indeks elementu, który chcesz usunąć z tablicy.
Jeśli chcesz usunąć z P do końca:
źródło
Dla osób, które szukają odpowiedzi używając mangusty z nodejs. Tak to robię.
Mogę przepisać tę odpowiedź, jeśli nie rozumiem zbyt dobrze, ale myślę, że jest w porządku.
Mam nadzieję, że ci to pomoże, straciłem dużo czasu na zmierzenie się z tym problemem.
źródło
Zamiast używać $ pull, możemy użyć $ pop do usuwania elementów z tablicy według jej indeksu. Ale należy odjąć 1 od pozycji indeksu w celu usunięcia na podstawie indeksu.
Na przykład, jeśli chcesz usunąć element z indeksu 0, powinieneś użyć -1, dla indeksu 1 powinieneś użyć 0 i tak dalej ...
Zapytanie o usunięcie trzeciego elementu (gadżetów):
db.people.update({"name":"dannie"}, {'$pop': {"interests": 1}})
dla odniesienia: https://docs.mongodb.com/manual/reference/operator/update/pop/
źródło
$pop
może usunąć tylko pierwszy lub ostatni element z tablicy. Zapytanie w tej odpowiedzi nie usuwa trzeciego elementu.