Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Running stored functions from Java API
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Keith Branton  
View profile  
 More options Jan 14 2011, 11:43 am
From: Keith Branton <ke...@branton.co.uk>
Date: Fri, 14 Jan 2011 09:43:47 -0700
Local: Fri, Jan 14 2011 11:43 am
Subject: Re: [mongodb-user] Re: Running stored functions from Java API

HG, how are you getting on with this?

I meant for you to use findAndModify on a collection that maintains the max
value. Sorry I was not clearer in my original post.

How you maintain the mapping in a concurrency-safe way is a little
different. How big of a problem is it if you occasionally end up with gaps
in your number sequence? If that's not a big deal then I would suggest an
algorithm such as this, assuming one collection called map {_id:key,
value:Integer}, and one called max {_id:0, current:Integer}:

public Integer getMappingFor(String key) {
    DBObject result = map.findOne(new BasicDBObject("_id",key));
    if (result != null) {
        return (Integer)result.get("value");
    }
    // at this point we need to record a new mapping
    // use find and modify on the max collection to get a new value
    DBObject query = new BasicDBObject("_id", 0);
    DBObject update = new BasicDBObject("$inc", new BasicDBObject("current",
1));
    Integer value = (Integer)max.findAndModify(query, null, null, false,
update, true, true).get("current");
    // now we need to attempt to map the key to the value
    // note that another host may have done this since we starting this
function
    try {
        map.insert(new BasicDBObject("_id", key).append("value", value),
WriteConcern.SAFE);
        return value;
    } catch (DuplicateKey e) {
        // if we're here then another host already recorded the mapping
        return (Integer)max.find(new BasicDBObject("_id",key).get("value"));
    }

}

This assumes that DBCollections max and map are in scope. Untested code
warning! Should be pretty close.

On the upsert we are providing a query to find the one and only record, an
update to increment current, and flags to insert if that record did not
exist, and return the new document rather than the original.

On the insert we use WriteConcern.SAFE so that the DuplicateKey exception
gets thrown if we try to insert a duplicate. Without that mode our request
would be quietly ignored.

It is possible for sequence numbers to be skipped in the case of collisions,
because if we can't insert the new mapping we discard the new key and use
the one from the collection we collided with. If skipping sequence numbers
is a problem then that too can be solved, but it adds complexity.

If you are performing many of these lookups on each host I would also
recommend caching the results on each host to save requesting the same value
more than once. How you cache depends on how many distinct values you are
creating keys for.

Hope this helps,

Keith.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.