How can I get something like this MYSQL query with createCriteria in grails?
SELECT *
FROM engine4_user_fields_values
WHERE field_id = 31 OR field_id = 24
GROUP BY item_id;
It works fine if I use something like this:
def items = items_c.list{
'in'('fieldId',field_ids)
projections{
groupProperty("itemId")
}
}
But I need to define order, max and sort field like this:
def items = items_c.list(max:5, sort:"itemId", order:"desc"){
'in'('fieldId',field_ids)
projections{
groupProperty("itemId")
}
}
But this gets me different rows with the same 'item_id'
What can I do?
How about listDistinct{} ?
http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.4.2 Criteria
Use the projection agains the first result,
lists= items.createCriteria().list(){
projections {
order ("ItemId")
}
}
or executeQuery("your Query Here"); with distnict
Related
Is there a way that I can get a list of distinct Order objects (based on customerName) with projections (selected fields only)?
Assuming only the id would be different, I want to fetch orders having unique customerName. Is it possible using projections or any other way?
My code is:
def criteria = Order.createCriteria()
def orders = criteria.list() {
and {
eq("showAddress", true)
like("customerName", "%abcdPqrs%")
}
projections {
distinct("customerName")
property("deliveryAddress")
property("billingAddress")
property("")
}
}
return orders
The above code fetches duplicate (customerName) records from Order, how can I fix this?
If you will see the SQL query generated by GORM, you will find that the distinct will apply on a complete row instead of the customerName. You can enable the logs by putting
logSql = true
in datasource.groovy.
You can try this
def criteria = Order.createCriteria()
def orders = criteria.list() {
and {
eq("showAddress", true)
like("customerName", "%abcdPqrs%")
}
projections {
groupProperty("customerName")
property("deliveryAddress")
property("billingAddress")
property("")
}
}
New to groovy, grails.
I have the following query where I want to match a few paramater exactly to as passed(eq), but for one, which I want to using a 'like'
if (params.ret_code) {
ret_cod = params.ret_code+"%"
}
def srchresults = DmnObj.where {
if (params.doc_num) { doc_num == params.doc_num.trim() } //works as expected
//How do I do this????
if (params.retn_code) { retn_code like ret_cod }
}
Tried this, but in-vain.
how do I set retn_code with a like?
Thank you!
This is how you can do this
// case sensitive like
def result = Domain.where {
fieldName ==~ "value"
}
// case insensitive like
def result = Domain.where {
fieldName =~ "value"
}
Remember to prefix, suffix or both the value with %. For more about where queries https://grails.github.io/grails-doc/latest/guide/GORM.html#whereQueries
You can do like this:
var feel []DB.Feelings
db.Where("column_name LIKE ?", "%"+yourText+"%").Limit(your_limit).Offset(your_offset).Find(&feel)
column_name is your column name
Limit and Offset are not required
You can do like this:
def result = DomainClass.where{
like('fieldName', '%'+myVariable+'%')
}
I suggest you have a look at the Grails documentation (section Domain Class Usage): you will find several interesting ways to filter your domain class objects as for example HQL queries or findAllBy* dynamic methods.
How do I write a createCriteria in grails which pull only few columns from the table instead of all columns?
I have a table called Ads. I want to retrieve only columns "Title" , "Price" and "Photo".
def c = Classified.createCriteria()
def records = c.list {
eq('publish_date', '2014-06-06')
}
maxResults(8)
}
Above query retrieves all the records. How to restrict to only few columns?
You can use projections to achieve this - at the simplest
projections {
property('title')
property('price')
property('photo')
}
would cause c.list to return a list of three-element lists, where records[n][0] is the title, records[n][1] is the price etc. If you want to be able to access the properties by name rather than by number then you need to assign aliases and use a result transformer
import org.hibernate.transform.AliasToEntityMapResultTransformer
def c = Classified.createCriteria()
def records = c.list {
eq('publish_date', '2014-06-06')
maxResults(8)
projections {
// first param is the property name, second is the alias definition -
// typically you'd leave them the same but here I make them different
// for demonstration purposes
property('title', 'ttl')
property('price', 'cost')
property('photo', 'picture')
}
resultTransformer(AliasToEntityMapResultTransformer.INSTANCE)
}
Now records will be a list of maps rather than a list of lists, and you can access the projected properties by alias name - records[n].ttl, records[n].cost, etc.
Try this:
def records = Classified.withCriteria {
eq('publish_date', '2014-06-06')
projections {
property('title')
property('price')
property('photo')
}
maxResults(8)
}
Is there a way that, i can get list of distinct User objects(based on username). And still get result as a List of User Objects rather than, List of username's.
My code is
def criteria = User.createCriteria()
def users = criteria.list() {
projections {
distinct("username")
}
setResultTransformer(CriteriaSpecification.ROOT_ENTITY)
}
return users
Currently am getting List of the usernames, not User.
Ya projection is like filtering and selecting by username you should change it to
def criteria = User.createCriteria()
def users = criteria.listDistinct() {
projections {
groupProperty("username")
}
}
return users
JOB DONE!
One of these should work - I haven't tested any of them, I leave that up to you :)
User.list().unique()
User.list().unique() with the equals() method on the User domain class overridden to compare objects using the username
User.list().unique { it.username } (might need toArray() after list())
def criteria = User.createCriteria()
def users = criteria.list() {
projections {
distinct("username")
}
setResultTransformer(CriteriaSpecification.ROOT_ENTITY)
}
Just replace setResultTransformer(CriteriaSpecification.ROOT_ENTITY) with resultTransformer(ALIAS_TO_ENTITY_MAP). You will get a list of string as a result
otherwise just replace .list with .listDistinct and use do not need distinct("username"), just can be property("username");
Usually people get problems with pagination. not results. If you already had something like:
User.createCriteria().list([max:params.max,offset:params.offset],{
createAlias("others", "others", CriteriaSpecification.LEFT_JOIN);
ilike("others.firstName", "%${query}%");
});
It could result in row duplicates. Because .listDistinct() does not support pagination, just add
resultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
So query will look like this:
User.createCriteria().list([max:params.max,offset:params.offset],{
resultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
createAlias("others", "others", CriteriaSpecification.LEFT_JOIN);
ilike("others.firstName", "%${query}%");
});
Where ever you got a collection (list, array, ...) (I don't know if work with any type of collection, but work in all that i could test). Use unique{ it.property }:
Example:
def users = []
for (def room in rooms) {
users.addAll(room.users)
}
return users.unique{ it.id }
Using where query(Detached criteria):
def userListQuery = User.where{
// Your search criteria
}
def userList = userListQuery.list().unique{ it.username }
it should result one query for distinct results.
This will get you the distinct user object based on userName
def userInstance = User.list().unique{ it.user_name}
Is this possible to convert in createCriteria()?
SELECT * FROM node WHERE (node.type = 'act' AND nid NOT IN (SELECT nid FROM snbr_act_community)) LIMIT 10
I know there's a 'in' operator and here's what I have so far:
def c = VolunteerOpportunity.createCriteria()
def matchingActs = c.list {
node {
eq('type', 'act')
}
maxResults(10)
}
Just want to see if this is possible. Otherwise, I guess this is possible in HQL right?
thanks Sammyrulez for the code. got an idea from that. tested it but it didn't work. i fixed it and here's the final working code:
def ids = [14400 as long, 14401 as long]
def c = VolunteerOpportunity.createCriteria()
def matchingActs = c.list {
node {
eq('type', 'act')
not { 'in'(ids) }
}
maxResults(10)
}
now i know how to use 'not' operator. thanks a lot!
not tried it myself but looking at the Grails doc and hibernate api you create nodes on this builder map with the static methods found in the Restrictions class of the Hibernate Criteria API 1. So something like
def c = VolunteerOpportunity.createCriteria()
def matchingActs = c.list {
node {
not(in('propertyName', ['val1','val2']))
}
maxResults(10)
}
Since you chain the in method (that returns a Criterion) with the not method (that takes a Criterion as argument and returns a negated version)
this is the solution :
def resultat=EnteteImputationBudgetaire.createCriteria().get{
between("dateDebutPeriode", dateDebut, dateFin)
and{ eq 'natureImputationBudgetaire','FONCTIONNEMENT' }
maxResults(1)
}
def resultat2=ParametragePlanBudgetaire.createCriteria().list() {
like('composantBudgetaire','6%')
if(resultat?.details) {
not {
'in'('composantBudgetaire',resultat?.details?.imputationBudgetaire)
}
}
}
According to Grails documentation about creating criteria here, you can use something like this:
not {'in'("age",[18..65])}
In this example, you have a property named "age" and you want to get rows that are NOT between 18 and 65. Of course, the [18..65] part can be substituted with any list of values or range you need.
Just remembering: in this case you don't have to use parenthesis and you can use inList, for example:
not { inList 'age',[18..65] }