我们有ShopArticles商店,想要添加评级系统。
我们的ShopArticle看起来像这样:
class ShopArticle {
String contUnit = 'STK', orderUnit = 'PCK'
Double value, tax = 0.19
String name, description, keyword
String group1, group2, group3, articleNumber
String producer
Boolean unlocked
static hasMany = [ratings: ShopArticleRating]
}
评级看起来像这样:
class ShopArticleRating {
String comment
int rating
ShopArticle shopArticle
User user
static belongsTo = ShopArticle
}
现在我们要过滤一个atricle的平均评分,所以我们做了这个:
def shopArticleList = ShopArticleRating.createCriteria().listDistinct {
projections {
groupProperty("shopArticle")
}
}
def ids = []
shopArticleList.each { shopArticle ->
def sum = 0
shopArticle.ratings.each {
sum += it.rating
}
if ((sum / shopArticle.ratings.size()) >= filter.rating) {
ids.add(shopArticle.id)
}
}
List<ShopArticle> list = ShopArticle.createCriteria().list {
if (ids.size() > 0) {
'in'("id", ids)
}
}
有没有更好的方法来过滤平均评分?
也许是这样的:
List<ShopArticle> list = ShopArticle.createCriteria().list {
createAlias('ratings','r')
projections {
groupProperty('r.rating')
}
gt("r.rating",filter.rating)
}
答案 0 :(得分:0)
如果是我,我会将一个averageRating属性添加到ShopArticle类本身。
计算在为ShopArticle添加/删除/更改评级时的平均值,并分配在每个评级条目/更改中进行数学计算的“成本”。十个人添加评分,你做10次数学运算。一千人做查询,你不做1000次数学计算。
显示平均评分只不过是在屏幕上显示另一个属性,过滤是微不足道的 - 查询数据时没有额外的工作(我认为可以安全地打赌会有更多的查询而不是添加评级)。 / p>
答案 1 :(得分:0)
试试这个:
ShopArticleRating.withCriteria {
projections {
avg("rating")
groupProperty("shopArticle")
}
}
这应该为您提供文章对象以及评分的平均值。
我无法测试相反的方式,但它应该是这样的:
ShopArticle.withCriteria {
projections {
ratings {
avg("rating)
}
property("id")
}
}
应该为您提供文章ID以及相应评级的平均值
另一种方法是编写自己的sql语法,让你绝对自由地返回你想要的一切。在这种情况下,寻找“grails HQL”。有时候,当我需要进行非常复杂的查询时,我会触摸边框。但在你的情况下,你应该是好的。