Отличный способ сделать это в Grails - PullRequest
0 голосов
/ 06 января 2010
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 (в отличной форме)?

Любые решения, использующие критерии или пользовательские запросы, также приветствуются.

Ответы [ 3 ]

1 голос
/ 06 января 2010

Это будет работать:

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())

0 голосов
/ 23 июня 2011

Я думаю, что вам нужно использовать отдельный запрос для каждого тега статьи:

// 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 для запросов.

0 голосов
/ 06 января 2010

В идеале вы должны использовать Criteria Query, ошибка, поскольку вы сказали, что не беспокоитесь о производительности, что-то вроде этого должно работать:

def category = 
def tagName

def relatedArticles = Article.list().findAll {
    (it.categoryName == myArticle.categoryName) || ( it.tags.contains(tagName) )            
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...