FIRST QUESTION:
I have the following domain class in my app:
class Test {
...
String name
static hasMany = [evaluationsTest: Evaluation]
...
}
class Evaluation {
...
String testName
Float testScore
...
}
I need to obtain the number of evaluations between a range of scores (example: evaluations with scores between 7-8 ) of a specific test.
With a criteria I can obtain it correctly:
def criteria = Test.createCriteria()
def example = criteria.list {
eq 'name', params.test
evaluationsTest {
ge("testScore", 7 as Float)
lt("testScore", 8 as Float)
}
projections {
count()
}
}
But I want to know a async search and for this reason I want to use a DetachedCriteria but it does not work.
DetachedCriteria detached = Test.where {
name == params.test
evaluationsTest {
ge("testScore", 7 as Float)
lt("testScore", 8 as Float)
}
.projections {
count()
}
} as DetachedCriteria
def result = detached.async.list()
EDITED: Solved with withCriteria() method.
SECOND QUESTION:
Besides, I have another doubt. I need to parallelize this code. How can I do the each fragment? I used to task but sometimes works and other times appears the error: Array Index Out of Bounds Exception
// Rows
def rows = []
def addRow = { name, value ->
rows << [c: [[v: name], [v: value]]]
}
// Add departments
departments.each { department ->
addRow(department.name, department.users.size())
}
def UDData = [cols: cols, rows: rows]
With this code (tasks), I obtain: Array index out of bounds
List queriesToExecute = []
// Add departments - Asynchronous/Multi-thread
departments.each { department ->
def departmentTask = tasks {
rows << [c: [[v: department.name], [v:department.users.size()]]]
}
queriesToExecute << departmentTask
}
waitAll(queriesToExecute)
One reason your query may be failing is because you're creating a where query instead of a criteria query, and where queries do not support projections very well. They work... but only sometimes. And you'd have to define them outside of the query, like so:
DetachedCriteria detached = Test.where {
name == params.test
evaluationsTest {
ge("testScore", 7 as Float)
lt("testScore", 8 as Float)
}
}.projections {
count()
} as DetachedCriteria
But, you don't actually need a DetachedCriteria
to perform an async query. You can do it with a criteria query:
def promise = Test.async.withCriteria() {
eq 'name', params.test
evaluationsTest {
ge("testScore", 7 as Float)
lt("testScore", 8 as Float)
}
projections {
count()
}
}
def result = promise.get()
Here's an example of using GPars to collect the department data concurrently, without side-effects:
import static groovyx.gpars.GParsPool.withPool
def rows
withPool {
rows = departments.collectParallel { department ->
[c: [[v: department.name], [v:department.users.size()]]]
}
}
def UDData = [cols: cols, rows: rows]
This is using fork-join. So the Closure
is executed concurrently, and then the results are joined together.