sql >> Database >  >> NoSQL >> MongoDB

MongoDB/Mongoose Hoe koppel ik twee db-items zonder conflicten?

In vervolg op mijn oorspronkelijke reactie , dit is weer iets waar een andere manier van denken je te hulp kan komen. En als zodanig lijkt dit meer over architectuur te gaan dan te zeggen dat het implementeren van je code "op een bepaalde manier" de beste manier is om te gaan.

Uit uw opmerking daarover en uw vraag hier, lijkt het erop dat het probleem dat u moet oplossen, is hoe u het aantal troepen voor de andere kunt aanpassen. gebruiker die de zet speelt. Laten we beginnen door opnieuw naar dezelfde gegevens te kijken:

{ "_id" : ObjectId("531cf5f3ba53b9dd07756bb7"), "user" : "A", "units" : 50 }
{ "_id" : ObjectId("531cf622ba53b9dd07756bb9"), "user" : "B", "units" : 62 }

De "verplaatsing" maken

Dus de situatie hier is dat gebruiker "B" net zijn zet heeft gedaan en 62 committed heeft gepleegd eenheden in die beweging. In het vorige bericht heb ik uitgelegd hoe je de zet terug kunt krijgen voor de overeenkomende gebruiker "A", en daarom kun je ze "koppelen" en de overwinning bepalen.

Als je dat verder bekijkt, overweeg dan wat er in het verzoek is gebeurd. Gebruiker "B" heeft ingediend, dan voegt u het document voor hun zet in en leest u het overeenkomende terug. Dus op dit moment heb je beide documenten in het geheugen voor het verzoek. Als je kijkt naar de sessiegegevens, dan heb je misschien zoiets als dit (in het kort):

{
    currentUnits: 100
}

Laten we dat de starttelling noemen. Dus wanneer u indient een zet van de gebruiker, je verlaagt gewoon het aantal troepen dat ze hebben. Dus bij het invoegen van 62 troepen, de teller gaat naar dit:

{
    currentUnits: 38
}

Dat is een goede gewoonte, aangezien u dat doet op de invoegbevestiging binnen de verhuizing. Maar de volgende keer dat je terugbelt, ga je de vondst doen zoals ik al zei, en dat alleen retourneert één document. Nu heb je de informatie die je kunt vergelijken en je berekeningen kunt maken. Gebruiker "B" wint, zodat u uw sessiewaarde kunt aanpassen:

{
    currentUnits: 150
}

Dus dat zou alles moeten dekken voor de verhuizing voor gebruiker "B". Je nam eenheden weg wanneer een zet werd gespeeld, je paste bij de andere speler, vervolgens "deed je de wiskunde" en paste je resultaten aan. Gedaan! Oh, en je hebt opgeslagen alle sessiegegevens in een permanente opslag, nietwaar? Ja knikken. En ook die sessiegegevens zijn gekoppeld aan de gebruikershandle (of de gebruiker is in feite de sessie-ID) om toegang te krijgen tot het wijzigen ervan.

Het enige dat overblijft is om de andere speler te "verwittigen".

Iemand anders het nieuws vertellen

Dit deel moet eenvoudig zijn. Dus ik codeer het niet voor je. Je gebruikt socket.io voor je sollicitatie, dus het komt er allemaal op aan om een ​​bericht te sturen. Dat betekent dat de gegevens die u "uitzendt" de andere gebruiker op de client vertellen dat ze "hun troepen hebben verloren", hoe u er ook mee om wilt gaan. Maar onthoud ook dat je die eenheden "wegnam" wanneer hun zet werd ingediend. In alle gevallen is dat ervoor zorgen dat niemand meer kan vastleggen dan ze hebben.

Het enige mogelijke om hier over te praten is schalen uw toepassing meer dan één instantie. U kunt dus vrolijk praten met gebeurtenissen op "knooppunt" die allemaal op één serverinstantie werken, maar om te "schalen" zou u berichten tussen verschillende instanties moeten doorgeven.

Een manier om dit aan te pakken met MongoDB kan zijn met een capped collections .

