MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

MongoDB/Mongoose Jak sparować dwa wpisy bazy danych bez konfliktów?

Kontynuacja mojej oryginalnej odpowiedzi , to znowu coś, w czym może ci pomóc inne myślenie. I wydaje się, że chodzi tu bardziej o architekturę niż o to, że implementacja kodu „w określony sposób” będzie najlepszą drogą.

Z twojego komentarza na ten temat i twojego pytania tutaj, wydaje się, że problemem, który musisz rozwiązać, jest dostosowanie liczby żołnierzy do innych użytkownik grający ruch. Zacznijmy od ponownego spojrzenia na te same dane:

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

Wykonywanie „ruchu”

Tak więc sytuacja jest taka, że ​​użytkownik „B” właśnie wykonał swój ruch i popełnił 62 jednostki w tym ruchu. W poprzednim poście wyjaśniłem, jak odzyskać ruch dla pasującego użytkownika „A”, a zatem możesz go „sparować” i określić wygraną.

Idąc dalej, zastanów się, co się stało w prośbie. Użytkownik „B” został zgłoszony, a następnie wstawiasz dokument do jego przeniesienia, a następnie odczytujesz odpowiedni. Więc teraz masz oba dokumenty w pamięci na żądanie. Jeśli weźmiesz pod uwagę dane sesji, możesz mieć coś takiego (w bardzo krótkim czasie):

{
    currentUnits: 100
}

Nazwijmy to liczeniem początkowym. Więc kiedy przesyłasz ruch od użytkownika, po prostu zmniejszasz liczbę posiadanych żołnierzy. Więc kiedy robisz wstawkę z 62 żołnierzy, licznik idzie do tego:

{
    currentUnits: 38
}

To dobra praktyka, ponieważ robisz to na potwierdzeniu wstawienia w ruchu. Ale w następnej kolejności w tym wywołaniu zwrotnym zamierzasz znaleźć, jak powiedziałem, i to tylko zwraca jeden dokument. Teraz masz informacje, które możesz porównać i policzyć. Użytkownik „B” wygrywa, więc możesz dostosować wartość sesji:

{
    currentUnits: 150
}

Tak więc powinno to obejmować wszystko dla ruchu dla użytkownika „B”. Zabierałeś jednostki, gdy był rozgrywany ruch, dopasowywałeś drugiego gracza, a następnie „zrobiłeś matematykę” i dostosowałeś swoje wyniki. Gotowe! Aha, i udało Ci się zapisać wszystkie dane sesji w trwałym sklepie, prawda? Przytakuj tak. A także, że dane sesji są powiązane z uchwytem użytkownika (lub użytkownik jest w rzeczywistości identyfikatorem sesji) w celu uzyskania dostępu do jego modyfikacji.

Pozostało tylko „powiadomić” drugiego gracza.

Przekazywanie komuś wiadomości

Ta część powinna być prosta. Więc nie koduję tego dla ciebie. Używasz socket.io dla twojej aplikacji, więc wszystko sprowadza się do wysłania wiadomości. Oznacza to, że dane, które „wyemitujesz”, informują innego użytkownika klienta, że ​​„stracił swoje wojska”, niezależnie od tego, jak chcesz sobie z tym poradzić. Pamiętaj jednak, że „zabrałeś” te jednostki, gdy ich ruch zostało wysłane. We wszystkich przypadkach jest to upewnienie się, że nikt nie może zatwierdzić więcej niż ma.

Jedyną możliwą rzeczą do omówienia tutaj jest skalowanie Twoja aplikacja poza jedną instancją. Możesz więc swobodnie rozmawiać ze zdarzeniami na „węźle”, które działają na jednej instancji serwera, ale aby „skalować”, musisz przekazywać wiadomości między różnymi instancjami.

Jednym ze sposobów radzenia sobie z tym za pomocą MongoDB może być użycie z limitowanych kolekcji .

