I have three domain classes: Lead, Submission and BuyerLog:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Lead { | |
static hasMany = [ submissions: Submission ] | |
Date dateCreated | |
// ... | |
} | |
class Submission { | |
static belongsTo = [ lead: Lead ] | |
static hasMany = [ buyerLogs: BuyerLog ] | |
Lead lead | |
// ... | |
} | |
class BuyerLog { | |
static belongsTo = [ submission: Submission ] | |
Submission submission | |
String leadBuyer | |
// ... | |
} | |
I have a need to get the number of duplicate leads which share the same leadBuyer (in the BuyerLog domain class). Here is the SQL:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SELECT count(l.id) | |
FROM lead AS l, submission AS s, buyerLog as bl | |
WHERE l.id = s.leadId | |
AND s.id = bl.submissionId | |
AND bl.leadBuyer = $buyerName | |
AND l.id != $lead.id | |
AND l.dateCreated::date > $daysAgo |
I want to do this using GORM / Criteria Builder. Here's my final code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Count duplicate submissions within 45 days | |
* SELECT count(l.id) | |
* FROM lead AS l, submission AS s, buyerLog as bl | |
* WHERE l.id = s.leadId | |
* AND s.id = bl.submissionId | |
* AND bl.leadBuyer = $buyerName | |
* AND l.id != $lead.id | |
* AND l.dateCreated::date > $daysAgo | |
*/ | |
protected def Boolean isDuplicateSubmission(Lead lead, ArrayList<String> buyerNames) { | |
def isDuplicate = false | |
def daysAgo = new Date() - 45 | |
def cnt = Lead.withCriteria { | |
not { | |
idEq(lead.id) | |
} | |
and { | |
le('dateCreated', daysAgo) | |
submissions { | |
buyerLogs { | |
inList('leadBuyer', buyerNames) | |
} | |
} | |
} | |
projections { | |
rowCount() | |
} | |
} | |
return (cnt > 0) | |
} |
Thanks to schmolly159 on the #grails freenode IRC channel for the examples and continued help.
This comment has been removed by the author.
ReplyDeleteManuel, yes that is correct. I fixed it. Thanks.
ReplyDeleteHey Eric,
ReplyDeleteLooks very cool, but have you thought about perhaps writing this as a named query inside your domain class? Encapsulating this in your model is a very tidy way of doing this sort of thing.
Coincidentally I wrote a blog post about this sort of thing too last week! Check out my article here:
http://mycodesnippets.com/2011/03/20/named-queries-with-projections-in-grails/
Cheers,
Marco.
Sorry, I removed the previous comment because I realized it had a typo. :)
ReplyDelete