Afgezien van wat gecapte collecties over het algemeen doen op het gebied van het bijhouden van een set grootte voor een verzameling documenten, is er nog iets dat ze bieden, en dat is een tailable cursor . Een tamelijk atypische manier om er een te maken met het knooppuntstuurprogramma zou zijn als:

var options = { tailable: true, awaitdata: true, numberOfRetries: -1 };
var cursor = collection.find(query, options).sort({ $natural: 1 });

De volledige opties staan ​​vermeld in de Cursor() gedeelte van de handleiding van het stuurprogramma. Je kunt deze "native" methoden in mangoest op de typische manier krijgen.

Wat een "aanwijsbare" cursor moet doen, is het "laatst ingevoegde" document in de verzameling "volgen" en u kunt op deze manier gaan zitten en "volgen" met een gelijkmatige peiling, ongeveer zoals in:

    (function more() {
        cursor.nextObject(handle(function(doc) {
            if (!doc) return setTimeout(poll, self.wait);

            callback(doc);
            latest = doc._id;
            more();
        }));
    })();

Dus binnen zo'n constructie "vindt" u het nieuw ingevoegde document en geeft u de informatie die moet worden verwerkt door aan uw innerlijke callback, waar u berichten naar klanten "verstuurt", dingen bijwerkt en wat u nog meer wilt doen.

Terug naar uw werkelijke "verzoek", dan zou u een invoeging uitgeven nadat u "uw wiskunde heeft gedaan" naar de afzonderlijke "afgetopte verzameling". Je zou iets zinnigs willen in het kort, zoals:

{ "player": "B", "vsplayer": "A", "win": 50, "loss": 62 }

En nogmaals, dit zijn slechts inzetstukken. U zou dus een TTL-index instellen om de verwijderingen in de loop van de tijd af te handelen en te worden afgetopt, zouden de oude items natuurlijk leeglopen door te worden "geduwd" uit de items die in de verzameling aanwezig zijn.

Aan uw "client"-kant houdt elke verbonden gebruikerstoepassing de ontvangen "laatste _id"-waarde bij. Dus de nieuw ingevoegde items zijn altijd groter in waarde dan de "oudere" vorige.

Er is dus "een manier" om MongoDB te gebruiken om een ​​aanhoudende wachtrij te maken die u achtereenvolgens kunt verwerken om berichten te delen tussen meerdere instanties van de toepassingsserver.

Laatste woorden

Met alles gezegd voor het implementeren van een "tail-able" cursor op deze manier, zou ik voor mijn geld zeromq gebruiken of iets dergelijks. Maar misschien vindt u de MongoDB-methode meer geschikt voor u als u zich niet in een andere technologie wilt verdiepen. Of misschien is dit soort "schaalbaarheid" niet nodig voor uw toepassing (tenminste in dit stadium) en is het voldoende om eenvoudigweg over te gaan naar "socket.io"-methoden binnen het verzoek. Aan jou.

Grotendeels echter, lijkt u nog steeds "op te hangen" aan uw concepten van "paren" en "verwijderen". Dit was de bedoeling om in de laatste reactie te behandelen en was om te zeggen dat verwijderen van documenten wanneer ze worden verwerkt, is niet vereist . Het beschreven proces zorgt ervoor dat je nooit het "hetzelfde paar" . krijgt terug op elk verzoek.

Ik zou je willen aanmoedigen om "opnieuw te lezen" die informatie en het proces echt begrijpen. En stel gerust als je vragen hebt. Van wat daar is besproken, lijkt de analogie van je gegevenstoegangspatroon meer op "een stapel uitspelen" dan "paren matchen".

Dus wat u als antwoord kreeg, in vervolg op met de hier beschreven logica is alles die u nodig heeft om uw gegevenstoegangspatronen in te stellen. Je andere component is natuurlijk de berichtgeving, maar dit geeft je toegang tot de gegevens die je nodig hebt.




  1. Strategieën voor snel zoeken van miljarden kleine documenten in MongoDB

  2. Geneste array bijwerken in array mongodb

  3. Hoe een query uit te voeren met punt (. ) via Mongoose in Node.js en hoe een lege array toe te voegen

  4. Hoe kan ik twee velden bijwerken in één opdracht in MongoDB?