MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

MongoDB/Mongoose Как да сдвоя два db записа без конфликти?

Следвайки моя оригинален отговор , това отново е нещо, при което различно мислене може да ви дойде на помощ. И като такова изглежда, че това е повече за архитектурата, отколкото да се каже, че внедряването на вашия код "по определен начин" ще бъде най-добрият начин.

От коментара ви за това и въпроса ви тук изглежда, че проблемът, който трябва да разрешите, е как да коригирате броя на войските за другите потребител, който играе хода. Нека започнем, като разгледаме същите данни отново:

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

Извършване на „движението“

Така че ситуацията тук е, че потребителят "B" току-що е направил своя ход и е ангажирал 62 единици в този ход. В предишната публикация обясних как да върна хода за съвпадащия потребител "A" и следователно можете да ги "сдвоите" и да определите победата.

Вземайки това по-нататък, помислете какво се е случило в заявката. Потребителят „B“ изпрати, след което вмъквате документа за неговия ход, след което четете съвпадащия. Така че в момента имате и двата документа в паметта за заявката. Ако вземете предвид данните за сесията, тогава може да имате нещо подобно (по много кратък начин):

{
    currentUnits: 100
}

Нека наречем това начален брой. Така че, когато изпращате ход от потребителя, вие просто намалявате броя на войските, които имат. Така че, когато правитевмъкнете от 62 войски, броячът отива на това:

{
    currentUnits: 38
}

Това е добра практика, тъй като правите това при потвърждението за вмъкване в хода. Но следващия път в това обратно извикване ще извършите намирането, както казах, и то само връща един документ. Сега имате информацията, която можете да сравните и да си направите сметката. Потребител "B" печели, така че можете да коригирате стойността на вашата сесия:

{
    currentUnits: 150
}

Така че това трябва да покрие всичко за преместването за потребител "B". Отнехте единици, когато беше изигран ход, съпоставихте другия играч, след това „направихте математиката“ и коригирахте резултатите си. Свършен! О, и вие спестихте всички данни за сесията в постоянен магазин, нали? Кимам да. И също така, че данните за сесията са свързани с потребителския манипулатор (или потребителят всъщност е идентификационният номер на сесията), за да получат достъп до модифицирането им.

Всичко, което остава, е да "уведомите" другия играч.

Разказване на новината на някой друг

Тази част трябва да е проста. Така че не го кодирам вместо вас. Вие използвате socket.io за вашето приложение, така че всичко това се свежда до изпращане на съобщение. Това означава, че данните, които „излъчвате“, казват на другия потребител на клиента, че са „загубили войските си“, но вие искате да се справите с тях. Но също така не забравяйте, че сте „отнели“ тези единици, когато се преместят беше подадено. Във всички случаи това е да се гарантира, че никой не може да ангажира повече, отколкото е поел.

Единственото възможно нещо, за което може да се говори тук, е мащабирането вашето приложение извън един екземпляр. Така че можете да говорите щастливо със събития на „възел“, всички работещи на един сървърен екземпляр, но за „мащабиране“ ще трябва да предавате съобщения между различни екземпляри.

Един от начините да се справите с това с помощта на MongoDB може да бъде с ограничени колекции .

Освен това, което колекциите с таван обикновено правят в начина на поддържане на набор размер за колекция от документи, има още нещо, което предлагат, и това е подвижен курсор . Доста нетипичен начин за създаване на такъв с драйвера на възела би бил като:

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

Пълните опции са изброени в Cursor() раздел на страницата с ръководството на драйвера. Можете да стигнете до тези "родни" методи в mongoose по типичния начин.

Това, за което е настроен курсорът, който може да се изпълнява, е да „следва“ „последния вмъкнат“ документ в колекцията и можете да седнете и да „следвате“ по този начин с равномерна анкета, подобно на:

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

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

Така че в рамките на такава конструкция вие „намирате“ нововмъкнатия документ и предавате на вашето вътрешно обратно извикване информацията, която трябва да бъде обработена, където „изпращате“ съобщения до клиенти, актуализирате неща и каквото друго искате да направите.

Обратно към вашата действителна „заявка“, тогава ще издадете вмъкване, след като сте „направили сметката си“ към отделната „ограничена колекция“. Бихте искали нещо смислено от кратко като:

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

И отново те са самос вложки. Така че бихте настроили TTL индекс за да се справят с изтриванията с течение на времето и да бъдат ограничени, старите записи естествено ще се източат, като бъдат „изтласкани“ от записите, налични в колекцията.

От страна на вашия „клиент“ всяко свързано потребителско приложение следи получената стойност „last _id“. Така че нововмъкнатите записи са винаги по-голяма по стойност от "по-старите" предишни.

Така че има "един начин" да използвате MongoDB за създаване на постоянна опашка, която можете да обработвате последователно, за да споделите предаването на съобщения между множество екземпляри на сървър на приложения.

Последни думи

С всичко казано за внедряване на курсор с възможност за "опашка" по този начин, за моите пари бих използвал zeromq или нещо подобно. Но може да откриете, че методът MongoDB е по-подходящ за вас, ако не искате да се задълбочавате в друга технология. Или може би този вид „мащабируемост“ не е необходим на вашето приложение (поне на този етап) и простото преминаване към методите „socket.io“ в заявката би било достатъчно. Зависи от вас.

До голяма степен обаче изглежда, че все още сте „окачени“ на концепциите си за „изрязване“ и „изтриване“. Това беше намерението да се обхване в последния отговор и беше да се каже, че изтриване документи, когато се обработват, не не се изисква . Описаният процес гарантирана че никога няма да получите "същия чифт" обратно при всяка заявка.

Бих ви насърчил да „препрочетете“ тази информация и наистина да разберете процеса. И питайте, ако имате въпроси. От това, което беше обсъдено там, аналогията с вашия модел за достъп до данни е по-скоро като „разиграване на стек“, отколкото „съвпадение на двойки“.

И така, това, което ви беше дадено в отговор, следва с описаната тук логика евсички трябва да имате нужда, за да настроите моделите си за достъп до данни. Другият ви компонент ще бъде, разбира се, съобщенията, но това ви дава достъп до данните, от които се нуждаете.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. как да задам нивото на регистриране на информация за MongoDb?

  2. MongoDB актуализира документ, когато вече съществува с ReactiveMongo

  3. Вмъкнете голям запис в mongodb с помощта на mongo shell

  4. Справяне с това как MongoDB съхранява DateTime, когато се използва с модел на локатор на услуги

  5. C# 10gen и mongo:десериализация за членове като интерфейси