2012-04-30 10 views
10

Mam kolekcję, w której wszystkie moje dokumenty mają co najmniej te 2 pola, na przykład name i url (gdzie url jest unikalny, więc ustawiłem na nim unikalny indeks). Teraz, jeśli spróbuję wstawić dokument z duplikatem url, spowoduje to błąd i zatrzyma program. Nie chcę tego zachowania, ale potrzebuję czegoś takiego jak mysql 's insert or ignore, więc mongoDB nie powinien wstawiać dokumentu z duplikatem url i kontynuować z następnymi dokumentami.wstawianie lub ignorowanie wielu dokumentów w mongoDB

Czy jest jakiś parametr, który można przekazać do polecenia insert w celu uzyskania tego zachowania? I ogólnie zrobić partię wkładek korzystających pymongo jako:

collection.insert(document_array) 

Tutaj collection jest zbieranie i document_array jest tablicą dokumentów.

Czy jest jakiś sposób wdrożenia funkcji insert or ignore dla wielu dokumentów?

+0

Czy wykonujące te wstawki przy użyciu iteracyjnej/pętli obiektów w pamięci, lub wykorzystujące Mongo wbudowanego w metodach batchInsert? – DeaconDesperado

+0

@DeaconDesperado Używam metody wsadowej wsadowej pymongo. Więc mam pętlę iw każdej iteracji wykonuję operację wstawiania wsadowego, aby wstawić wiele dokumentów. – lovesh

+0

@lovesh Czy jest szansa, że ​​przyjmiesz tutaj odpowiedź? –

Odpowiedz

0

Dlaczego po prostu nie dzwonisz pod numer w bloku try: ... except: i nie kontynuujesz, jeśli wstawka się nie powiedzie?

Ponadto można również użyć zwykłego połączenia update() z flagą upsert. Szczegóły tutaj: http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29

+1

Jeśli korzysta z wsadowego wsadu (przekazując tablicę dokumentów do metody wstawiania), pierwsza, która ulegnie awarii, uruchomi wyjątek, a następnie wyłączy się z wstawiania. Jedyny sposób, w jaki mogę pomyśleć, aby wstawić błąd w milczeniu, a następnie kontynuować z pozostałymi dokumentami, to powtórzenie ich w skrypcie. – DeaconDesperado

+0

Czy mongoDB obsługuje coś takiego jak "wstaw lub zignoruj" w mysql lub sqlite, gdzie wszystko, co jest duplikatem, zostanie po cichu zignorowane i będzie kontynuowane z resztą – lovesh

0

Jeśli masz już tablicę dokumentów w pamięci w swoim skrypcie Pythona, dlaczego nie wstawić ich przez iterację za ich pośrednictwem, a po prostu złapać te, które zawierują się podczas wstawiania z powodu unikalnego indeksu?

for doc in docs: 
    try: 
    collection.insert(doc) 
    except pymongo.errors.DuplicateKeyError: 
    print 'Duplicate url %s' % doc 

Jeżeli zbiór jest instancją kolekcji stworzonej z połączeniem instancji baz danych i/docs jest tablica słowników (dokumenty) byś być obecnie przechodząc do wstawienia.

Możesz również zdecydować, co zrobić z duplikatami kluczy, które naruszają unikatowy indeks w bloku except.

+1

Chciałem zrobić "wsadową wstawkę", ponieważ jest to szybsze niż wstawianie jednego dokumentu na czas i mam tysiące dokumentów do wstawienia – lovesh

-2

Jest wysoce zalecane, aby użyć upsert

stat.update({'location': d['user']['location']}, \ 
     {'$inc': {'count': 1}},upsert = True, safe = True) 

Tutaj stat jest kolekcja jeśli lokalizacja gość jest już obecny w kolekcji, count jest zwiększana o jeden, inny count jest ustawiony na 1.

Oto link do dokumentacji http://www.mongodb.org/display/DOCS/Updating#Updating-UpsertswithModifiers

+1

, jeśli używam upsert i nie mogę wykonać wsadowego wsadu. Muszę przejrzeć każdy dokument, sprawdzić, czy w zbiorze znajduje się już jakiś dokument z tym adresem URL, a jeśli go tam nie ma, wstaw go. – lovesh

+0

Dokumenty Mongo DB są przechowywane jako drzewo B, a wstawka zbiorcza jest specyficzna dla sterownika. [http://www.mongodb.org/display/DOCS/Inserting#Inserting-Bulkinserts](http://www.mongodb.org/display/DOCS/Inserting#Inserting-Bulkinserts) – Kracekumar

+0

OP nie pyta o upsert. Chce wstawić luzem, który nie zawiedzie, gdy jeden rekord się nie powiedzie. To jest coś zupełnie innego. – RickyA

-1

Co robię:

  1. wygenerować tablicę identyfikatorów MongoDB chcę wstawić (hash pewnych wartości w moim przypadku)
  2. usunąć istniejące identyfikatory (Używam wydajności bcoz kolejki Redis, ale możesz zapytać o mongo)
  3. Włóż wyczyszczone dane!

Redis jest idealnym miejscem na to, można użyć Memcached lub MySQL pamięć, według swoich potrzeb

+0

OP nie prosi o ponowienie. – RickyA

+0

Używam Redis do przechowywania kolejki lub do przechowywania już wstawionego adresu URL. –

9

Spróbuj tego:

try: 
    coll.insert(
     doc_or_docs=doc_array, 
     continue_on_error=True) 
except pymongo.errors.DuplicateKeyError: 
    pass 

Operacja wkładka będzie nadal wyjątek jeśli wystąpi błąd insert (np. próba wstawienia duplikatu dla unikalnego indeksu), ale nie wpłynie to na inne pozycje w tablicy. Następnie możesz połknąć błąd, jak pokazano powyżej.

+0

kiedy widzę kod wyrzucania DuplicateKeyError, zastanawiam się, czy to błąd, czy co? Teraz wiem, że to ~~ Dziękuję ~ – zhkzyth

+0

Pamiętaj, że tylko wyrzuca ostatni błąd. nie wszyscy z nich. – RickyA

13

Ustawienie flagi continue_on_error podczas wywoływania insert(). Uwaga PyMongo kierowca serwer wersja 2.1 i 1.9.1 są wymagane:

continue_on_error (opcjonalnie): Jeśli prawda, że ​​baza danych nie zatrzyma przetwarzania zbiorczego wkładkę jeśli nie powiedzie się (na przykład ze względu na powielać identyfikatory). To sprawia, że ​​wkładka zbiorcza zachowuje się podobnie do serii pojedynczych wkładek, , z wyjątkiem lastError zostanie ustawiony, jeśli jakikolwiek insert się nie powiedzie, a nie tylko ostatni jeden. Jeśli wystąpi wiele błędów, tylko najnowszy zostanie zgłoszony przez błąd().

Powiązane problemy