MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Soluzione per trovare e modificare in blocco in MongoDB

Come dici tu, al momento non esiste un modo pulito per fare ciò che vuoi. L'approccio migliore in questo momento per operazioni come quella di cui hai bisogno è questo :

  1. Il lettore seleziona X documenti con il limite e l'ordinamento appropriati
  2. Il lettore contrassegna i documenti restituiti da 1) con il proprio ID lettore univoco (e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true) )
  3. Il lettore seleziona tutti i documenti contrassegnati come in elaborazione e con il proprio ID lettore. A questo punto è garantito l'accesso esclusivo all'insieme di documenti risultante.
  4. Offri il set di risultati da 3) per la tua elaborazione.

Si noti che questo funziona anche in situazioni altamente simultanee poiché un lettore non può mai prenotare documenti non già riservati da un altro lettore (si noti che il passaggio 2 può prenotare solo i documenti attualmente disponibili e le scritture sono atomiche). Aggiungerei anche un timestamp con il tempo di prenotazione se vuoi essere in grado di sospendere le prenotazioni (ad esempio per scenari in cui i lettori potrebbero andare in crash/fallire).

EDIT:Maggiori dettagli :

Tutte le operazioni di scrittura possono occasionalmente produrre operazioni in sospeso se la scrittura richiede un tempo relativamente lungo. Ciò significa che il passaggio 2) potrebbe non visualizzare tutti i documenti contrassegnati dal passaggio 1) a meno che tu non esegua i passaggi seguenti :

  • Utilizza un valore "w" (scrivi preoccupazione) appropriato, che significa 1 o superiore. Ciò garantirà che la connessione su cui viene richiamata l'operazione di scrittura attenda il completamento indipendentemente dal fatto che ceda.
  • Assicurati di eseguire la lettura nel passaggio 2 sulla stessa connessione (rilevante solo per i set di replica con letture abilitate per slaveOk) o thread in modo che siano garantiti per essere sequenziali. Il primo può essere eseguito nella maggior parte dei driver con i metodi "requestStart" e "requestDone" o simili (documentazione Java qui ).
    • Aggiungi il flag $isolated ai tuoi aggiornamenti multipli per assicurarti che non possa essere intercalato con altre operazioni di scrittura.

Vedi anche i commenti per la discussione sull'atomicità/isolamento. Ho erroneamente pensato che gli aggiornamenti multipli fossero isolati. Non lo sono, o almeno non per impostazione predefinita.