我有一个活跃的记录模型Event
我想按排名排序。等级将是加权属性的总和。例如,我可能想要使用某些逻辑对事件进行排名:
LOG(number of followers) + (7 - number of days from now)
以下工作,但不能令人满意,因为它返回结果集而不是关系对象。因此,我无法将其视为范围。 (仅供参考我使用Postgres和PostGIS扩展程序)
x = Event.find_by_sql("
SELECT
(
CASE WHEN COUNT(follows.*) = 0
THEN 0
ELSE LOG(COUNT(follows.*)) END
+
SIGN(7 - (EXTRACT(EPOCH FROM start) - EXTRACT(EPOCH FROM NOW())) / 86400) * LOG(ABS(7 - (EXTRACT(EPOCH FROM start) - EXTRACT(EPOCH FROM NOW())) / 86400))
) as score,
events.*
FROM events
LEFT OUTER JOIN follows
ON events.id = follows.followable_id AND follows.followable_type = 'Event' AND follows.blocked = 'f'
WHERE (events.start > NOW()) AND (ST_DWithin(st_setsrid(st_point(#{@location[:lng]}, #{@location[:lat]}), 4326), st_transform(loc, 4326), 48280.2, true))
GROUP BY events.id
ORDER BY 1 DESC
")
我知道我可以在Events
表中添加一个计数器缓存并避免连接,但将来我会想通过其他一些关联来计算排名,所以知道如何非常有帮助。
由于
答案 0 :(得分:3)
这实际上很容易分成ActiveRecord::Relation
个查询。
x = Event.select("(
CASE WHEN COUNT(follows.*) = 0
THEN 0
ELSE LOG(COUNT(follows.*)) END
+
SIGN(7 - (EXTRACT(EPOCH FROM start) - EXTRACT(EPOCH FROM NOW())) / 86400) * LOG(ABS(7 - (EXTRACT(EPOCH FROM start) - EXTRACT(EPOCH FROM NOW())) / 86400))
) as score,
events.*")
x = x.joins("LEFT OUTER JOIN follows
ON events.id = follows.followable_id AND follows.followable_type = 'Event' AND follows.blocked = 'f'")
x = x.where("(events.start > NOW()) AND (ST_DWithin(st_setsrid(st_point(#{@location[:lng]}, #{@location[:lat]}), 4326), st_transform(loc, 4326), 48280.2, true))")
x = x.group('events.id')
x = x.order('1 desc')
当然,我建议将它们分成不同的范围,但这至少应该让你朝着正确的方向发展。
答案 1 :(得分:-1)
我认为这不会回答你的问题,但我想使用格式化。
我会更轻松,因为我对ruby更熟悉,我会在你的Event类中创建一个新方法:
def rank
# you rank computation according model columns and associations
Math.log(followers_count) + (7 - number_of_days_from_now)
end
def self.by_rank(order = 'desc')
all.sort{ |event, event1| order == 'desc' ? event1 <=> event : event <=> event1 }
end
然后你可以扩展你的计算缓存,在事件表中创建一个排名列,这样你就可以这样做:
Event.order('rank desc')
Event.order('rank asc')