我正在开发一个GRAILS应用程序(我是GRAILS的新手并继承了之前开发人员的项目)。我正在慢慢了解GRAILS如何运作以及DOMAIN类,hibernate等的使用.MySQL数据库托管在亚马逊上,我们正在使用ElasticCache。
您是否有更多知识渊博的人知道如何将以下SQL语句转换为域类和查询条件。
if(params?.searchterm) {
def searchTerms = params.searchterm.trim().split( ',' )
def resultLimit = params.resultlimit?: 1000
def addDomain = ''
if (params?.domainname){
addDomain = " and url like '%${params.domainname}%' "
}
def theSearchTermsSQL = ""
/*
* create c.name rlike condition for each search term
*
*/
searchTerms.each{
aSearchTerm ->
if( theSearchTermsSQL != '' ){
theSearchTermsSQL += ' or '
}
theSearchTermsSQL += "cname rlike '[[:<:]]" + aSearchTerm.trim() + "[[:>:]]'"
}
/*
* build query
*
*/
def getUrlsQuery = "select
u.url as url,
c.name as cname,
t.weight as tweight
from
(category c, target t, url_meta_data u )
where
(" + theSearchTermsSQL + ")
and
t.category_id = c.id
and t.url_meta_data_id = u.id
and u.ugc_flag != 1 " + addDomain + "
order by tweight desc
limit " + resultLimit.toLong()
/*
* run query
*
*/
Sql sqlInstance = new Sql( dataSource )
def resultsList = sqlInstance.rows( getUrlsQuery )
}
表格如下(虚拟数据):
[Category]
id | name
-----------
1 | small car
2 | bike
3 | truck
4 | train
5 | plane
6 | large car
7 | caravan
[Target]
id | cid | weight | url_meta_data_id
----------------------------------------
1 | 1 | 56 | 1
2 | 1 | 76 | 2
3 | 3 | 34 | 3
4 | 2 | 98 | 4
5 | 1 | 11 | 5
6 | 3 | 31 | 7
7 | 5 | 12 | 8
8 | 4 | 82 | 6
[url_meta_data]
id | url | ugc_flag
---------------------------------------------
1 | http://www.example.com/foo/1 | 0
2 | http://www.example.com/foo/2 | 0
3 | http://www.example.com/foo/3 | 1
4 | http://www.example.com/foo/4 | 0
5 | http://www.example.com/foo/5 | 1
6 | http://www.example.com/foo/6 | 1
7 | http://www.example.com/foo/7 | 1
8 | http://www.example.com/foo/8 | 0
域类
class Category {
static hasMany = [targets: Target]
static mapping = {
cache true
cache usage: 'read-only'
targetConditions cache : true
}
String name
String source
}
class Target {
static belongsTo = [urlMetaData: UrlMetaData, category: Category]
static mapping = {
cache true
cache usage: 'read-only'
}
int weight
}
class UrlMetaData {
String url
String ugcFlag
static hasMany = [targets: Target ]
static mapping = {
cache true
cache usage: 'read-only'
}
static transients = ['domainName']
String getDomainName() {
return HostnameHelper.getBaseDomain(url)
}
}
基本上,来自url_meta_data的网址可以与许多类别相关联。所以本质上我想要实现的应该是一个相对基本的操作...返回搜索词'car'的所有url,它们的权重(即重要性)以及ugc_flag的位置不是1(即url不是用户生成的内容)。数据库中有100K以上的记录,这些记录是从第三方提供程序导入的。请注意,所有URL都属于我的客户端 - 这里没有做任何狡猾的事情。
请注意我在查询中使用的rlike - 我最初使用的是ilike%searchterm%,但是会找到类别,其中searchterm是更大词的一部分,例如'caravan') - 不幸的是,虽然rlike不会如果用户请求“汽车”,则返回任何内容。
我编辑了代码 - 因为Igor指出了'domainName'最初的奇怪包含。这是一个传递的可选参数,允许用户过滤仅某个域的网址(例如'example.com')
答案 0 :(得分:0)
我创建了一个给定域对象的空列表, 循环遍历resultsList,从每一行构造一个域对象,并将其添加到这些对象的列表中。然后从控制器返回该列表以查看。这就是你要找的东西吗?
答案 1 :(得分:0)
1)如果它是从头开发的Grails应用程序(而不是基于遗留数据库结构),那么您可能应该已经拥有域类Category
,Target
,UrlMetaData
(否则你必须手动或使用db-reverse-engineer插件创建它们
2)我认为Target
有一个字段Category category
而Category
有一个字段UrlMetaData urlMetaData
3)可行的方法可能是http://grails.org/doc/2.1.0/ref/Domain%20Classes/createCriteria.html,我将尝试概述您特定案例的基础知识
4)不确定theDomain
意味着什么 - 可能是代码气味,以及从客户端接受rlike
个参数
5)以下代码根本没有经过测试 - 特别是我不确定嵌套标准内部的分离是否有效。但这可能是一个合适的起点; logging sql查询应该有助于使其工作(How to log SQL statements in Grails)
def c = Target.createCriteria() //create criteria on Target
def resultsList = c.list(max: resultLimit.toLong()) { //list all matched entities up to resultLimit results
category { //nested criteria for category
//the following 'if' statement and its body is plain Groovy code rather than part of DSL that translates to Hibernate Criteria
if (searchTerms) { //do the following only if searchTerms list is not empty
or { // one of several conditions
for (st in searchTerms) { // not a part of DSL - plain Groovy loop
rlike('name', st.trim())) //add a disjunction element
}
}
}
urlMetaData { //nested criteria for metadata
ne('ugcFlag', 1) //ugcFlag not equal 1
}
}
order('weight', 'desc') //order by weight
}
明确写明
时,or
限制可能效果更好
if (searchTerms) {
def r = Restrictions.disjunction()
for (st in searchTerms) {
r.add(new LikeExpression('name', st.trim()))
}
instance.add(r) //'instance' is an injected property
}
干杯,
伊戈尔西内夫