sql >> Database >  >> NoSQL >> MongoDB

Denormalisatie met Mongoose:wijzigingen synchroniseren

Ok, terwijl ik wacht op een beter antwoord dan het mijne, zal ik proberen te posten wat ik tot nu toe heb gedaan.

Pre/Post Middleware

Het eerste wat ik probeerde was de pre/post middlewares te gebruiken om documenten te synchroniseren die naar elkaar verwijzen. (Als u bijvoorbeeld Author . heeft en Quote , en een auteur heeft een array van het type:quotes: [{type: Schema.Types.ObjectId, ref:'Quotes'}] , dan moet je elke keer dat een citaat wordt verwijderd de _id . ervan verwijderen uit de reeks. Of als de auteur is verwijderd, wilt u misschien dat al zijn aanhalingstekens worden verwijderd).

Deze aanpak heeft een belangrijk voordeel :als u elk schema in zijn eigen bestand definieert, kunt u daar de middleware definiëren en alles netjes georganiseerd hebben . Telkens wanneer u naar het schema kijkt, kunt u direct hieronder zien wat het doet, hoe de wijzigingen andere entiteiten beïnvloeden, enz.:

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.
    )
})

Het belangrijkste nadeel is echter dat deze hooks niet worden uitgevoerd wanneer u update of een statische update-/verwijderingsfunctie van het model aanroept . In plaats daarvan moet u het document ophalen en vervolgens save() . aanroepen of remove() op hen.

Een ander kleiner nadeel is dat Quote nu op de hoogte moet zijn van iedereen die ernaar verwijst, zodat het deze kan bijwerken wanneer een Quote wordt bijgewerkt of verwijderd. Dus laten we zeggen dat een Period heeft een lijst met aanhalingstekens, en Author heeft ook een lijst met citaten, Quote moet deze twee weten om ze bij te werken.

De reden hiervoor is dat deze functies atomaire queries direct naar de database sturen. Hoewel dit leuk is, haat ik de inconsistentie tussen het gebruik van save() en Model.Update(...) . Misschien gebruikt iemand anders of jij in de toekomst per ongeluk de statische update-functies en wordt je middleware niet geactiveerd, waardoor je hoofdpijn krijgt waar je moeite mee hebt.

NodeJS-gebeurtenismechanismen

Wat ik momenteel doe is niet echt optimaal, maar het biedt me genoeg voordelen om de nadelen te overstijgen (althans, dat geloof ik, als iemand me feedback wil geven, zou dat geweldig zijn). Ik heb een service gemaakt die rond een model draait, zeg AuthorService dat breidt events.EventEmitter . uit en is een Constructor-functie die er ongeveer zo uitziet:

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

De voordelen:

  • Elke geïnteresseerde functie kan zich inschrijven voor de Serviceevents en op de hoogte worden gebracht. Op die manier, bijvoorbeeld, wanneer een Quote is bijgewerkt, kan de AuthorService ernaar luisteren en de Authors update bijwerken overeenkomstig. (Opmerking 1)
  • Quote hoeft niet op de hoogte te zijn van alle documenten die ernaar verwijzen, de Service activeert eenvoudig de QuoteUpdated gebeurtenis en alle documenten die bewerkingen moeten uitvoeren wanneer dit gebeurt, zullen dit doen.

Opmerking 1:Zolang deze service wordt gebruikt wanneer iemand met mangoest moet communiceren.

De nadelen:

  • Boilerplate-code toegevoegd, waarbij rechtstreeks een service wordt gebruikt in plaats van mangoest.
  • Het is nu niet precies duidelijk welke functies worden aangeroepen als je de gebeurtenis activeert.
  • Je ontkoppelt producent en consument ten koste van de leesbaarheid (aangezien je gewoon emit('EventName', args) , het is niet meteen duidelijk welke diensten naar dit evenement luisteren)

Een ander nadeel is dat iemand een Model uit de Service kan halen en save() . kan aanroepen , waarbij de gebeurtenissen niet worden geactiveerd hoewel ik zeker weet dat dit kan worden aangepakt met een soort hybride tussen deze twee oplossingen.

Ik sta erg open voor suggesties op dit gebied (daarom heb ik deze vraag in de eerste plaats gepost).



  1. blpop stopt na een tijdje met het verwerken van de wachtrij

  2. MongoDB:proberen om Long uit JSON te lezen, veroorzaakt java.lang.Integer kan niet worden gecast naar java.lang.Long

  3. MongoError:getaddrinfo ENOTFOUND undefined undefined:27017

  4. MongoDB updateMany met voorwaardelijk