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

Denormalisering med Mongoose:Sådan synkroniseres ændringer

Ok, mens jeg venter på et bedre svar end mit eget, vil jeg prøve at skrive, hvad jeg har lavet indtil videre.

Pre/Post Middleware

Det første jeg prøvede var at bruge pre/post middlewares at synkronisere dokumenter, der refererede til hinanden. (For eksempel, hvis du har Author og Quote , og en forfatter har en matrix af typen:quotes: [{type: Schema.Types.ObjectId, ref:'Quotes'}] , så hver gang et citat slettes, skal du fjerne dets _id fra arrayet. Eller hvis forfatteren er fjernet, vil du måske have alle hans citater fjernet).

Denne tilgang har en vigtig fordel :hvis du definerer hvert skema i sin egen fil, kan du definere mellemvaren der og få det hele pænt organiseret . Når du ser på skemaet, lige nedenfor kan du se, hvad det gør, hvordan dets ændringer påvirker andre enheder osv.:

var Quote = new Schema({
    //fields in schema
})
//its quite clear what happens when you remove an entity
Quote.pre('remove', function(next) {
    Author.update(
        //remove quote from Author quotes array.
    )
})

Den største ulempe det er dog, at disse kroge ikke udføres, når du kalder opdatering eller nogen statisk modelopdaterings-/fjernelsesfunktion . I stedet skal du hente dokumentet og derefter kalde save() eller remove() på dem.

En anden mindre ulempe er, at Citat nu skal være opmærksom på alle, der henviser til det, så det kan opdatere dem, hver gang et Citat opdateres eller fjernes. Så lad os sige, at en Period har en liste over citater og Author har også en liste over citater. Citat skal kende til disse to for at opdatere dem.

Grunden til dette er, at disse funktioner sender atomforespørgsler direkte til databasen. Selvom dette er rart, hader jeg uoverensstemmelsen mellem at bruge save() og Model.Update(...) . Måske bruger en anden eller du i fremtiden ved et uheld de statiske opdateringsfunktioner, og din middleware udløses ikke, hvilket giver dig hovedpine, som du kæmper for at slippe af med.

NodeJS Event Mechanisms

Det, jeg gør i øjeblikket, er ikke rigtig optimalt, men det giver mig nok fordele til faktisk at opveje ulemperne (eller det tror jeg, hvis nogen gider give mig noget feedback, ville det være fantastisk). Jeg oprettede en tjeneste, der omslutter en model, f.eks. AuthorService der udvider events.EventEmitter og er en Constructor-funktion, der vil se nogenlunde sådan ud:

function AuthorService() {
    var self = this

    this.create = function() {...}
    this.update = function() {
        ...
        self.emit('AuthorUpdated, before, after)
        ...
    }
}

util.inherits(AuthorService, events.EventEmitter)
module.exports = new AuthorService()

Fordelene:

  • Enhver interesseret funktion kan tilmelde sig servicebegivenhederne og få besked. På den måde, for eksempel, når et Quote er opdateret, kan AuthorService lytte til den og opdatere Authors derfor. (Note 1)
  • Citat behøver ikke at være opmærksom på alle de dokumenter, der refererer til det, tjenesten udløser blot QuoteUpdated begivenhed og alle de dokumenter, der skal udføre handlinger, når dette sker, vil gøre det.

Bemærk 1:Så længe denne tjeneste bruges, når nogen har brug for at interagere med mongoose.

Ulemperne:

  • Tilføjet boilerplate-kode ved at bruge en tjeneste i stedet for mongoose direkte.
  • Nu er det ikke helt indlysende, hvilke funktioner der kaldes, når du udløser begivenheden.
  • Du afkobler producent og forbruger på bekostning af læselighed (da du bare emit('EventName', args) , det er ikke umiddelbart indlysende, hvilke tjenester der lytter til denne begivenhed)

En anden ulempe er, at nogen kan hente en model fra tjenesten og kalde save() , hvor begivenhederne ikke udløses selvom jeg er sikker på, at dette kunne løses med en slags hybrid mellem disse to løsninger.

Jeg er meget åben over for forslag på dette område (hvilket er grunden til, at jeg postede dette spørgsmål i første omgang).



  1. MongoDB kan ikke opdatere dokumentet, fordi _id er streng, ikke ObjectId

  2. Vedvarende og flush - Doktrin og MongoDB

  3. Send filen til aktivt job / baggrundsjob

  4. Mongo-forespørgsler tager lang tid. Hvordan gøre det hurtigere?