MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB/Mongoose Comment jumeler deux entrées db sans conflits ?

Suite à ma réponse originale , c'est encore quelque chose où une pensée différente peut vous venir en aide. Et en tant que tel, cela semble être plus une question d'architecture que de dire que l'implémentation de votre code "d'une certaine manière" sera la meilleure voie à suivre.

D'après votre commentaire à ce sujet et votre question ici, il semble que le problème que vous devez résoudre est de savoir comment ajuster le nombre de troupes pour l'autre utilisateur jouant le coup. Commençons par examiner à nouveau les mêmes données :

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

Faire le "bouger"

Donc, la situation ici est que l'utilisateur "B" vient de faire son mouvement et a engagé 62 unités dans ce mouvement. Dans le post précédent, j'ai expliqué comment récupérer le mouvement pour l'utilisateur correspondant "A", et donc vous pouvez les "associer" et déterminer la victoire.

Pour aller plus loin, considérez ce qui s'est passé dans la demande. L'utilisateur "B" a soumis, puis vous insérez le document pour son déménagement, puis vous relisez celui qui correspond. Donc, en ce moment, vous avez les deux documents en mémoire pour la demande. Si vous considérez les données de session, vous pourriez avoir quelque chose comme ceci (de manière très brève) :

{
    currentUnits: 100
}

Appelons cela le compte de départ. Ainsi, lorsque vous soumettez un mouvement de l'utilisateur, vous venez de décrémenter le nombre de troupes dont il dispose. Ainsi, lors de l'insertion de 62 troupes, le compteur va à ceci :

{
    currentUnits: 38
}

C'est une bonne pratique, car vous le faites sur l'accusé de réception d'insertion dans le mouvement. Mais ensuite à l'intérieur de ce rappel, vous allez faire la recherche comme je l'ai dit, et cela seulement renvoie un document. Vous avez maintenant les informations que vous pouvez comparer et faire vos calculs. L'utilisateur "B" gagne, vous pouvez donc ajuster la valeur de votre session :

{
    currentUnits: 150
}

Cela devrait donc tout couvrir pour le déménagement de l'utilisateur "B". Vous avez retiré des unités lorsqu'un coup a été joué, vous avez égalé l'autre joueur, puis vous avez "fait le calcul" et ajusté vos résultats. Fait! Oh, et vous avez enregistré toutes les données de session dans un magasin persistant, n'est-ce pas ? Hochez oui. Et aussi que les données de session sont liées au pseudo de l'utilisateur (ou l'utilisateur est en fait l'identifiant de session) afin d'avoir accès à sa modification.

Il ne reste plus qu'à "avertir" l'autre joueur.

Dire la nouvelle à quelqu'un d'autre

Cette partie doit être simple. Donc je ne le code pas pour vous. Vous utilisez socket.io pour votre application, donc tout cela se résume à envoyer un message. Cela signifie que les données que vous "émettez" indiquent à l'autre utilisateur du client qu'il a "perdu ses troupes", mais vous voulez y faire face. Mais rappelez-vous également que vous avez "retiré" ces unités lorsque leur déplacement a été soumis. Dans tous les cas, il s'agit de s'assurer que personne ne peut s'engager plus qu'il n'en a.

La seule chose dont il est possible de parler ici est la mise à l'échelle votre application au-delà d'une instance. Ainsi, vous pouvez parler avec plaisir avec des événements sur "nœud" qui fonctionnent tous sur une instance de serveur, mais pour "évoluer", vous devez transmettre des messages entre différentes instances.

Une façon de gérer cela en utilisant MongoDB peut être avec une collections plafonnées .

Mis à part ce que font généralement les collections plafonnées dans la manière de conserver un ensemble taille pour une collection de documents, il y a encore une chose qu'ils offrent, et c'est un curseur tailable . Une façon assez atypique d'en créer un avec le pilote de nœud serait du genre :

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

Les options complètes sont répertoriées dans le Cursor() section de la page du manuel du pilote. Vous pouvez accéder à ces méthodes "natives" dans la mangouste de la manière habituelle.

Ce qu'un curseur "tailable" est configuré pour faire est de "suivre" le document "dernier inséré" dans la collection et vous pouvez vous asseoir et "suivre" de cette manière avec un sondage pair, un peu comme dans :

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

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

Ainsi, dans une telle construction, vous "trouvez" le document nouvellement inséré et transmettez à votre rappel interne les informations à traiter, où vous "envoyez" des messages aux clients, mettez à jour des choses et tout ce que vous voulez faire.

Revenons à votre "demande" réelle, alors vous publieriez un encart après avoir "fait vos calculs" dans la "collection plafonnée" séparée. Vous voudriez quelque chose de significatif par brief comme :

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

Et encore une fois, ce ne sont que inserts. Vous devez donc configurer un index TTL pour gérer les suppressions au fil du temps et étant plafonnées, les anciennes entrées s'écouleraient naturellement en étant "éjectées" des entrées présentes dans la collection.

Côté "client", chaque application utilisateur connectée conserve la trace de la valeur du "dernier _id" reçue. Ainsi, les entrées nouvellement insérées sont toujours supérieur en valeur aux "plus anciens" précédents.

Il existe donc "une façon" d'utiliser MongoDB pour créer une file d'attente persistante que vous pouvez traiter de manière séquentielle afin de partager les messages transmis entre plusieurs instances de serveur d'applications.

Derniers mots

Avec tout ce qui a été dit pour implémenter un curseur "tail-able" de cette manière, pour mon argent j'utiliserais zeromq ou quelque chose de similaire. Mais vous trouverez peut-être que la méthode MongoDB vous convient mieux si vous ne souhaitez pas vous plonger dans une autre technologie. Ou peut-être que ce type de "scalabilité" n'est pas nécessaire pour votre application (du moins à ce stade) et qu'il suffit de passer aux méthodes "socket.io" dans la requête. À vous de décider.

En grande partie cependant, vous semblez toujours "accroché" à vos concepts de "couper" et de "supprimer". C'était l'intention de couvrir dans la dernière réponse et était de dire que supprimer des documents lors de leur traitement n'est pas nécessaire . Le processus décrit garantit que vous n'obtenez jamais la "même paire" de retour sur toute demande.

Je vous encourage à "relire" cette information et vraiment comprendre le processus. Et demandez si vous avez des questions. D'après ce qui a été discuté ici, l'analogie avec votre modèle d'accès aux données ressemble plus à "jouer sur une pile" qu'à "faire correspondre des paires".

Donc, ce qu'on vous a donné en réponse, suite à avec la logique décrite ici est tout dont vous avez besoin pour configurer vos modèles d'accès aux données. Votre autre composant sera bien sûr la messagerie, mais cela vous donne accès aux données dont vous avez besoin.