2012-12-28 16 views
10

Próbuję użyć upsert w MongoDB, aby zaktualizować jedno pole w dokumencie, jeśli znalezione LUB wstawić zupełnie nowy dokument z dużą ilością pól. Problem polega na tym, że wydaje mi się, że MongoDB albo zamienia każde pole, albo wstawia podzbiór pól w swojej operacji upsert, tj. Nie może wstawić więcej pól, niż faktycznie chce zaktualizować.Mongodb upsert aktualizuje tylko wybrane pola, ale wstaw wszystkie

Co chcę zrobić jest następujący:

  • kwerendy dla pojedynczej unikalnej wartości
  • Jeśli dokument już istnieje, tylko wartość datownika (nazwijmy go „lastseen”) jest aktualizowany do nowa wartość:
  • Jeśli dokument nie istnieje, dodam go z długą listą różnych par klucz/wartość, które powinny pozostać statyczne przez pozostałą część okresu trwałości.

Pozwala zilustrować:

Ten przykład z mojego zrozumienia zaktualizować „lastseen” datę, jeśli „name” zostanie znaleziony, ale jeśli „nazwa” nie zostanie znaleziony byłoby wstawić tylko „name” + „lastseen ".

db.somecollection.update({name: "some name"},{ $set: {"lastseen": "2012-12-28"}}, {upsert:true}) 

Jeśli dodałem kolejne pola (par klucz/wartość) do drugiego argumentu i upuścić $ zestaw, po czym każde pole zostanie zastąpiony na aktualizacji, ale mają pożądany wpływ na wkładce. Czy jest coś podobnego do $ insert lub podobnego, aby wykonywać operacje tylko podczas wstawiania?

Więc wydaje mi się, że mogę dostać tylko jedną z następujących czynności:

  • poprawne zachowanie aktualizacji, ale włóż dokument tylko podzbiór żądanych polach jeśli dokument nie istnieje
  • Prawidłowe zachowanie płytki, ale nadpisanie wszystkich istniejących pól, jeśli dokument już istnieje.

Czy moje zrozumienie jest prawidłowe? Jeśli tak, czy można to rozwiązać za pomocą pojedynczej operacji?

+1

Czy istnieje powód, dlaczego te pary klucz-wartość nie może być używane w klauzuli Znajdują upsert? – Sammaye

+0

Powodem jest to, że istnieje tylko jedno pole, które znam wartość w tym punkcie. Nie chcę, aby zapytanie zwróciło 0 trafień, jeśli dokładne kombinacje pól nie pasują do siebie. Jedyne pole, w którym znam wartość, decyduje o tym, czy jest to nowa wstawka czy aktualizacja. – agnsaft

Odpowiedz

27

MongoDB 2.4 ma $setOnInsert

db.somecollection.update(
    {name: "some name"}, 
    { 
     $set: { 
      "lastseen": "2012-12-28" 
     }, 
     $setOnInsert: { 
      "firstseen": <TIMESTAMP> # set on insert, not on update 
     } 
    }, 
    {upsert:true} 
) 
8

Istnieje żądanie funkcji dla tego (https://jira.mongodb.org/browse/SERVER-340), które jest rozwiązane w 2.3. Nieparzyste wydania są w rzeczywistości wydaniami dewelopera, więc będzie to stabilne w wersji 2.4.

W obecnej wersji stabilnej nie ma rzeczywistego sposobu, aby to zrobić. Obawiam się, że jedyną metodą jest wykonanie 3 kwerend warunkowych atm: 1, aby sprawdzić wiersz, a następnie if wstawić lub zaktualizować.

Przypuszczam, że gdybyś miał prawdziwy problem z blokadą, mógłbyś wykonać tę funkcję z jedynym JS, ale to zło, ale zablokowałoby to aktualizację do pojedynczego wątku.

+0

Dzięki kolego. Właściwie szukałem w Jira takich informacji, ale najwyraźniej tęskniłem za tym. – agnsaft

Powiązane problemy