在Grails中做它的Groovy方式

时间:2010-01-06 19:54:37

标签: grails groovy

Article { 
   String categoryName 
   static hasMany = [ 
        tags: Tag 
    ] 
} 

Tag { 
   String name 
}

现在我想查找所有相关文章的列表。相关含义,所有与myArticle具有相同类别名称的文章或与myArtcle具有相同标签的所有文章。

只有匹配的categoryName,这是我如何使用闭包获取relatedArticles。

def relatedArticles = Article.list().find {it.categoryName == myArticle.categoryName } 

任何人都希望通过CategoryName或Tag Name(以一种常规的方式)来查找所有文章?

任何使用Criteria或自定义查询的解决方案也会受到赞赏。

3 个答案:

答案 0 :(得分:1)

这样可行:

def myArticle = // the article you want to match

def relatedArticles = Article.list().findAll {
    (it.categoryName == myArticle.categoryName || 
            it.tags.name.intersect(myArticle.tags.name)) &&
            it.id != myArticle.id)            
} 

但是,如果你有相当多的文章,并且只有少数文章可以匹配,那么效率会非常低,因为这会加载所有文章,然后遍历所有文章,寻找匹配。

更好的方法是简单地编写一个只加载匹配文章的查询(而不是调用Article.list()

答案 1 :(得分:0)

我认为您需要为每篇文章标记使用单独的查询:

// Use a LinkedHashSet to retain the result order if that is important
def results = new LinkedHashSet()

results.addAll(Article.findAll("from Article as article \
  where article.categoryName = :categoryName \
  and article.id != :id",
  [
    categoryName:myArticle.categoryName,
    id:myArticle.id,
  ])

myArticle.tags.each {
 results.addAll(Article.executeQuery(
   "select distinct article from Article as article, \
   Tag as tag \
   where tag.name = :tag \
   and tag in elements(article.tags) \
   and article.id != :id",
   [
     tag:it.name,
     id:myArticle.id,
   ]))
}

def relatedArticles = results as List

当您在系统中拥有大量内容并希望避免为单个页面请求加载整个数据库时,这显然是值得做的。其他改进包括为查询指定max和offset参数。

答案 2 :(得分:-1)

理想情况下,你会使用Criteria Query,因为你说你不关心性能,所以你应该这样做:

def category = 
def tagName

def relatedArticles = Article.list().findAll {
    (it.categoryName == myArticle.categoryName) || ( it.tags.contains(tagName) )            
}