2012-06-13 6 views
6

Mam kolekcję zdarzeń, którą przechodzę, aby znaleźć kategorię dla określonego wydarzenia, a następnie aktualizuję inną moją kolekcję za pomocą $ push komunikat. Problem polega na tym, że gdy dwa wydarzenia mają tę samą kategorię, utworzą duplikat, którego nie chcę.Wepchnij element do tablicy, jeśli go nie ma (brak duplikatów)

Wiem o upserts, ale nie jestem pewien, czy są one najlepszym sposobem postępowania w tej sprawie? I jestem trochę zdezorientowany, jeśli chodzi o to, jak napisać upsert, który działa z "$ push" -wymaganie.

To jest jak moja zmiana wygląda teraz:

self.users.update({"user_id": event['userid']}, {'$push': {'campaigns': UserCampaign}}) 

..where:

UserCampaign = { 
     "id": campaign['id'], 
     "name": campaign['name'] 
} 

W "UserCampaign" zostanie wypełnione z tych samych informacji od czasu do czasu, a ponieważ mój kolekcja prawdopodobnie będzie bardzo duża. Chcę ją ukończyć tak wydajnie, jak to tylko możliwe.

TLDR; Chcę zaktualizować tablicę w dokumencie znalezionym za pomocą "wypychania" bez ryzyka otrzymania duplikatów.

Odpowiedz

11

Znaleziono lepszą odpowiedź na mój problem:

Korzystając $ addToSet go nie tworzyć duplikatów (ja również, że żadne duplikaty gdzie dokonane przed dodając wszystkie słowniki do listy):

self.users.update({"user_id": event['userid']}, {'$addToSet': {'campaigns': UserCampaigns[i]}}) 

Gdybym użył przycisku $ push, zawsze tworzyłby duplikaty elementów w "kampaniach" w kolekcji użytkowników. Stało się to bez i z góry.

Z jakiegoś powodu $ każda nie działała, ale nie była wymagana, myślę, że PyMongo zajmie się tym dla mnie.

+1

ah, wcześniej wskazałem kilka innych operatorowi $ addToSet, ale myślę, że sposób, w jaki pytanie zostało sformułowane, został wykorzystany w odpowiedziach związanych z wersjami, zamiast dodawać do tablicy elementów, szczególnie gdy ostatnie pytanie podsumowujące jednoznacznie mówi: "zaktualizuj moją kolekcję za pomocą" wypychania "", gdy masz na myśli coś takiego: zaktualizuj tablicę w dokumencie za pomocą polecenia push bez duplikowania elementów. Zmieniłem to pytanie, aby lepiej odzwierciedlało twoje rzeczywiste wymagania. –

+1

Tak, rozumiem, że może być trudno, abyście wiedzieli, czego potrzebuję. To było moje słabe wyjaśnienie problemu, który był winą. Przykro mi, ale znalazłem działające rozwiązanie i dlaczego specjalnie wskazałem, że $ push w tytule było takie, ponieważ naprawdę myślałem, że właśnie to wykorzystam. W każdym razie przeczytałem o $ addToSet i od razu wiedziałem, że to operator, który rozwiąże mój problem. Dziękuję za twoją pomoc i zaktualizowałem ten wątek, aby ludzie, tak jak ja, w przyszłości, mogli sprostować, tak jak ja. – Ms01

9

Wyślij trzeci argument aktualizacji, tak jak w przypadku MongoDB Docs i PyMongo Docs.

self.users.update({"user_id": event['userid']}, {'$push': {'campaigns': UserCampaign}}, True) 
+0

Nie mogę znaleźć tego w dokumentach, gdzie mogę go znaleźć? Dzięki za twoją odpowiedź btw! – Ms01

+0

W dokumentach, które połączyłem, po prostu przewiń w dół do części 'upserts'. Nie mogłem połączyć się bezpośrednio z nim, ponieważ używają nawiasów klamrowych w pływającej części URI, co powoduje, że nie renderuje ona poprawnie łącza. –

+0

Dodałem link do Dokumentów PyMongo na 'updates()'. Trzecim argumentem funkcji jest flaga 'upsert'. –

1

Christian ma właściwe argumenty w swojej odpowiedzi, więc zostawię tę część w spokoju (wznowił swoją odpowiedź).

Jednakże, można również poprosić o unikanie duplikaty itp

Kluczem tutaj jest, aby upewnić się, że kryteria część zapytania aktualizacji jest specyficzny do poziomu chcesz. Upsert (lub aktualizacja) jest tak dobry, jak kryteria, które do niego wprowadzasz. Upsert wstawi nowy dokument, jeśli nie znajdzie takiego, który pasuje do kryteriów, a update wykona tylko $ push (lub jakakolwiek inna aktualizacja zostanie określona), jeśli znalezione kryteria zostaną znalezione (możesz dokonać wielu aktualizacji, jeśli więcej niż jeden dokument również został znaleziony).

W twoim przypadku, część kryteria to:

UserCampaign = { 
     "id": campaign['id'], 
     "name": campaign['name'] 
} 

Upewnij się, że ta część jest wyjątkowa i będzie w porządku - jeśli można to dopasować więcej niż jeden dokument, to będziesz mieć duplikaty.

+0

Dziękuję za odpowiedź, ale UserCampaign w moim przykładzie nie może być unikalna. Tak też myślałem. Naprawdę nie chcę, aby tworzył nowy wiersz w tabeli. Ale miejmy nadzieję, że nigdy nie będzie wstawki, więc myślę, że wszystko jest w porządku, ale wciąż jest mała szansa. Może powinienem zrobić podstawowe logiki Pythona, zanim będę aktualizować bazę danych z treścią. – Ms01

+0

To może być najlepsze - inną opcją byłoby wymuszenie wyjątkowości dla tych kryteriów, ale brzmi to tak, jak nie jest to coś, co chcesz z innych powodów. Możesz spróbować dodać duplikat, aby uniknąć utraty danych, ale oznaczając je jako takie (dodatkowe pole, takie jak {dupe: 1}), aby później można było je wyczyścić. –

+0

Przepraszam za spóźnioną odpowiedź. Dlaczego nie chcę wymuszać unikalności, ponieważ wiersz, do którego wstawiam, jest gromadzony przed wstawieniem tych danych. Możesz oglądać go jak kolekcję użytkowników, a następnie dodawać akcje użytkownika. – Ms01

Powiązane problemy