Oprócz tego, co zwykle robią kolekcje ograniczone w sposobie utrzymywania zestawu rozmiar dla kolekcji dokumentów, jest jeszcze jedna rzecz, którą oferują, a jest to kursor ogonowy . Dość nietypowy sposób na utworzenie takiego ze sterownikiem węzła wygląda następująco:

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

Pełne opcje są wymienione w Cursor() na stronie podręcznika sterownika. Możesz dostać się do tych "natywnych" metod w manguście w typowy sposób.

Kursor „ogonalny” ma „podążać” za „ostatnio wstawionym” dokumentem do kolekcji i można w ten sposób siedzieć i „śledzić” z równą ankietą, podobnie jak w:

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

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

Tak więc w ramach takiej konstrukcji „znajdziesz” nowo wstawiony dokument i przekazujesz swojemu wewnętrznemu wywołaniu zwrotnemu informacje do przetworzenia, gdzie „wysyłasz” wiadomości do klientów, aktualizujesz rzeczy i cokolwiek innego, co chcesz zrobić.

Wracając do rzeczywistej "prośby", to po "zrobieniu matematyki" wystawiłbyś wkładkę do oddzielnej "zamkniętej kolekcji". Chciałbyś czegoś znaczącego w skrócie, takiego jak:

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

I znowu są to tylko wstawki. Skonfiguruj więc indeks TTL aby poradzić sobie z usuwaniem z biegiem czasu i być ograniczanym, stare wpisy w naturalny sposób wyczerpią się, zostając „wypchnięte” z wpisów obecnych w kolekcji.

Po stronie „klienta” każda połączona aplikacja użytkownika śledzi otrzymaną wartość „ostatni _id”. Więc nowo wstawione wpisy są zawsze większą wartość od „starszych” poprzednich.

Tak więc istnieje "jeden sposób" na użycie MongoDB do utworzenia trwałej kolejki, którą można sekwencyjnie przetwarzać w celu współdzielenia przekazywania komunikatów między wieloma instancjami serwera aplikacji.

Końcowe słowa

Biorąc pod uwagę wszystko, co zostało powiedziane za zaimplementowaniem w ten sposób kursora "ogonowego", za moje pieniądze używałbym zeromq lub coś podobnego. Ale może się okazać, że metoda MongoDB będzie dla Ciebie bardziej odpowiednia, jeśli nie chcesz zagłębiać się w inną technologię. A może tego rodzaju "skalowalność" nie jest potrzebna twojej aplikacji (przynajmniej na tym etapie) i wystarczyłoby przejście do metod "socket.io" w żądaniu. Do Ciebie.

W dużej mierze jednak nadal wydajesz się być "zawieszony" na swoich koncepcjach "parowania" i "usuwania". Miało to na celu uwzględnienie w ostatniej odpowiedzi i stwierdzenie, że usuwanie dokumentów podczas ich przetwarzania nie jest wymagane . Opisany proces zapewnia że nigdy nie otrzymasz „tej samej pary” z powrotem na każde żądanie.

Zachęcam do „ponownego przeczytania” te informacje i naprawdę zrozumieć proces. I zapytaj, czy masz pytania. Z tego, co zostało tam omówione, analogia do wzorca dostępu do danych jest bardziej jak „odgrywanie stosu” niż „dopasowywanie par”.

A więc to, co otrzymałeś w odpowiedzi, po z opisaną tutaj logiką to wszystkie powinieneś potrzebować, aby skonfigurować swoje wzorce dostępu do danych. Twoim drugim komponentem będzie oczywiście przesyłanie wiadomości, ale daje to dostęp do potrzebnych danych.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Aktualizacja listy osadzonych dokumentów w mongoengine

  2. Jak używać zmiennych w zapytaniu MongoDB?

  3. MongoDB:Problemy z użyciem $concat do aktualizacji wartości pola

  4. Łączenie się z bazą danych Mongo przez tunel SSH w Javie

  5. mongodb:zapytaj kilka pierwszych wierszy, w których suma określonej kolumny jest większa lub równa C