2011-09-13 25 views
14

Mam pole w mondzieb, to ciąg znaków. {"field": "some text"}, chcę przekonwertować je wszystkie na tablice. {"field": ["some text"]}Zmiana typu mongodb na tablicę

Wiem, że mogę po prostu przejrzeć wszystkie dokumenty, pobrać pole, a następnie zaktualizować, ale zastanawiam się, czy istnieje bardziej przejrzysty sposób.

Dzięki.

Odpowiedz

3

Można to zrobić w Reduce funkcja map/reduce, aby zachować wszystkie przetwarzanie w mongodb. Zasadniczo użyjesz map/reduce, aby umieścić wyniki w nowej kolekcji, a następnie możesz skopiować je z powrotem do starej kolekcji (lub usunąć stare i zmienić nazwę na nową). Ma to tę zaletę, że utrzymuje wszystko w środku mongo.

Aktualizacja: Inną opcją może być dla ciebie użycie db.eval. db.eval wykonuje się na serwerze, aby aktualizacje były wykonywane na serwerze bez żadnego ruchu/opóźnień.

Myślę, że jedyną opcją jest ta, którą opisałeś - zrób to na kliencie, sprawdzając i aktualizując każdy z nich.

+0

Myślisz, że mapa zmniejszyć w Mongo będzie szybciej? – Harry

+0

Głównie zależy to od liczby dokumentów i ilości danych przenoszonych między serwerem a klientem. Jeśli jest dużo danych przesuwających się między serwerem/klientami, to chcesz zachować przetwarzanie wewnątrz MongoDB z mapReduce lub spróbuj db.eval (jak właśnie dodałem w powyższej edycji). –

+0

dzięki za db.eval, zawsze chętnie się czegoś nowego. – Harry

0

ale zastanawiam się, czy jest jakiś sposób czystsze ..

Krótka odpowiedź brzmi: nie.

MongoDB nie ma pojedynczej operacji ani polecenia do wykonania "typu zmiany".

Najszybszym sposobem jest użycie jednego ze sterowników i wprowadzenie zmiany. Możesz użyć powłoki i napisać pętlę for, ale jeśli chodzi o szybkość, inne sterowniki mogą być szybsze.

Zgodnie z tym, najwolniejsza część procesu będzie ładowanie wszystkich danych z dysku do pamięci, które zostaną zmienione, a następnie wypłukanie tych danych z powrotem na dysk. Byłoby to prawdą nawet przy użyciu magicznego polecenia "typu zmiany".

3

spróbować zamiast

to zmienić typ pola z łańcucha do tablicy w MongoDB

db.jobs.find({ "jobLocationCity" : { $type : 2 } }).forEach(function (x) { 
    x.jobLocationCity = {"Location":x.jobLocationCity}; 
    db.jobs.save(x); 
}); 

zobaczyć link odpowiedź $ type za possible values

+0

Ta odpowiedź doprowadziła mnie do rozwiązania, które uważam za bardzo zwięzłe. Problem z podanym tu przykładem polega na tym, że ponieważ wywoływane jest wywołanie save() w pętli forEach, kursor był pomieszany i funkcja była wywoływana wiele razy dla tego samego dokumentu. Rozwiązaniem jest wywołanie snapshot() przed foreach: db.jobs.find (blah) .snapshot(). ForEach() –

10

Nitin Garg za wyżej prawie działa, z wyjątkiem tego, że jego przykład konwertuje ciąg znaków na skrót, a NIE ciąg znaków na tablicę.

przy uwzględnieniu uwag Joel Harris, prawidłowe rozwiązanie będzie wyglądać następująco:

db.jobs.find({ "jobLocationCity" : { $type : 2 } }).snapshot().forEach(function (x) { 
    x.jobLocationCity = [ jobLocationCity ]; 
    db.jobs.save(x); 
}); 

Albo jeśli używasz db.eval:

function f() { 
    db.jobs.find({ "jobLocationCity" : { $type : 2 } }).snapshot().forEach(function (x) { 
     x.jobLocationCity = [ jobLocationCity ]; 
     db.jobs.save(x); 
    }); 
} 
db.eval(f); 
+2

mała poprawka: x.jobLocationCity = [x.jobLocationCity]; – Vitamon

+0

Dlaczego 'save', a nie' update'? – nilskp

5

Faktycznie, znalezienia ({ "jobLocationCity": { $ type: 2}}) nie będzie działał poprawnie, , ponieważ jeśli następnym razem uruchomisz skrypt aktualizacyjny, potraktuje on ponownie elementy ['mystring'] jako typ łańcucha.

należy używać mniej więcej tak, aby zapobiec:

db.message_info.find({ "jobLocationCity" : { $type : 2 } } ).snapshot().forEach(
    function (x) { 
    if (!Array.isArray(x.jobLocationCity)){ 
     x.jobLocationCity = [ x.jobLocationCity ]; 
     db.jobs.save(x); 
    } 
    } 
) 

zobaczyć http://docs.mongodb.org/manual/reference/operators/

Powiązane problemy