MongoDB Лучший способ связать и удалить последовательные записи базы данных

Ладно, скажем, я делаю игру в слепую войну! Пользователи A и B имеют x количество солдат

В настоящее время имеется 0 документов БД.

Пользователь А отправляет 50 солдат для создания документа БД. Пользователь Б отправляет 62 солдата после пользователя А!

Это создает новый документ БД.

Мне нужен наиболее эффективный/масштабируемый способ поиска документа пользователя А, сравнения его с документом пользователя Б, а затем удаления обоих документов! (После возврата результата, конечно)

Вот проблема! Потенциально я мог бы иметь более 10 000 пользователей, отправляющих солдат относительно одновременно! Как я могу успешно завершить вышеуказанный процесс без дублирования?

Я использую MEANstack для разработки, поэтому я не ограничен выполнением этого в базе данных, но, очевидно, веб-приложение должно быть на 100% безопасным!

Если вам нужна дополнительная информация или объяснение, пожалуйста, дайте мне знать, и я обновлю этот вопрос.

-Спасибо


person gbachik    schedule 09.03.2014    source источник
comment
Вот вопрос, который нужно посмотреть stackoverflow.com/questions/22262114/   -  person loveNoHate    schedule 10.03.2014
comment
сравнить 2 документа каким образом?   -  person mpm    schedule 10.03.2014
comment
Сравните как в: посмотрите на стоимость войск каждого документа! Эффективно разделив их по порядку. Ака документ 1 с 2 (возврат победителя = документ 1, удалить оба) документ 3 с 4 (возврат победителя = документ 4, удалить оба)   -  person gbachik    schedule 10.03.2014
comment
Кажется, что этого немного не хватает из-за того, что он слишком минимален. Я думаю, сначала вам нужно объяснить, как вы собираетесь хранить эти ходы для A и B, и четко объяснить, как вы узнаете, что они играют друг против друга. В противном случае это станет очень широким вопросом, и мнения каждого будут отличаться.   -  person Neil Lunn    schedule 10.03.2014
comment
Смысл игры в том, чтобы быть минимальным! Нет учетных записей, есть только пользователи на основе сеансов. В настоящее время в игре используются успокаивающие вызовы для игры. Каждый пользователь в основном играет против пользователя перед ним. Если бы пользователь до них отправил 20 войск, они бы отправили более 20, чтобы победить, но не знают, сколько отправил пользователь до них!   -  person gbachik    schedule 10.03.2014
comment
@dollarVar Я действительно думаю, что ответ немного отличается от вопроса, заданного в этом случае. Но если вы рассматриваете аналогичную проблему, то ответ, который я предоставил, может быть полезен и для вас.   -  person Neil Lunn    schedule 10.03.2014
comment
@NeilLunn Эй, спасибо за уведомление. И отличный ответ! Однако, честно говоря, у меня пока вообще нет подобных проблем, я по-прежнему стою перед никакими подготовленными операторами, но .eval(). (не по теме;)   -  person loveNoHate    schedule 10.03.2014
comment
У тебя было время переварить это. Общий случай заключается в том, что вместо того, чтобы вести долгую и затяжную дискуссию о параллелизме, которая ничего не решит, нужно сказать: «Эй, на самом деле есть другой способ решить вашу проблему». Хотя это не может быть прямым ответом, он действителен. Самое главное, он соответствует спецификациям того, что вы хотите сделать.   -  person Neil Lunn    schedule 10.03.2014


Ответы (1)


Одна вещь, которая приходит на ум, это то, что вам может не понадобиться выполнять всю работу, которую вы считаете необходимой, и ваша проблема, вероятно, может быть решена с небольшой помощью индексы TTL и, возможно, коллекции с ограничениями. Рассмотрим следующие записи:

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

Итак, есть две записи, и вы вернули это значение _id при вставке. Таким образом, в начале «А» не с кем было играть, но запись для «Б» будет играть против предыдущей.

