2012-08-17 19 views
6

I primi esperimenti con Spring Data e MongoDB sono stati grandiosi. Ora ho la seguente struttura (semplificato):Spring Data MongoDB: accesso e aggiornamento dei documenti secondari

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

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

Caricamento e salvataggio interi oggetti Lettera/documenti funziona come un fascino. (Io uso ObjectId di generare ID univoci per il campo Section.id.)

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

Poiché i documenti sono grandi (200K) e, talvolta, solo sotto-parti sono necessari per l'applicazione: C'è la possibilità di interrogare per un sotto-documento (sezione), modificarlo e salvarlo? mi piacerebbe implementare un metodo come

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

E di metodi corso come:

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

vedo che gli ultimi tre metodi sono un po ' "strano", vale a dire caricare l'intero documento, la modifica la raccolta e il salvataggio di nuovo possono essere l'approccio migliore da un punto di vista orientato agli oggetti; ma il primo caso d'uso ("navigare" verso un sotto-documento/sotto-oggetto e lavorare nell'ambito di questo oggetto) sembra naturale.

Penso che MongoDB possa aggiornare i documenti secondari, ma è possibile utilizzare SpringData per la mappatura degli oggetti? Grazie per qualsiasi suggerimento.

risposta

12

Ho individuato il seguente approccio per l'affettatura e il caricamento di un solo suboject. Sembra ok? Sono a conoscenza di problemi con modifiche simultanee.

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); 

Questa è una soluzione alternativa che carica tutte le sezioni, ma omette gli altri campi (grandi).

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); 

Questo è il codice che uso per la memorizzazione di un solo elemento collezione:

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); 

E 'bello vedere come i dati della molla può essere utilizzato con "risultati parziali" da MongoDB.

Qualsiasi commento molto apprezzato!

+0

Puoi condividere il tuo metodo di metodo findSectionById()? –

+0

Sono felice di condividerlo, è semplice, però - scorre semplicemente su sezioni della lettera e confronta il campo ID. Non abbiamo il codice esatto qui al momento. –

Problemi correlati