ActiveRecord获得特定时间段的奖项评选获奖网站

时间:2019-06-11 08:17:57

标签: ruby-on-rails activerecord

有一个Website模型,其中有Rating个属性,其中有score个。

要确定十大获胜者网站,我可以在此之后计算并缓存total_score在网站记录和订单上。

不幸的是,这并非易事-我需要在特定时间范围内确定奖项的获胜者。可以在奖励时间段之前和之后对其进行评分。

我该怎么做?分组然后按计数排序(这不起作用-见下文)?我猜它有大约1.000个网站记录,总共有100.000个评分...

Website.left_joins(:ratings).group('ratings.website_id').
        where(ratings: { created_at: Time.parse('2019-01-01')..Time.parse('2019-06-01') }).
        order('count(ratings.score) desc').
        limit(10)

还是创建类似那个时期的快照?

任何建议都会很棒!

1 个答案:

答案 0 :(得分:2)

如果没有联接/子查询:

即如果您仅要检索前10个(仅少数)网站,而不是成千上万的{{​​1}}记录,或者您不想对成千上万个数组中的每一个进行迭代。

import React, { Component } from 'react';
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";

export default class DatepickerDemo extends Component {

  constructor() {
    this.state = {
      selectedDate: null
    }
  }

  componentDidMount() {
    this.curDate = new Date()
    this.setState({
      selectedDate: this.curDate.setDate(this.curDate.getDate() +2)
    })
  }

  handleChange = (date) => {
    this.setState({ selectedDate: date });

  }
  render() {
    console.log("state", this.state);
    return (
      <div>
        <DatePicker
          selected={this.state.selectedDate}
          onChange={this.handleChange}
          autoFocus
        />
      </div>
    )
  }

警告: 注意,上面的查询只是“选择” website,而不是“ ratings = Rating.where( created_at: Time.parse('2019-01-01')..Time.parse('2019-06-01') ).group( :website_id ).order( 'sum(score) desc' ).select( :website_id ) top_10_winner_websites = ratings.take(10).map(&:website) # above is ordered by sum(score) desc # so, # top_10_winner_websites[0] has the highest sum score, while # top_10_winner_websites[-1] has the lowest sum score amongst the 10 ”,这意味着另一个ratings.website_id个对象的属性(例如ratings.*id)将全部为score,只有ratings

如果具有联接/子查询:

编辑:下面的待办事项尚未完成;可能需要帮助。无法找到/解决保留子查询外部nil的顺序的方法。此刻很忙。

如果要迭代每个website_id记录,或者要检索数千个website_id记录,则可以防止N + 1查询。

website

当前解决方法(针对上面未完成的子查询):

作为解决子查询外部“保留顺序”的解决方法,同时防止N + 1个查询:

website

编辑:根据扩展请求,您可以检查并获得网站的排名:

top_10_winner_websites = Website.where(
  id: Rating.where(
    created_at: Time.parse('2019-01-01')..Time.parse('2019-06-01')
  ).group(
    :website_id
  ).order(
    'sum(ratings.score) desc'
  ).select(
    'website_id r'
  )
).limit(10).order('r.website_id asc')

^如果您想要一个纯SQL等级检查器,我不太确定如何实现它。

编辑:每个扩展请求为ratings = Rating.where( created_at: Time.parse('2019-01-01')..Time.parse('2019-06-01') ).group( :website_id ).order( 'sum(ratings.score) desc' ).select( :website_id ) top_10_winner_website_ids = ratings.take(10).map(&:website_id) top_10_winner_websites = Website.where( id: top_10_winner_website_ids ).sort_by do |website| top_10_winner_website_ids.index(website.id) end 记录具有额外的“条件”:

...您仍然可以使用website_to_check = Website.find(1) index = top_10_winner_websites.index{|winner_website| winner_website.id == website_to_check.id } if index.nil? puts 'Website was not part of the top 10 winners in this time period' else puts "Website rank for this time period was: #{index + 1}" end ,但是与Websitejoins(:website)相比,这不能阻止N + 1个查询,但是由于{{ 1}},但是您仍然可以使用上述解决方法来阻止N + 1查询。参见下面的完整示例:

eager_load(:website)