【问题标题】:Retain only records whose belongs_to association's has_many has a COUNT of 2?只保留belongs_to 关联的has_many 的COUNT 为2 的记录?
【发布时间】:2021-03-04 15:52:17
【问题描述】:

这个问题举个例子就很容易理解了:像airbnb,客人评价房东,房东评价客人。 Booking 正好有 2 条评论(都是在创建预订时创建的),并且评论有一个字段 submitted: true/false

假设我们希望在房东的个人资料中显示他们的评论,但假设我们想要排除房东尚未评论过客人的任何评论。 (因此,即使房客对房东进行了点评,也应在房客回馈并点评房客之前显示)。我们该怎么做?

还有一个 Booking has_many 评论,评论在 Host 和 Guest 上是多态的。

到目前为止我所知道的

我想出了各种各样的半解决方案,要么不起作用,要么导致 sql 效率极低。这是一个

bookings_for_host = Booking.where(host_id: 1).pluck(:id) # use host number 1 here for example
all_reviews_for_relevant_bookings = Review.where('booking_id IN (?)', bookings_for_host)

# This doesn't work
all_reviews_for_relevant_bookings
  .select("booking_id")
  .group("booking_id")
  .having("COUNT(booking_id = 2")

上面的代码不仅行不通,而且效率也很低。

问题

最终,我如何过滤房东的评论,以便不包含属于_的评论,该预订的评论少于 2 条 submitted == true

【问题讨论】:

    标签: ruby-on-rails activerecord arel


    【解决方案1】:

    我可以想到 3 种可能的解决方案

    解决方案 1在您的审核表中添加一个布尔值我个人会选择这个

    您可以在bookings 表中添加一个布尔列host_and_guest_reviewed,您可以在创建hostguest 评论时对其进行更新。然后你要做的就是检查这个值是否为真。根据您的要求,布尔列也可能在评论表上。

    解决方案 2使用计数器缓存

    每次针对预订创建评论时,预订的计数器都会增加。在这种情况下,您可以有效地清除没有 2 条评论的预订

    你可以阅读更多关于计数器缓存here

    解决方案 3自连接 SQL 查询

    您可以单独加入评论表,以便仅包含预订的其他评论的评论。像这样的

    Review
      .joins('INNER JOINS reviews reciprocated_reviews ON reviews.id != reciprocated_reviews.id AND reviews.booking_id = reciprocated_reviews.booking_id')
    

    【讨论】:

    • 非常感谢。我能问一下为什么你会使用解决方案 1 而不是解决方案 3 吗?是因为它更简单吗?我认为 3 可能会更好,因为它将业务逻辑和数据层分开?
    • 因为solution 3 中的查询比较昂贵。您可以对生成的查询执行explain,并检查数据库服务器是否必须实际遍历表中的每一行才能执行reviews.id != reciprocated_reviews.id 部分。这个我可能错了,你应该验证一次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多