2012-02-10 16 views
17

Chciałbym dodać nowe pole do kolekcji, przy wartości nowego pola ustawionego na wartość istniejącego pola.Dodaj nowe pole do kolekcji o wartości istniejącego pola.

Konkretnie chciałbym iść z tego:

# db.foo.findOne() 
    { 
     "_id"  : ObjectId("4f25c828eb60261eab000000"), 
     "created" : ISODate("2012-01-29T16:28:56.232Z"), 
     "..."  : ... 
    } 

do tego:

# db.foo.findOne() 
    { 
     "_id"  : ObjectId("4f25c828eb60261eab000000"), 
     "created" : ISODate("2012-01-29T16:28:56.232Z"), 
     "event_ts" : ISODate("2012-01-29T16:28:56.232Z"), #same as created 
     "..."  : ... 
    } 

(nowe dokumenty w tej kolekcji nie wszyscy mają ten specyficzny redundancji, ale chcę aby zrobić to dla moich istniejących dokumentów)

+0

Więc to jest jednorazowa rzecz, którą musisz zrobić? – ggreiner

+0

prawda, wystarczy zrobić to tylko raz, aby przygotować te dane. – Purrell

Odpowiedz

38
function addEventTsField(){ 
    db.foo.find().forEach(function(doc){ 
     db.foo.update({_id:doc._id}, {$set:{"event_ts":doc.created}}); 
    }); 
} 

Uruchom z konsoli:

addEventTsField(); 
+2

Nie jest to jednak operacja atomowa. Są to dwie oddzielne operacje z możliwością zmiany danych pomiędzy nimi. (chociaż prawdopodobnie jest bezpieczny w swoim przypadku, ponieważ wydaje się, że robi to raz, offline) – UpTheCreek

2

Nie, to niemożliwe. Tylko dwa kroki, które prawdopodobnie znasz:

  1. Załaduj dokument, przeczytaj pole. (Można ładować tylko specific fields: _id i created w Twoim przypadku, jeśli wydajność jest problemem)
  2. Atomowej aktualizację dokumentu (ustawiony event_ts za pomocą załadowany created boiska)
+0

Nawet z czymś z db.foo.find(). ForEach()? – Purrell

+1

@Purrell: 'forEach' faktycznie ładuje wszystkie znalezione dokumenty i staje się aktualizacją dwuetapową ... –

-1

ponieważ twój kod już wie, jak obsługiwać event_ts, dlaczego musisz skopiować dane? można zmienić nazwę pola zamiast:

{ $rename : { old_field_name : new_field_name } } 

Zobacz http://www.mongodb.org/display/DOCS/Updating

+4

Zakładasz założenie, że "stworzony" nie jest również potrzebny w dokumentach. – Purrell

-1

Jeśli jest to sprawa jednorazowa robić, jej nic wielkiego. Uruchom zapytanie typu "db.foo.find();" w twoim mongo shellu i wklej całe wyjście do edytora takiego jak Textpad lub Wysublimowany tekst, wykonaj blok kolumnowy (W wysublimowanym tekście jest Ctrl + kółko przewijania kliknij & Przeciągnij), wklej to, co rozszerzy się do innego pola, zmień nazwę nowo wkleić kolumnę, jak chcesz, po zakończeniu, wykonaj polecenie, aby edytować cały pakiet jako "^" za pomocą "db.foo.insert ({" i "$" jako "});"

To jest jak następujące kroki.

  1. wklejeniu wyjście jak { '': pole1 wartości, 'Pole2': wartość2, 'field3': value4};
    1. skopiuj ostatni zestaw i rozszerz, używając bloku kolumny edytora {'pole1': wartość, "pole2": wartość2, "pole3": wartość4};
    2. Teraz wstaw odpowiednie słowa, aby wyglądało jak polecenie dla mongo db.foo.insert ({'field1': value, 'field2': value2, 'field3': value4});
    3. Teraz skopiuj je wszystkie i wklej w powłoce Mongo, która zrobi wszystko, co chcesz, tak jak chcesz. Przetestuj go raz i ponów całą operację zaraz po wyczyszczeniu kolekcji, w przeciwnym razie wstawi duplikaty. Usuń również pola "_id" w wynikach, ponieważ będą się one kolidować przy próbie ponownego wstawienia !!

Teraz każdy pojedynczy wiersz w edytorze pokazuje prawidłową komendę Mongo, które mogą być wklejone do swojej skorupy, aby wstawić nowy dokument do kolekcji. więc przetestuj go raz i działa dobrze, posprzątaj całą swoją kolekcję jak "db.foo.remove ({});" i wklej całe polecenie z edytora, które zrobi to w giffy.

Może to być trudne, gdy spróbujesz po raz pierwszy, ale jeśli zrobisz to dobrze, będzie to poręczna rzecz do pracy, kiedy tylko chcesz ... !!

+0

Ta odpowiedź nie ma nawet sensu, ponieważ jest podatna na błędy, nie może być zautomatyzowana, nie może być testowana, nie może być napisana w skrypcie ... Dlaczego miałbyś kiedykolwiek chcieć wykonać tę operację w edytorze, kiedy można to zrobić tak łatwo za pomocą prostej funkcji i forEach()? –

+0

Również -1, ponieważ wymaga 'db.foo.remove ({})' w środku operacji, co zepsułoby wszystko, co mogłoby spowodować, że istniejące dane nadal tam będą. – David

+0

Pytanie zostało wysłane z zamiarem jest to jednorazowa praca. Również robienie tego w edytorze znacznie ułatwia to, co trzeba edytować, co komentować lub co usunąć. Oczywiście rozwiązanie wykorzystujące foreach jest lepsze, to nie jest takie złe, ponieważ jest bardzo przydatne, gdy jesteśmy w trakcie testowania, w którym musimy wstawiać dane dość często, usuwać je, dodawać je ponownie z kilkoma zmianami tutaj n itp. Może być również zautomatyzowany, kiedy po prostu uruchomisz ten sam plik skryptu w linii poleceń. – Param

Powiązane problemy