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
 
HG  
View profile  
 More options Jan 17 2011, 11:42 am
From: HG <hg.l...@gmail.com>
Date: Mon, 17 Jan 2011 18:42:04 +0200
Local: Mon, Jan 17 2011 11:42 am
Subject: Re: [mongodb-user] Re: Running stored functions from Java API
Thanks Keith!

I think you understood my problem. What you propose seems to be ok -
except that I need to check the gaps. But otherwise - thanks a lot!
This is how far I got myself:
1) In java, get index for string
2) if it returns null, then call this function on server:

> function saveAndGetNew(s){

...   var newstr = db.map.findOne({"_id" : s});
...   if (newstr == null){
...     var max = db.map.findOne({"_id" : 0});
...     max.CurrentMax++;
...     db.map.save(max);
...     db.map.save({"_id" : s, "index" : max.CurrentMax});
...     return max.CurrentMax;
...   } else {
...     return newstr.index;
...   }
... }

> db.map.save({"_id": 0, "CurrentMax" : 0})

Which seems to work:

> db.map.find()

{ "_id" : 0, "CurrentMax" : 0 }
> saveAndGetNew("String1")
1
> saveAndGetNew("String2")
2
> saveAndGetNew("String3")
3
> saveAndGetNew("String2")
2
> db.map.find()

{ "_id" : 0, "CurrentMax" : 3 }
{ "_id" : "String1", "index" : 1 }
{ "_id" : "String2", "index" : 2 }
{ "_id" : "String3", "index" : 3 }

So, now if I can call this from Java, I can try you method and this to
see which works faster. (Yes, I will cache all ID's on the client
nodes as far as I have memory there.) However, how to call that from
Java (as was my original question)? Java docs contain "eval" and
"doEval" however, the javadoc doesn't tell anything about those
commands, so I don't know what they do or how to use them (at least my
trial calls such as above from the shell, have not worked).

--
HG

On Fri, Jan 14, 2011 at 6:43 PM, Keith Branton <ke...@branton.co.uk> wrote:
> 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 received this message because you are subscribed to the Google Groups
> "mongodb-user" group.
> To post to this group, send email to mongodb-user@googlegroups.com.
> To unsubscribe from this group, send email to
> mongodb-user+unsubscribe@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/mongodb-user?hl=en.


 
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.