Skip to content

Instantly share code, notes, and snippets.

@jwill
Created March 11, 2010 06:11
Show Gist options
  • Save jwill/328892 to your computer and use it in GitHub Desktop.
Save jwill/328892 to your computer and use it in GitHub Desktop.
import com.mongodb.*
public class MongoUtils {
public static void decorateCollectionClass() {
//meta programming convenience methods courtesy of jareed
DBCollection.metaClass {
findAll << { LinkedHashMap query -> delegate.find(query as BasicDBObject) }
findAll << { LinkedHashMap query, LinkedHashMap filter -> delegate.find(query as BasicDBObject, filter as BasicDBObject) }
find << { LinkedHashMap query -> delegate.find(query as BasicDBObject).find {true} }
find << { LinkedHashMap query, LinkedHashMap filter -> delegate.find(query as BasicDBObject, filter as BasicDBObject).find {true} }
insert << { LinkedHashMap doc -> delegate.insert(doc as BasicDBObject) }
update << { BasicDBObject doc, LinkedHashMap op -> delegate.update(doc, op as BasicDBObject) }
}
}
public static void decorateCollection(DBCollection collection) {
collection.metaClass.methodMissing = {String methodName, args ->
def operators = [
"LessThan":'$lt',
"LessThanEquals":'$lte',
"GreaterThan":'$gt',
"GreaterThanEquals":'$gte',
"InList":'$in',
"NotInList":'$nin',
"Exists":'$exists',
"AllInList":'$all',
"NotEqual":'$ne',
"ArraySize":'$size',
//modifiers
"WithLimit":'$limit',
"WithSkip":'$skip'
]
def matcher = (methodName =~ /^(find)(\w+)$/)
if (matcher.matches()) {
def temp = matcher.group(2) - "By"
def list = temp.split("And")
def map = [:]
for (item in list) {
def property
def operator
def hasOperator = false
for (op in operators.keySet()) {
if (item.endsWith(op)) {
operator = operators[op]
property = item.replace(op,"").replace("_",".").toLowerCase()
if (operator.equals('$limit') || operator.equals('$skip')) {
if (!property.equals(""))
map.put(property, '$eq')
map.put(operator, "")
} else map.put(property.toLowerCase(), operator)
hasOperator = true
}
}
if (!hasOperator) {
def name = item.replace('_','.')
map.put(name.toLowerCase(), '$eq')
}
}
// create function
def function = { arguments ->
def attrs = map
def query
def builder = BasicDBObjectBuilder.start()
builder.start()
map.entrySet().eachWithIndex { entry, i ->
if (!entry.value.equals("")) {
if (entry.value.equals('$eq'))
builder.append(entry.key, arguments[i])
else builder.append(entry.key, [entry.value, arguments[i]] as BasicDBObject)
}
}
query = builder.get()
def cursor = collection.find(query)
// skip and limit
//TODO
return cursor
}
collection.metaClass.(methodName.toString()) = function
function(args)
}
}
}
}
def m = new Mongo()
DB db = m.getDB( "mydb" )
def coll = db.getCollection('posts')
coll.drop()
MongoUtils.decorateCollectionClass() // decorate with meta methods
coll.insert([author:'James', date:new Date().getTime()])
coll.insert([author:'Paul', date:(new Date()-1).getTime()])
coll.insert([author:'John', date:(new Date()-2).getTime()])
coll.insert([author:'Kate', date:(new Date()-3).getTime()])
println "Meta-find:"+ coll.find(['author':'James'])
MongoUtils.decorateCollection(coll)
def d = new Date() -1
println d.getTime()
def cursor = coll.findByDateLessThan( d.getTime())
while(cursor.hasNext()) {
println(cursor.next());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment