javamongodbgroovygmongo

doEval() With Multiline String Argument


Using Groovy 2.3.6, GMongo 1.2, Java 1.8, MongoDB 3.0.0...

I'm trying to use doEval() to get a count of documents in a collection. (For various reasons I want to use doEval() rather than count()). Invoking doEval() with a single line string argument returns retval with a double value of 1.0 and ok with a double value of 1.0 which is what I expect:

def str = "db.configurations.count({name: 'Mike'})"
database.doEval(str)

If the argument is on multiple lines retval that is returned is null (ok is 1.0).

def str = "db.configurations.count({\nname: 'Mike'\n})"
database.doEval(str)

I expect doEval to return a retval of 1.0 not null, like in the first example. Is this a bug or is my expectation incorrect? Should doEval() support a multiline string argument?


Solution

  • From doEval() javadoc:

    Evaluates JavaScript functions on the database server. This is useful if you need to touch a lot of data lightly, in which case network transfer could be a bottleneck.

    Parameters:

    code - String representation of JavaScript function

    args - arguments to pass to the JavaScript function

    So you are not passing a javascript function to doEvalmethod. Anyway, the result you are getting is consistent with the result you can get invoking directly the mongo shell:

    > db.eval("db.configurations.count({name: 'Mike'})");
    1
    > db.eval("db.configurations.count({\nname: 'Mike'\n})");
    null
    

    (I did not dig deeper on mongo shell javascript internals... :-)

    Passing a javascript function you can get the result you want:

    println db.configurations.count([name: 'Mike'])
    
    def str = '''function(name) {
        return db.configurations.count({
            name: name
        });
    }'''
    println db.doEval(str, 'Mike')
    

    The above yields:

    1
    [serverUsed:/127.0.0.1:27017, retval:1.0, ok:1.0]