Paulo Poiati | Blog

@SuppressWarnings(“useless”)

  • Home
  • About
  • Github
  • GMongo
  • SandBox
Twitter Facebook RSS

GMongo 0.5 Released

Posted on 20/06/2010 by Paulo Poiati
24 CommentsLeave a comment

UPDATE: GMongo is in constantly development, for more details check https://github.com/poiati/gmongo.

GMongo is an alternative to de default Java driver for Mongodb. It’s use an easy and less verbose syntax, the grammar is very close to the official mongo shell cliente (javascript).

It’s just a wrapper around the Java driver. So, every single method of the the official driver is available here too.

The main class is the com.gmongo.GMongo. It has the same API of the com.mongodb.Mongo but it’s not a subclass. Instead, the methods calls are delegated. Despite GMongo, all other classes are the same from the Java driver.

To be more practical, here are some examples:

// To download GMongo on the fly and put it at classpath
@Grab(group='com.gmongo', module='gmongo', version='0.5.1')
import com.gmongo.GMongo
// Instantiate a com.gmongo.GMongo object instead of com.mongodb.Mongo
// The same constructors and methods are available here
def mongo = new GMongo("127.0.0.1", 27017)

// Get a db reference in the old fashion way
def db = mongo.getDB("gmongo")

// Collections can be accessed as a db property (like the javascript API)
assert db.myCollection instanceof com.mongodb.DBCollection
// They also can be accessed with array notation
assert db['my.collection'] instanceof com.mongodb.DBCollection

// Insert a document
db.languages.insert([name: 'Groovy'])
// A less verbose way to do it
db.languages.insert(name: 'Ruby')
// Yet another way
db.languages << [name: 'Python']

// Insert a list of documents
db.languages << [[name: 'Javascript', type: 'prototyped'], [name: 'Ioke', type: 'prototyped']]

def statics = ['Java', 'C', 'VB']

statics.each {
	db.languages << [name: it, type: 'static']
}

// Finding the first document
def lang = db.languages.findOne()
assert lang.name == 'Groovy'
// Set a new property
lang.site = 'http://groovy.codehaus.org/'
// Save the new version
db.languages.save lang

assert db.languages.findOne(name: 'Groovy').site == 'http://groovy.codehaus.org/'

// Counting the number of documents in the collection
assert db.languages.find(type: 'static').count() == 3

// Another way to count
assert db.languages.count(type: 'prototyped') == 2

// Updating a document using the '$set' operator
db.languages.update([name: 'Python'], [$set: [paradigms: ['object-oriented', 'functional', 'imperative']]])

assert 3 == db.languages.findOne(name: 'Python').paradigms.size()

// Using upsert
db.languages.update([name: 'Haskel'], [$set: [paradigms: ['functional']]], true)

assert db.languages.findOne(name: 'Haskel')

// Removing some documents
db.languages.remove(type: 'prototyped')
assert 0 == db.languages.count(type: 'prototyped')

// Removing all documents
db.languages.remove([:])
assert 0 == db.languages.count()

// To ensure complete consistency in a session use DB#inRequest
// It is analogous to user DB#requestStarted and DB#requestDone
db.inRequest {
	db.languages.insert(name: 'Objective-C')
	assert 1 == db.languages.count(name: 'Objective-C')
}

And a simple MapReduce:

@Grab(group='com.gmongo', module='gmongo', version='0.5.1')
import com.gmongo.GMongo

// There is some bug using the [Random] word into codesnipt plugin
import java.util.Random as Rand

def mongo = new GMongo("127.0.0.1", 27017)
def db = mongo.getDB("gmongo")

def words = ['foo', 'bar', 'baz']
def rand  = new Rand()		

1000.times {
	db.words << [word: words[rand.nextInt(3)]]
}

assert db.words.count() == 1000

def result = db.words.mapReduce(
	"""
	function map() {
		emit(this.word, {count: 1})
	}
	""",
	"""
	function reduce(key, values) {
		var count = 0
		for (var i = 0; i < values.length; i++)
			count += values[i].count
		return {count: count}
	}
	""",
	"mrresult",
	[:] // No Query
)

