2012-08-17 11 views
6

Pierwsze eksperymenty z Spring Data i MongoDB były świetne. Teraz mam następującą strukturę (uproszczoną):Dane źródłowe MongoDB: dostęp do dokumentów podrzędnych i ich aktualizacja

public class Letter { 
    @Id 
    private String id; 
    private List<Section> sections; 
} 

public class Section { 
    private String id; 
    private String content; 
} 

Ładowanie i zapisywanie całych obiektów/dokumentów listowych działa jak czar. (Używam objectID do generowania unikalnych identyfikatorów dla pola Section.id.)

Letter letter1 = mongoTemplate.findById(id, Letter.class) 
mongoTemplate.insert(letter2); 
mongoTemplate.save(letter3); 

jako dokumenty są duże (200K), a czasem tylko sub-części są potrzebne do wniosku: Czy istnieje możliwość kwerendy dla pod-dokument (sekcja), modyfikować i zapisywać? Chciałbym zaimplementować metodę jak

Section s = findLetterSection(letterId, sectionId); 
s.setText("blubb"); 
replaceLetterSection(letterId, sectionId, s); 

I oczywiście metod, takich jak:

addLetterSection(letterId, s); // add after last section 
insertLetterSection(letterId, sectionId, s); // insert before given section 
deleteLetterSection(letterId, sectionId); // delete given section 

widzę, że ostatnie trzy metody są nieco „dziwne”, czyli załadowaniu całego dokumentu, modyfikując zbieranie i zapisywanie go ponownie może być lepszym podejściem z punktu widzenia obiektowego; ale pierwszy przypadek użycia ("nawigacja" do pod-dokumentu/pod-obiektu i praca w zakresie tego obiektu) wydaje się naturalny.

Myślę, że MongoDB może aktualizować pod-dokumenty, ale czy SpringData może być używany do mapowania obiektów? Dzięki za wszelkie wskazówki.

Odpowiedz

12

Podejrzewałem następujące podejście do krojenia i ładowania tylko jednego podobiektu. Czy wydaje się być w porządku? Mam świadomość problemów z równoczesnymi modyfikacjami.

Query query1 = Query.query(Criteria.where("_id").is(instance)); 
query1.fields().include("sections._id"); 
LetterInstance letter1 = mongoTemplate.findOne(query1, LetterInstance.class); 
LetterSection emptySection = letter1.findSectionById(sectionId); 
int index = letter1.getSections().indexOf(emptySection); 

Query query2 = Query.query(Criteria.where("_id").is(instance)); 
query2.fields().include("sections").slice("sections", index, 1); 
LetterInstance letter2 = mongoTemplate.findOne(query2, LetterInstance.class); 
LetterSection section = letter2.getSections().get(0); 

Jest to alternatywne rozwiązanie ładujące wszystkie sekcje, ale pomijające inne (duże) pola.

Query query = Query.query(Criteria.where("_id").is(instance)); 
query.fields().include("sections"); 
LetterInstance letter = mongoTemplate.findOne(query, LetterInstance.class); 
LetterSection section = letter.findSectionById(sectionId); 

Jest to kod używam do przechowywania tylko pojedynczy element kolekcji:

MongoConverter converter = mongoTemplate.getConverter(); 
DBObject newSectionRec = (DBObject)converter.convertToMongoType(newSection); 

Query query = Query.query(Criteria.where("_id").is(instance).and("sections._id").is(new ObjectId(newSection.getSectionId()))); 
Update update = new Update().set("sections.$", newSectionRec); 
mongoTemplate.updateFirst(query, update, LetterInstance.class); 

Miło jest zobaczyć, jak wiosna Dane mogą być używane z „wyników cząstkowych” z MongoDB.

Wszelkie uwagi bardzo doceniane!

+0

Czy możesz udostępnić swoją metodę findSectionById()? –

+0

Cieszę się, że mogę je udostępnić, ale jest to proste - po prostu pętle przechodzi przez sekcje i porównuje pole ID. W tej chwili nie ma tu dokładnego kodu. –

Powiązane problemy