2013-04-12 12 views
12

Mam kolekcję około 1 miliona rekordów z 20 polami każdego. Muszę zaktualizować pole liczby całkowitej flag w każdym rekordzie (dokumencie) przypisującym losowo 1 lub 2 do tego pola flag. Jak to zrobić podczas iteracji kursora nad całą kolekcją? To nie wydaje się być dobrym pomysłem, aby szukać raz drugi dla obiektu już znaleziona przez MongoDB, tylko żeby być w stanie zaktualizować go:Java, MongoDB: Jak zaktualizować każdy obiekt podczas iterowania ogromnej kolekcji?

DBCursor cursor = coll.find(); 
    try { 
    while(cursor.hasNext()) { 
    BasicDBObject obj = (BasicDBObject) cursor.next(); 
    ... 
    coll.update(query,newObj) 

    } 
    } finally { 
    cursor.close(); 
    } 

Jak zaktualizować pola w każdym dokumencie ogromnej kolekcji MongoDB z różnymi wartościami wydajnie?

+0

Możesz zaktualizować wszystkie dokumenty (które pasują do określonego warunku) w jednym zapytaniu z flagą "wiele" w poleceniu 'update' ustawionym na true. Sprawdź to: http://stackoverflow.com/questions/4146452/mongodb-what-is-the-fastest-way-to-update-all-records-in-a-collection –

+1

Nie mogę użyć flagi 'multi' ponieważ aktualizuję każdy dokument o unikalnej wartości. To nie jest to samo, co aktualizacja wielu dokumentów o jednej i tej samej wartości. –

Odpowiedz

17

Twoje podejście jest zasadniczo poprawne. Jednak nie uważam taką kolekcję jako „ogromny” można uruchomić coś podobnego z powłoki:

coll.find({}).forEach(function (doc) { 
    doc.flag = Math.floor((Math.random()*2)+1); 
    coll.save(doc); 
}); 

zależności od wersji MongoDB, konfiguracji i obciążenia, może to wziąć coś między kilku minut do kilku godziny

Jeśli chcesz wykonać tę aktualizację w puszkach, korzystać z niektórych warunków w dokumencie zapytań, coś takiego jak coll.find({"aFiled" : {$gt : minVal}, "aFiled" : {$lt : maxVal}})

+1

W moim podejściu każdy dokument jest dwukrotnie przeszukiwany przez MongoDB. Czy jest sens? –

+0

Moja wyprostowana funkcja redukuje ją do pojedynczego zapytania kursora, nie tworzysz dodatkowego zapytania dla każdej iteracji. Jak widzisz, używam 'coll.save (doc)' –

+1

Ma to problemy: zobacz http://docs.mongodb.org/manual/faq/developers/#faq-developers-isolate-cursors – Nashenas

4

Moje rozwiązanie do mojego pytania, zainspirowany @orid:

public void tagAll(int min, int max) { 
    int rnd = 0; 
    DBCursor cursor = this.dataColl.find(); 
    try { 
     while (cursor.hasNext()) { 
      BasicDBObject obj = (BasicDBObject) cursor.next(); 
      rnd = min + (int) (Math.random() * ((max - min) + 1)); 
      obj.put("tag", rnd); 
      this.dataColl.save(obj); 
     } 
    } finally { 
     cursor.close(); 
    } 
} 
Powiązane problemy