I have a domain class named Keyword and I need to run a query to get all the duplicate keywords in the system, base on some criteria.
The query in MySQL is somethine like this:
select keywordid, md5, match_type, count(md5)
from keyword
where site_id = 'MLU'
and customer_id = 1075613440
group by md5
having count(md5) > 1;
Now I need to "translate" this query to Grails but the requirement from my boss is to aviod HQL.
Is it possible to do it?
For now all I have is this:
def dupKws = criteria.list {
eq('siteId', siteId)
eq('customerId', account.customerId)
projections {
groupProperty('md5')
groupProperty('matchType')
rowCount()
}
}
You can run this query in grails with:
import groovy.sql.Sql
def query = """ select keywordid, md5, match_type, count(md5)\
from keyword\
where site_id = 'MLU'\
and customer_id = 1075613440\
group by md5\
having count(md5) > 1 """
Sql sql = new Sql(datasource)
sql.execute(query)
Related
I am trying to implement the following SQL query in GORM:
select au.* from App_user au
inner join SEC_USER su on su.id=au.SEC_USER_ID
where
not su.id in (
select susr.SEC_USER_ID from SEC_USER_SEC_ROLE susr
inner join SEC_ROLE sr on susr.SEC_ROLE_ID=sr.id
where sr.authority like 'ROLE_INTERNAL%'
and susr.SEC_USER_ID=su.id
)
(get all the users who don't have a role matching the ROLE_INTERNAL.* pattern)
I have a working query, using GORM:
AppUser.createCriteria().list(args, {
secUser {
// def su = SecUser
notIn "id", SecUserSecRole.where {
secRole {
authority ==~ 'ROLE_INTERNAL%'
}
/*
secUser {
id == su.id
}
*/
}.property("secUser.id")
}
})
But this query is inefficient, due to the fact that I don't know how to add the SQL where clause and susr.SEC_USER_ID=su.id in the criteria DSL.
I have seen here and there mentions of using the commented code, to create an alias of the SecUser (su) at the root level, and then using it in the subquery, but I ger the following exception when trying to uncomment my additional statements:
No such property: id for class: SecUser
I feel that i am really close, but I can't figure it out by looking at the documentation. It is rather sparse in this aspect.
As the documentation shows under "7.4.8. More Advanced Subqueries in GORM",
DetachedCriteria<AppUser> query = AppUser.where {
secUser {
def u = SecUser
notIn "id", SecUserSecRole.where {
def u2 = secUser
secRole.authority ==~ 'ROLE_INTERNAL%' && u2.id == u.id
}.property("secUser.id")
}
}
query.list(args)
Getting the last record is trivial in SQL, e.g. (for MySQL)
class ExchangeRate {
Currency from
Currency to
BigDecimal rate // e.g. 10
Date dateCreated
}
class Currency {
String iso
etc..
}
SQL to get the latest is trivial:
Select max(id), rate
from exchange_rate
where from_id = 1
and to_id = 3
or
select rate
from exchange_rate
where from_id = 2
order by id desc
limit 1
The question is, how does one do this efficiently in Grails? I only want a single result.
This obviously wont work:
def query = ExchangeRate.where {
from == from && to == to && id == max(id)
}
ExchangeRate exchangeRate = query.find()
There have been several posts on this, but not with an actual answer which I could figure out how to apply (I am a SQL guy, and don't know hibernate language and would prefer a solution which did not involve it if there was one)
If there was an easy way to run SQL directly without having to hand manage result sets that would work (as we will never use another DB other than MySQL)
I am sure it could be done with sort and limit, but a) haven't found an example I could copy, and b) would assume this be inefficient, because it appears that the sorting and limiting is done in code, not SQL?
This example is in the documentation:
Book.findAll("from Book as b where b.author=:author",
[author: 'Dan Brown'], [max: 10, offset: 5])
could lead to this:
def exchangeRates = ExchangeRate.findAll("from ExchangeRate as e where e.from = :from order by id desc", [from: from], [max: 1])
if (exchangeRates.size() == 1) {
return exchangeRates.first().rate
}
return null
is there a better way (e.g. one which doesnt use hibernate low level language, or one which uses SQL instead, or one which is more efficient?)
Try using a subquery according to the documentation.
def query = ExchangeRate.where {
id = max(id).of { from == fromValue } && to == toValue
}
query.find()
I retrieve rows on the my database through my domain using a code similar to this:
def DomainList = DomainClass.list(sort: orderBy, order: "asc")
Assuming that the orderBy variable is a String that is the name of one of the domain's column. But what if I want to sort it by a column index instead:
SELECT * FROM `table` ORDER BY 2 DESC
How can I do that on Grails?
After some time, I gave up on finding a dynamic solution. Instead, I use an if-else trap at the beginning of the code since each index corresponds to a particular column:
def orderBy = params?.orderBy
def orderByPolicy = params?.orderByPolicy
if(orderBy.equals("0")) {
orderBy = "name_of_index_0_column"
}
else if(orderBy.equals("1")) {
orderBy = "name_of_index_1_column"
}
else if(orderBy.equals("2")) {
orderBy = "name_of_index_2_column"
}
else if(orderBy.equals("3")) {
orderBy = "name_of_index_3_column"
}
if(!orderByPolicy?.equalsIgnoreCase("desc")) {
orderByPolicy = "asc"
}
def DomainList = DomainClass.list(sort: orderBy, order: orderByPolicy)
Note though, this is not dynamic. It cannot accommodate adding on new columns to the DomainClass; you must manually edit also the if-else trap.
I ran below HQL Query, I got [2015,2014]
select DISTINCT(YEAR(SP.deliveryDate)) from SupplyPlan as SP where SP.samplePlan=2
Above query I need in criteria, I have tried like below but it is not working. Any suggestions?
def supplyPlanCriteria=SupplyPlan.createCriteria()
def list=supplyPlanCriteria.list {
projections {
property("YEAR(deliveryDate)")
}
eq("samplePlan",samplePlan)
}
I wanted to make some translatable content with rest service so i decided to create collection with this structure. But I can't find BSON by value from String Map.
class LocalizableString{
static mapWith = "mongo"
ObjectId id
Map<String, String> values = new HashMap<String, String>();
}
Then i wanted to get like this. But it works like join query.
def list = LocalizableString.createCriteria().list {
values{ like('value',"%${value}%") }
}
Here is similar plain mongo example. But how can i implement it with gorm mongoDB http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-Example
Is there any solution for that ?
class BaseService {
def findByLocalizableString(def domainClass ,def query , def field ,def params = null) {
def q = new BasicDBObject()
def queryList = []
def allowedLanguages = ConfigurationHolder.config.grails.localizableString.allowedLanguages
allowedLanguages.each { locale ->
queryList.add(new BasicDBObject("values.${locale}", new BasicDBObject('$regex', /.*${query}.*/)))
}
q.put('$or',queryList)
def lsc = LocalizableString.collection.find(q)
def list = lsc.hasNext() ? domainClass.createCriteria().list(params) {
or {
while (lsc.hasNext()) {
def n = lsc.next()
eq("${field}",n._id)
}
}
} : null
return list
}
}
I'm not 100% on this, but I'm fairly certain the Mongo GORM plugin does not work with criteria relation traversal, which is what this looks like (despite not really being like that).
From mongoGorm website (http://blog.mongodb.org/post/18510469058/grails-in-the-land-of-mongodb):
Some of the GORM features that are not supported include:
Criteria queries on associations
HQL
Groovy SQL
So you may need to rethink the Map structure you have as a data model here :/ Anyone more experienced can weigh in?