有一个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)
还是创建类似那个时期的快照?
任何建议都会很棒!
答案 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
,但是与Website
或joins(:website)
相比,这不能阻止N + 1个查询,但是由于{{ 1}},但是您仍然可以使用上述解决方法来阻止N + 1查询。参见下面的完整示例:
eager_load(:website)