sql >> Databasteknik >  >> NoSQL >> MongoDB

Denormalisering med Mongoose:Hur man synkroniserar ändringar

Ok, medan jag väntar på ett bättre svar än mitt eget, ska jag försöka lägga upp vad jag har gjort hittills.

Pre/Post Middleware

Det första jag försökte var att använda pre/post middlewares för att synkronisera dokument som refererade till varandra. (Till exempel om du har Author och Quote , och en författare har en array av typen:quotes: [{type: Schema.Types.ObjectId, ref:'Quotes'}] , närhelst ett citat raderas måste du ta bort dess _id från arrayen. Eller om författaren tas bort kanske du vill att alla hans citat tas bort).

Detta tillvägagångssätt har en viktig fördel :om du definierar varje schema i sin egen fil kan du definiera mellanvaran där och få allt prydligt organiserat . När du tittar på schemat, precis nedanför kan du se vad det gör, hur dess ändringar påverkar andra enheter, etc:

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örsta nackdelen är dock att dessa krokar inte exekveras när du anropar uppdatering eller några statiska uppdaterings-/borttagningsfunktioner för modell . Istället måste du hämta dokumentet och sedan anropa save() eller remove() på dem.

En annan mindre nackdel är att Quote nu måste vara medveten om alla som refererar till det, så att det kan uppdatera dem när ett offert uppdateras eller tas bort. Så låt oss säga att en Period har en lista med citat och Author har en lista med citat också, Quote måste känna till dessa två för att uppdatera dem.

Anledningen till detta är att dessa funktioner skickar atomfrågor direkt till databasen. Även om detta är trevligt, hatar jag inkonsekvensen mellan att använda save() och Model.Update(...) . Kanske någon annan eller du i framtiden råkar använda de statiska uppdateringsfunktionerna och din mellanprogramvara inte utlöses, vilket ger dig huvudvärk som du kämpar för att bli av med.

NodeJS Event Mechanisms

Det jag gör för närvarande är inte riktigt optimalt men det ger mig tillräckligt med fördelar för att faktiskt väga upp nackdelarna (eller så tror jag, om någon bryr sig om att ge mig lite feedback skulle det vara bra). Jag skapade en tjänst som omsluter en modell, säg AuthorService som utökar events.EventEmitter och är en konstruktorfunktion som kommer att se ut ungefär så här:

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

Fördelarna:

  • Alla intresserade funktioner kan registrera sig på Serviceevents och bli meddelade. På det sättet, till exempel, när en Quote är uppdaterad kan AuthorService lyssna på den och uppdatera Authors följaktligen. (Anmärkning 1)
  • Citat behöver inte vara medveten om alla dokument som hänvisar till det, tjänsten utlöser helt enkelt QuoteUpdated händelse och alla dokument som behöver utföra operationer när detta händer kommer att göra det.

Obs 1:Så länge den här tjänsten används när någon behöver interagera med mangust.

Nackdelarna:

  • Lägg till boilerplate-kod, använder en tjänst istället för mongoose direkt.
  • Nu är det inte direkt uppenbart vilka funktioner som anropas när du utlöser händelsen.
  • Du frikopplar producent och konsument på bekostnad av läsbarheten (eftersom du bara emit('EventName', args) , det är inte direkt uppenbart vilka tjänster som lyssnar på den här händelsen)

En annan nackdel är att någon kan hämta en modell från tjänsten och anropa save() , där händelserna inte utlöses även om jag är säker på att detta skulle kunna lösas med någon form av hybrid mellan dessa två lösningar.

Jag är väldigt öppen för förslag på detta område (vilket är anledningen till att jag postade den här frågan i första hand).



  1. pymongo:ta bort dubbletter (förminska kartan?)

  2. MongoDb-frågevillkor vid jämförelse av 2 fält

  3. Fråga mongodb för villkorade villkor

  4. hur lägger man till --auth för mongodb-bild när man använder docker-compose?