ObejctId являются монотонными, что означает, что "следующий" всегда больше по стоимости от последнего. Итак, с вставленными данными просто сделайте следующее:

db.moves.find({ 
    _id: {$lt: ObjectId("531cf622ba53b9dd07756bb9") }, 
    user: { $ne: "B" } 
}).limit(1)

Это дает предыдущему вставленному «ходу» текущий только что сделанный ход, и делает это, потому что все, что было вставлено ранее, будет иметь _id с меньшим значением, чем текущий пункт. Вы также убедитесь, что вы не «играете» против собственного хода пользователя, и, конечно, вы ограничиваете результат только одним документом.

Таким образом, «ходы» будут всегда двигаться вперед. Когда следующая вставка будет сделана пользователем «C», они получат «ход» от пользователя «B», а затем пользователь «A» получит «ход» от пользователя «C». ", и так далее.

Все, что здесь "может" случиться, это то, что "Б" сделает следующий "ход" по порядку, и вы заберете тот же документ, что и в последнем запросе. Но это точка для вашего "сеансового" дизайна, чтобы сохранить последний "результат" и убедиться, что вы не получите то же самое обратно, и, таким образом, справиться с этим, однако вы хотите использовать в своем дизайне.

Этого должно быть достаточно, чтобы «поиграть». Но давайте перейдем к вашей части «удаление».

Естественно, вы «думаете», что хотите что-то удалить, но, вернемся к моим первоначальным «помощникам», в этом нет необходимости. Сверху удаление становится лишь фактором «очистки», поэтому ваша коллекция не разрастается до огромных размеров.

Если вы применили индекс TTL, во многом так же, как объясняет это руководство. , записи вашей коллекции будут очищены для вас и удалены через определенный период времени.

Кроме того, что можно сделать, и особенно учитывая, что мы используем возрастающую природу ключа _id и что это более или менее "очередь" по своей природе, вы могли бы применить это как ограниченная коллекция. Таким образом, вы можете установить максимальный размер того, сколько «ходов» вы будете сохранять в любой момент времени.

Объединив их вместе, вы получите что-то, что «вырастает» только до определенного размера и будет автоматически очищаться для вас, если активность немного замедлится. И это обеспечит быстрость всех операций.

Суть в том, что параллелизм «удалений», о котором вы беспокоились, был устранен путем фактического «удаления» необходимости удалять только что воспроизведенные документы. Запрос делает его простым, а индекс TTL и ограниченная коллекция позаботятся об управлении данными за вас.

Итак, вот что я думаю об очень параллельной игре «Война вслепую».

person Neil Lunn    schedule 10.03.2014
comment
Привет! На самом деле я думаю, что это решение почти идеально подходит для того, что мне нужно, и вчера я почти принял его! Однако проблема вот в чем. Отправляемые войска объединяются. Затем победитель получает x количество войск обратно из этого пула. Таким образом, если пользователь b играет за пользователя a, а пользователь c играет за пользователя b, то пул войск будет перевыведен, так как пользователь b владеет и его войска больше не находятся в центральном пуле! Есть ли способ применить ваш ответ выше, чтобы сопоставлялись только два пользователя? - person gbachik; 11.03.2014
comment
@gbachik Что я хотел показать здесь, что, учитывая контекст вашего вопроса, и что он основан на работе с парами документов, что можно избежать проблем параллелизма с обновлениями и удалениями и достичь того же результата. Так что это служит ответом на это. Ваша новая проблема интересна, но кое-что приходит на ум об уведомлении игроков о выигрышах/проигрышах, так сказать, из материала, который я вам дал. Подумайте об этом, и это все еще ускользает от вас, тогда вы всегда можете задать другой вопрос. - person Neil Lunn; 11.03.2014
comment
Истинный! Я задал здесь еще один вопрос: stackoverflow.com/questions/22316027/ - person gbachik; 11.03.2014