Se essenzialmente ottengo il tuo senso, in pratica vuoi
- Estrarre l'elemento non richiesto dall'array di riferimenti
- Imposta il valore del tuo campo di riferimento principale sul primo elemento dell'array modificato
E fai tutto in un solo aggiornamento senza spostare i documenti attraverso il cavo.
Ma questo purtroppo non può essere fatto. Il problema principale è che non c'è modo di fare riferimento al valore di un altro campo all'interno del documento da aggiornare. Anche così, per farlo senza iterare dovresti anche accedere al modificato array per ottenere il nuovo primo elemento.
Forse un approccio è ripensare il tuo schema per ottenere ciò che desideri. La mia opzione qui sarebbe espandere un po' i tuoi documenti di riferimento e rimuovere la necessità del campo di riferimento principale.
Sembra che il presupposto con cui sei disposto a convivere con gli aggiornamenti sia che se il riferimento rimosso era il riferimento principale, puoi semplicemente impostare il nuovo riferimento principale sul primo elemento nell'array. Tenendo presente ciò, considera la seguente struttura:
refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ]
Modificandoli in documenti con un oid
proprietà che verrebbe impostata su ObjectId offre la possibilità di avere una proprietà aggiuntiva sul documento che specifica quale è l'impostazione predefinita. Questo può essere facilmente interrogato per determinare quale Id è il riferimento principale.
Ora considera anche cosa accadrebbe se il documento corrispondente a "object5" nel campo oid venisse estratto dall'array:
refs: [ { oid: "object1" }, { oid: "object2" } ]
Quindi, quando esegui una query per quale è il main-reference
secondo la logica precedente, accetti il primo documento nell'array. Ora, ovviamente, in base ai requisiti della tua applicazione, se desideri impostare un diverso main-reference
devi solo modificare il documento
refs: [ { oid: "object1" }, { oid: "object2", main: true } ]
E ora la logica resta quella di scegliere l'elemento dell'array che ha la proprietà principale come true si verificherebbe di preferenza e, come mostrato sopra, se quella proprietà non esiste su nessun documento degli elementi, allora ricadere sul primo elemento.
Con tutto ciò digerito, la tua operazione per estrarre tutti i riferimenti a un oggetto da quell'array in tutti i documenti diventa abbastanza semplice, come fatto nella shell (lo stesso formato dovrebbe sostanzialmente applicarsi a qualsiasi driver):
db.books.update(
{ "refs.oid": "object5" },
{ $pull: { refs: {oid: "object5"} } }, false, true )
I due argomenti extra per l'operazione di query e aggiornamento sono upsert
e multi
rispettivamente. In questo caso, upsert
non ha molto senso in quanto vogliamo solo modificare i documenti esistenti e multi
significa che vogliamo aggiornare tutto ciò che corrisponde. L'impostazione predefinita è modificare solo il primo documento.
Naturalmente ho abbreviato tutta la notazione, ma ovviamente i valori possono essere effettivi ObjectId secondo le tue intenzioni. Sembrava anche ragionevole presumere che il tuo utilizzo principale del main-reference
è una volta recuperato il documento. Definizione di una query che restituisce il main-reference
seguendo la logica che è stata delineata dovrebbe essere possibile, ma così com'è ho scritto molto qui e ho bisogno di una pausa per cena :)
Penso che questo rappresenti un caso utile per ripensare il tuo schema per evitare iterazioni over the wire per ciò che vuoi ottenere.