Based on some emails I received last days I will show some features of GMongo that not everyone is aware.
Regex based search
In the mongo official Java driver you can do searches using Regular Expression. To do that you just need to pass a java.util.regex.Pattern instance as the search term. In Groovy there is a shortcut to create a Pattern: ~/regex/.
For example:
def pattern = ~/mypattern/
assert pattern.class.is(java.util.regex.Pattern)
Here is a small script demonstrating the usage of regex search:
@Grab('com.gmongo:gmongo:0.6')
import com.gmongo.GMongo
def gmongo = new GMongo('localhost:27017')
def db = gmongo.getDB('tips')
db.so.drop()
db.so << [name: 'Windows XP']
db.so << [name: 'Windows 7']
db.so << [name: 'Windows Vista']
db.so << [name: 'Mac OS X v10.3 "Panther"']
db.so << [name: 'Mac OS X v10.4 "Tiger"']
db.so << [name: 'Mac OS X v10.5 "Leopard"']
db.so << [name: 'Mac OS X v10.6 "Snow Leopard"']
db.so << [name: 'Mac OS X v10.7 "Lion"']
// Mac OS Only
println "\nMac Os Only\n"
db.so.find([name: ~/^Mac/]).each { so ->
println so
}
// Print:
// Mac OS Leopard, Snow Leopard
println "\nMac OS Leopard, Snow Leopard\n"
db.so.find([name: ~/Leopard/]).each { so ->
println so
}
Persisting your POGO
There is an easy way to persist your POGO using GMongo. Suppose we have the class:
class Person {
def name
def age
}
In Groovy we can get all properties from a class using the properties property, for example:
def person = new Person(name: 'Paulo', age: 25)
println person.properties
This code outputs:
[
class:class Person,
age:25,
metaClass:org.codehaus.groovy.runtime.HandleMetaClass@450a10011],
name:Paulo
]
As you can see, not every property means something to us. We doesn’t want to store class and metaClass in our storage, because it isn’t part of the domain. So, we need to ignore them:
println person.properties.findAll { !['class', 'metaClass'].contains(it.key) }
Now, all we need to do is persist this Map in MongoDB. Here is a complete example:
@Grab('com.gmongo:gmongo:0.6')
import com.gmongo.GMongo
class Person {
def name
def age
}
def gmongo = new GMongo('localhost:27017')
def db = gmongo.getDB('example')
def person = new Person(name: 'Paulo', age: 25)
db.persons.drop()
db.persons << person.properties.findAll { !['class', 'metaClass'].contains(it.key) }
def personFromMongo = db.persons.findOne()
assert 'Paulo' == personFromMongo.name
assert 25 == personFromMongo.age
BasicDBObject to POGO conversion
The class com.mongodb.BasicDBObjects extends java.util.LinkedHashMap so it’s easy to convert it to POGO, thankfully to Groovy array notation constructor call. Don’t worry, I will explain. Suppose we have the class:
class Person {
def name
def age
}
The two statements bellow are equivalent:
Person mike = new Person(name: 'Mike', age: 23)
Person john = [name: 'John', age: 36]
To this work you need to use typed variable. If you use untyped variable definition Groovy can’t infer what constructor to call.
So, taking advantage of this cool Groovy feature you can do things like this:
@Grab('com.gmongo:gmongo:0.6')
import com.gmongo.GMongo
class Person {
def name
def age
def whoIAm() {
"Hello, I'm $name and I have $age year."
}
}
def gmongo = new GMongo('localhost:27017')
def db = gmongo.getDB('example')
def person = new Person(name: 'Paulo', age: 25)
db.persons.drop()
db.persons << person.properties.findAll { !['class', 'metaClass'].contains(it.key) }
Person personFromMongo = db.persons.findOne().findAll { it.key != '_id' }
assert "Hello, I'm Paulo and I have 25 year." == personFromMongo.whoIAm()
As you can see, we need to remove the _id property from the Map before instantiate the class Person, that is because Person hasn’t this property. Another alternative is add the _id property to the Person class.
Any feedback is appreciated.
Share and Enjoy