Grails controller search criteria with list - grails

I need to do a search based on various criteria.
if a name contains the specified string.
if the name contains the specified string and a string from a list.
if the name contains one of the strings from a list.
I have the following code but it doesn't work. How bad is this code?
def taskList = Object.createCriteria().list(params) {
if (params.query) {
ilike("name", "%${params.query}%")
}
if (params.nameList) {
params.nameList.split("&").each {
or {
ilike("name", "%${it}$%")
}
}
}
The result is empty for use cases 2 & 3. What am I doing wrong? How should I do it?
Cheers

I'd use in operator for 3. case
list{
or{
if( params.query ) ilike "name", "%${params.query}%"
if( params.nameList ) 'in' 'name', params.nameList.split("&")
}
}

def taskList = Object.createCriteria().list(params) {
def names = []
if(params.nameList){
names = nameList.split("&")
}
or{
if (params.query){ilike("name", "%${params.query}%")}
and{
if (params.query){ilike("name", "%${params.query}%")}
if(names){'in'('name', names)}
}
if (names) {
names.each {name->
or {
ilike("name", "%$name$%")
}
}
}
}
}
Untested, but can you try with above. I would rather go with an HQL to achieve what you needed.

Related

Gorm Criteria for "each in" / "none in"

I have to write some queries to implement a search in a complex data model. I want to use the Criteria DSL of Gorm to solve that.
For simple queries like the examples in the Gorm or Grails Documentation it's no problem, but I don't know, how to implement more complicated queries like
"each in", "none in" or "only one of x is in". I hope someone can give me a hint.
Grails Domain Classes:
class Content {
Integer contentNumber
static hasMany = [titles : Title]
}
class Title {
String title
Titletype titletype
}
class Titletype {
String name
}
Method with Criteria:
def filter(GrailsParameterMap args) {
//To ensure that the ids of titletypes to query are always given as Long[]
Long[] argsTitletype = [args.title.titletype.value].flatten() as Long[]
def query = new DetachedCriteria(Content).build {}
// Every Content, which has a Title with Titletype in argsTitletype
query = query.build {
titles {
'in'('titletype.id', argsTitletype)
}
}
return query.list()
}
The return of the query above has the expected result: All Content, which has a Titletype in argsTitletype
But how to query "Content, which has all the Titletypes in argsTitletype"?
I tried for example:
query = query.build {
titles {
and {
argsTitletype.each { tt ->
eq('titletype.id', tt)
}
}
}
or
query = query.build {
and {
argsTitletype.each { tt ->
titles {
eq('titletype.id', tt)
}
}
}
Where is my misstake? Have I to use Subqueries?
For your all-in Try the following out:
query = query.build {
titles {
titletype {
argsTitletype.each { tt ->
eq 'id', tt
}
}
}
}
you don't need ands here, as those are applied by default.

Grails Criteria multiple hasMany intersection

I've been trying to query with multiple hasMany objects, such as:
def product = Product.createCriteria().list {
createAlias("productAttributeValues", "pav")
and {
if (session.filters?.filter_instore) {
and {
eq("pav.attribute", Attribute.findByCode("instore"))
eq("pav.valueDe", session.filters?.filter_instore?.toString())
}
}
if (session.filters?.filter_promo) {
and {
eq("pav.attribute", Attribute.findByCode("promo"))
eq("pav.valueDe", "1")
}
}
}
}
This doesn't seem to work, since I never get a result set, although I have test data that would match. It seems that the problem is that I'm querying twice with the same objects.
One possible solution would be to query the productAttributeValues seperately and then intersect with a "in"("myPavs", pavs) - but this seems to be inefficient to me.
Any thoughts?
Thanks.
I would re-build your query so:
def products = Product.withCriteria{
productAttributeValues{
or{
if (session.filters?.filter_instore) {
and {
eq("attribute", Attribute.findByCode("instore"))
eq("valueDe", session.filters?.filter_instore?.toString())
}
}
if (session.filters?.filter_promo) {
and {
eq("attribute", Attribute.findByCode("promo"))
eq("valueDe", "1")
}
}
}
}
}

Search and get all parents that contains a child with value

class Client {
String name
static hasMany = [courses:Course]
}
class Course {
String name
static belongsTo = [client:Client]
}
I have this and I want to get all Clients that has a Course with name = "blabla"
I was trying to do : Clients.findWhere(Course.any { course -> course.name = "math" })
You can do this with criteria:
Client.withCriteria {
courses {
eq('name', 'math')
}
}
I believe that the following where query is equivalent to the above criteria:
Client.where { courses.name == 'math' }
or you may find you need another closure:
Client.where {
courses {
name == 'math'
}
}
but I rarely use where queries myself so I'm not 100% sure of that.
There are probably a lot of different syntactical expressions to achieve the same thing. I can say definitively that this works in my project though.
def ls = Client.list {
courses {
eq('name','math')
}
}

GORM Criteria Query: Finding Children with specific properties

Have the following Domain modal:
class TransactionHeader {
static hasMany = [details: TransactionDetail]
}
class TransactionDetail {
static belongsTo = [header: TransactionHeader]
Product product
}
I'm trying to write a criteria query that will return all the TransactionHeader rows that contain TransactionDetails with 2 different Products. This is what I have so far and it isn't doing exactly what I'm after:
def list = TransactionHeader.withCriteria {
details {
and {
eq("product", product1)
eq("product", product2)
}
}
}
What's happening is it is return rows that contain at least 1 detail with 1 of the products. I need rows that have 2 details, each with one of the products.
Feels like you want to move details out of that, so actually
def list = TransactionHeader.withCriteria {
and {
details {
eq("product", product1)
}
details {
eq("product", product2)
}
}
}
Not sure how hibernate / gorm will deal this, though.
Have you tried using the "in" statement in your criteria dsl?
def list = TransactionHeader.withCriteria {
and {
details {
'in'("product", [product1, product2])
}
}
}

I am facing a problem with projections in createCriteria

I am facing a problem to get the required result from this closure
def authors{
results = Message.createCriteria().list {
projections {
author{
groupProperty('id', 'authorId') // 2nd param is alias
property('username', 'username')
}
}
and{
...
...
}
}
[authors:results]
}
I want to show this list on my gsp page
and wants to access the values using aliases
(while above criteria is returning a list of arrays)
Use resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP).
import org.hibernate.criterion.CriteriaSpecification
Message.createCriteria().list {
resultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP)
projections {
author{
groupProperty('id', 'authorId')
property('username', 'username')
}
}
}
All projections must have aliases. Otherwise the resulting map will contain nulls.
You can try this
def authors{
results = Message.createCriteria().list {
projections {
author{
groupProperty('id')
property('username')
}
}
and{
...
...
}
}
List authors = results.collect{record -> [authorId : record[0], username:record[1]}
[authors:authors] }

Resources