2012-09-28 51 views
0

我正在開發一個GRAILS應用程序(我是GRAILS的新手,並繼承了以前的開發人員的項目)。我正在慢慢掌握GRAILS如何操作以及DOMAIN類,休眠等的使用。MySQL數據庫託管在Amazon上,我們正在使用ElasticCache。grails:將SQL轉換爲域類

做你們任何一位更有見識的人都知道如何將下面的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一個url可以關聯到許多類別。因此,本質上,我試圖實現應該是一個相對基本的操作...返回搜索詞'汽車'的所有網址,它們的權重(即重要性)和ugc_flag不是1(即該網址不是用戶生成的內容)。數據庫中有100K以上的記錄,這些記錄是從第三方提供商導入的。請注意,所有的URL都屬於我的客戶 - 這裏沒有做任何狡猾的事情。

請注意我在查詢中使用的rlike - 我最初使用的是ilike%searchterm%,但會發現其中searchterm是較大單詞的一部分的類別,例如'caravan') - 不幸的是,雖然rlike不是如果用戶請求「汽車」將返回任何東西。

我編輯了代碼 - 正如伊戈爾指出最初的'domainName'的奇怪包含。這是一個可選的參數傳遞,允許用戶過濾只有某個域名的網址(例如'example.com')

回答

0

我會創建一個給定域對象的空列表, 循環遍歷resultsList,構造來自每行的域對象並將其添加到這些對象的列表中。然後從控制器返回該列表以查看。那是你在找什麼?

+0

由於矢量當or限制效果更好。我很高興通過循環遍歷resultsList,並且現在我正在將它發送到gsp視圖,就像您提到的一樣。我實際上從代碼中刪除了這個問題,只是爲了將我的問題集中在如何將SQL轉換爲休眠狀態。 – Ewen

0

1)如果是從暫存(而不是基於舊的數據庫結構開發的Grails應用程序),那麼你應該已經有了領域類CategoryTargetUrlMetaData(否則你必須手動或創建它們DB-逆向工程插件)

2)我假設Target有場Category categoryCategory有一個字段UrlMetaData urlMetaData

3)要走的路可能是http://grails.org/doc/2.1.0/ref/Domain%20Classes/createCriteria.html,我會盡力勾勒出基本使用特殊情況下

4)不知道是什麼意思theDomain - 可能是一個代碼味道,以及從下面的代碼沒有經過測試,在所有客戶端

5)接受rlike參數 - 尤其是我不確定嵌套條件中的分離是如何工作的。但這可能是一個合適的起點;登錄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 
} 

幫助可能明確寫入

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 
} 

乾杯,
伊戈爾Sinev

+0

謝謝伊戈爾!我編輯原始帖子,以包括數據庫表和一些虛擬數據。在代碼中修復了domainName的使用,並進一步解釋了我試圖最終實現的功能。 – Ewen

+0

我仍然不確定您是否已經擁有「類別」和「目標」這樣的域類,或者您現在需要現在創建它們。 –

+0

如果你確實有域名類,那麼你能否告訴我是否提供了我建議的代碼? (我認爲根據您的數據從頭開始構建測試應用程序並不現實 - 無論如何它都不準確) –