assert db.mrresult.count() == 3
assert db.mrresult.find()*.value*.count.sum() == 1000

It’s a stable version and still a work in progress. The only dependency is the mongo Java driver version 2.0 and, of course, Groovy. It’s tested under Groovy 1.7.2 and 1.7.3. It’s opensource and hosted at http://github.com/poiati/gmongo.

The binaries can be found at Maven Central.
Click here for more details.

Any bug, suggestion or issue, please, contact me.

Share and Enjoy

Categories: GMongo, Groovy, NoSQL | Tags: groovy, java, mongodb, nosql, opensource
Notice: This work is licensed under a BY-NC-SA. Permalink: GMongo 0.5 Released
GMongo available at Maven Central
Forwarding Objective-C Messages

24 Responses to “GMongo 0.5 Released”

  1. Steve says:
    15/10/2011 at 16:52

    Hi, I like GMongo, but I think it suffers the same problem as the default driver with respect to the need to call close() no database objects. For a long running process, if there are instances created with new that are not closed, unused threads can accumulate until the JVM is no longer able to allocate new ones and the app freezes. Instead of using new, have you considered a more Groovy like syntax using closures? E.g.


    GMongo.collection(collection_name, db) { collection_ref ->
    collection_ref.findAll { println it }
    ...
    }

    Reply
    • Paulo Poiati says:
      15/10/2011 at 17:43

      Hello Steve,

      I’m not sure about what u mean. The only close I found in the Java API is the com.mongodb.Mongo#close, and this one close all open connections from the pool.

      The problem is the JVM overflowing threads limit or the MongoDB connection pool being empty of usable connections? Can u show me some code u want to achieve in the Java driver?

      Reply
      • Steve says:
        17/10/2011 at 17:56

        typo: *call close() on database objects.*

        Right that is the close that needs to be called. If you have a process that uses new instances of (G)Mongo that are not closed you will eventually run out of threads in the JVM if new is called repeatedly. Of course, the simple answer is don’t create new instances. On that note, I would refine the syntax I suggested in order to avoid passing in a new instance:


        def collection(name, location='localhost', port='27017', closure) { ...}
        ...
        collection('my_collection') { coll -> ...}

        All the responsibility of maintaining mongo instances can be handled by the class containing the collection method which can ensure only a single connection pool per mongodb server instance exists.

        Alternatively, a closure taking the db instance could be used

        def database( location='localhost', port='27017', closure) { ... }

        database { db ->
        db.my_collection...
        }

        Since the user never gets to call new, resource leaks can be prevented in either scenario.

        Reply
        • Steve says:
          18/10/2011 at 01:18

          Prior post was missing name argument for database

          def database(name, location='localhost', port='27017', closure) { ... }
          ...
          database("gmongo") { db ->
          def words = ['foo', 'bar', 'baz']
          def rand = new Rand()
          1000.times { db.words << [word: words[rand.nextInt(3)]] }
          assert db.words.count() == 1000
          }

          Reply
          • Paulo Poiati says:
            19/10/2011 at 21:24

            Hello Steve,

            I see your point. But, I don’t like the idea of protect the programmer from himself. Only make sense to had more Mongo instances if you have more than one server to connect, and the developer should be aware of this.

            I think the Mongo#close must be used carefully, because of that, I think this should be done explicitly.

            Thanks.

            []‘s

            Reply
  2. Dennis van den Berg says:
    15/08/2011 at 09:47

    I seem to have the same problem as Tony;
    groovy.lang.MissingPropertyException: No such property: myCollection for class: com.mongodb.DBApiLayer

    However, I only got this problem when I put gmongo-0.5.1.jar and mongo-java-driver-2.0rc4.jar on the classpath myself (and removing the line with @grab)

    Any idea’s how this might result in such a problem?

    Thanks, Dennis

    Reply
    • Paulo Poiati says:
      15/08/2011 at 13:27

      Hello Denis,

      Which version of Groovy are you using?

      You really need version 0.5.1? Currently we are in version 0.8:

      http://mvnrepository.com/artifact/com.gmongo/gmongo

      Reply
      • Dennis van den Berg says:
        15/08/2011 at 16:14

        Hi Paulo,

        When using version 0.8 I got the same problem. I am running from eclipse (helios) with groovy 1.7.5. Note that I only have this problem when not using @grab, but adjusting the classpath in my project settings instead.

        Dennis

        Reply
        • Paulo Poiati says:
          16/08/2011 at 01:30

          I downloaded Eclipse Helios, installed the Groovy Plugin, added gmongo and mongo-java-driver dependencies… And everything worked just fine.

          Are you sure the classpath is configured correctly?

          Tks!

          Reply
  3. mongo DB | Ben's Computer Graphics Blog says:
    25/07/2011 at 07:47

    [...] ^ GMongo [...]

    Reply
  4. sd says:
    22/07/2011 at 04:57

    Hi,
    Is it possible to also provide a sort and limit in addition to the query for the mapReduce call? These are permitted options for MongoDB.

    db.runCommand(
    { mapreduce : ,
    map : ,
    reduce :
    [, query : ]
    [, sort : ]
    [, limit : ]
    [, out : ]
    [, keeptemp: ]
    [, finalize : ]
    [, scope : ]
    [, verbose : true]
    }
    );

    Thanks

    Reply
  5. Alessandro says:
    24/05/2011 at 15:23

    Nice article and nice library!!! Very simple and useful!
    One question: is it possible to update more than a record in a single statement, like sql?

    thanks a lot!

    Reply
    • Paulo Poiati says:
      26/05/2011 at 23:00

      Hello Alessandro. Tks!

      Answering:
      Yes, it’s possible. Using updateMulti:

      @Grab( 'com.gmongo:gmongo:0.8' )
      import com.gmongo.GMongo
      
      def gmongo = new GMongo( )
      def db = gmongo.getDB( 'test' )
      
      db.foo.drop( )
      
      db.foo.insert key: 1, value: 'foo'
      db.foo.insert key: 2, value: 'bar'
      db.foo.insert key: 1, value: 'baz'
      
      println "Before"
      
      db.foo.find( ).each { println it }
      
      db.foo.updateMulti( [ key: 1 ], [ $set: [ value: 'qux'] ] )
      
      println "\nAfter"
      
      db.foo.find( ).each { println it }
      
      Reply
  6. Kai says:
    20/01/2011 at 12:37

    Hi Paulo,

    Thank you for all your great help when I needed it the most. Your groovy plugin is really great. I wonder if you could be so kind and share some more query tricks, such as filtering, sorting and things that I forgot to mention here. :)

    I will put “Have a gmongo based GORM plugin for Grails that works!” on my X-mas wishlist.

    All the best,
    —Kai

    Reply
  7. Ewan Dawson says:
    15/07/2010 at 09:03

    Nice work Paulo, looking forward to checking this out!

    Reply
  8. Tony Requist says:
    07/07/2010 at 14:04

    The problem was clearly something on my end and not in your code, so I flailed until I figured it out — I was experimenting with Groovy in Eclipse, and the default Run Configuration it builds via one usage path is wrong. Sorry to clutter the blog :)

    Reply
    • Paulo Poiati says:
      07/07/2010 at 17:28

      No problem Tony! Any possible problem or suggestion are welcome.

      Reply
  9. GMongo available on Maven Central | Paulo Poiati | Blog says:
    03/07/2010 at 04:41

    [...] GMongo 0.5 Released [...]

    Reply
  10. Tony Requist says:
    02/07/2010 at 20:46

    I am having trouble getting this to work in a simple test, using Mongo 1.7.3 and mongo-2.0.jar
    It works fine from Java, but with this simple script I get an error. Getting the collection with db.getCollection(“things”) works, but with db.things it does not:

    import com.gmongo.GMongo
    GMongo mongo = new GMongo(“localhost”)
    db = mongo.getDB(“test”)

    def colls = db.getCollectionNames()
    colls.each { println “Collection: ” + it }

    def things1 = db.getCollection(“things”)
    println “things1 = ${things1}, class = ${things1.getClass().getName()}”

    def things2 = db.things
    println “things2 = ${things2}, class = ${things2.getClass().getName()}”

    Collection: foo
    Collection: system.indexes
    Collection: things
    things1 = things, class = com.mongodb.DBApiLayer$MyCollection
    Caught: groovy.lang.MissingPropertyException: No such property: things for class: com.mongodb.DBApiLayer
    at Stuff.run(Stuff.groovy:11)

    Reply
    • Paulo Poiati says:
      02/07/2010 at 23:02

      Hello Tony, did you mean Groovy 1.7.3 ?

      I executed your script here, and it works for me.

      @Grab("com.gmongo:gmongo:0.5")
      import com.gmongo.GMongo
      
      println System.properties['os.name']
      println System.properties['java.vm.name']
      println System.properties['java.version']
      println System.properties['java.class.path']
      
      println()
      
      GMongo mongo = new GMongo("localhost")
      db = mongo.getDB("test")
      
      def colls = db.getCollectionNames()
      colls.each { println "Collection: " + it }
      
      def things1 = db.getCollection("things")
      println "things1 = ${things1}, class = ${things1.getClass().getName()}"
      
      def things2 = db.things
      println "things2 = ${things2}, class = ${things2.getClass().getName()}"
      

      Output:

      Mac OS X
      Java HotSpot(TM) 64-Bit Server VM
      1.6.0_20
      /usr/local/langs/groovy/current/lib/groovy-1.7.3.jar

      Collection: foo
      Collection: system.indexes
      Collection: testBinary
      things1 = things, class = com.mongodb.DBApiLayer$MyCollection
      things2 = things, class = com.mongodb.DBApiLayer$MyCollection

      PS: gmongo-0.5 (from maven central) use mongo-java-driver-2.0RC4 as Dep., but it works with 2.0 as well.

      Can you give me more details plz.
      Tks.

      Reply
  11. Natividad Weist says:
    30/06/2010 at 08:58

    Thank you! That’s perfect….
    +1

    Reply
  12. Peter Balogh says:
    29/06/2010 at 18:42

    Thank you! That’s perfect….

    Reply
  13. Peter Balogh says:
    24/06/2010 at 15:18

    I love this! Good work.

    One question: can you provide an example of saving into nested collections? I.e., if inside of languages you had a “static” collection and a “dynamic” collection, how would you save into them?

    Thanks again!

    Reply
    • Paulo Poiati says:
      24/06/2010 at 18:16

      Mongodb doesn’t support nested collections, what you can do is create two collections, one for each language type:


      db[‘languages.static’].insert( ['C', 'Java'] )
      db[‘languages.dynamic’].insert( ['Groovy', 'Ruby'] )

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

