Hi
I'm evaluating mongo-db for a tick-based game where I need to update a
lot of documents each time the game "ticks". These updates a related
to a sort of commodity exchange, where the prices can change for each
tick. Players can place orders to be executed once certain market
conditions are met, and it is these orders I need to evaluate for each
tick. My current idea is to represent the state of each player with
documents of the form:
{
credits: 200,
inventory:
[
{name: "gold", quantity: 125 }
],
orders:
[
{ type: "sell", name: "gold", limit: 15, quantity: 20}
{ type: "sell", name: "gold", limit: 40, quantity: 50}
{ type: "buy", name: "silver", limit: 30, quantity: 50}
],
order_count: 3
}
for each tick I then need to:
1) find documents where order_count > 0
2) for each of these documents evaluate the orders and credits fields
against context data: "game time" and a table with commodity-prices
3) do a per-document atomic-update if buy/sell conditions are met
I have so far prototyped this by:
1) Query to find potential documents:
db.gamestate.find({ "order_count" : { $gt: 0} } );
2) Load each document to java backend, and evaluate against price
data
3) Update using atomic operators:
db.game.update(
{credit: {$gt: 50}, "
inventory.name": "gold", orders: {name:
"gold", quantity: 25, type: "buy", limit: 50 }},
{$inc: {credit: -50}, $inc: {"inventory.$.quantity": 25},
$inc: {order_count: -1}, $pull: {orders: {name: "gold", quantity:
25, type: "buy", limit: 50 }}} );
This approach does however have a number of problems:
1) I need to transfer a lot of full documents out of the server to
do the evaluation. At any given tick, only a few of them is likely to
be triggered.
2) Nasty atomic update, and it even depends on the 'inventory' field
being pre-polutated with entries for each commodity in existence,
since the positional operator depends on finding an existing entry.
Seems to me what is really needed is a sort of multi-update with a
procedure to atomically calculate and apply the update for each
document that matches the overall criteria for consideration. I've
been looking at using map/reduce and db.eval but neither seems to fit
the description. In map/reduce the doc and forum suggest you are not
able/supposed to manipulate the db, and the db.eval documentation
suggests that db.eval blocks other operations. Any solution should
preferably work with sharding as well.
Okay, that was a lot of background info. My hope was you could help
answer the following questions:
1) The db.eval doc says "In 1.7.2, a nolock option was added to
db.eval". Can anyone expand on that, and does it mean that db.eval
would be a fit for my requirements?
2) Are there other approaches that would be a better way to solve the
problem?
Thanks