*

*


question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

  • Recent Posts

    • A not well know and underestimated css property: box-sizing
    • jQuery Builder: Introduction
    • Installing VimRepress in MacVim (OSX Lion)
    • Easyhash: An easy interface to generate md5 and sha1 hash in hexadecimal format
    • Grails / GORM: Changing default id name and type from an entity
  • Categories

    • CSS
    • GMongo
    • GORM
    • Grails
    • Groovy
    • Java
    • Javascript
    • jQuery
    • NoSQL
    • Objective-c
    • OSX
    • Programming
    • Vim
  • Tags

    brew builder C css easyhash gmongo grails gorm groovy groovy html java javascript jquery mongodb nosql Objective-c opensource osx python vim web wordpress
  • Blogroll

    • Rodrigo Lazoti Blog
  • Links

    • Mac Developers
    • Siteapps
  • Recent Comments

    • Trying out VimRepress | Blind, Not Dumb on Installing VimRepress in MacVim (OSX Lion)
    • Paulo Poiati on Installing VimRepress in MacVim (OSX Lion)
    • Chris Patti on Installing VimRepress in MacVim (OSX Lion)
    • rohit on Groovy / GMongo tips and tricks
    • Paulo Poiati on GMongo 0.5 Released
© Paulo Poiati | Blog. Proudly Powered by WordPress | Nest Theme by YChong