【问题标题】:Rails complicated selection with order in mongoidRails 复杂的选择与 mongoid 中的顺序
【发布时间】:2018-08-20 16:57:57
【问题描述】:

我有:

gem 'rails', '~> 5.1.1'

gem 'mongoid', '~> 6.1.0'

我有 3 个模型,与这个问题有关。

class Book
  include Mongoid::Document
  field :name, type: String
  field :author, type: String
  field :description, type: String
  field :status, type: String
  field :image, type: String

  has_many :histories, dependent: :destroy
  has_many :likes, dependent: :destroy
  has_many :comments, dependent: :destroy

  def ordered_histories
    histories.order(taken_in: :desc)
  end

  def book_rating
    rating_array = likes.map { |like| like.rate.to_i }
    return 0 if rating_array.empty?
    (rating_array.sum / rating_array.size).round
  end
end

class Like
  include Mongoid::Document
  field :rate, type: Integer
  belongs_to :book
  belongs_to :user
end

class History
  include Mongoid::Document
  field :taken_in, type: DateTime
  field :returned_in, type: DateTime
  belongs_to :book
  belongs_to :user
end

我需要获得点赞和历史最多的前 5 本书。

据我所知 - mongoid 不支持连接。 我考虑过在 Book 模型中存储 likes_count 和 histories_count 。但我认为这不是最好的方法。请帮助我找到更好的解决方案,从 mongodb 获得前 5 本书。

【问题讨论】:

    标签: ruby-on-rails database mongodb mongoid relationship


    【解决方案1】:

    您应该使用aggregation framework。

    尝试使用以下代码获取历史记录最多的前 5 本书的 ID。相同的方法可以用于 Like 类。

    History.collection.aggregate([
        {"$group" => {
            "_id" => "$book_id",
            "histories" => {"$sum" => 1}
        }},
        {"$sort" => { "histories" => -1}},
        {"$limit" => 5 }
    ])
    

    【讨论】:

    • 你好。我尝试过这种方式,但我并不完全了解如何从退回的书籍中获取顶级书籍的 ID。我已将此代码的返回值分配给变量 top_books,然后在控制台中查看结果。我发现结果是:
    • #<:collection::view::aggregation:0x00000004d9e960 namespace="library_exercise_development.histories">, @pipeline=[{"$group"=>{"_id"=>"$book_id", "likes"=>{"$sum"=>1}}}, {"$sort"= >{"likes"=>-1}}, {"$limit"=>5}], @options={}, @cursor=#<:cursor:0x38733420 :view:0x40695240 namespace="library_exercise_development.histories">>> 我也尝试迭代结果,发现它只包含第一本书 id {"_id"=>BSON::ObjectId ('5a9aabf193e60b126fd406dc'), "喜欢"=>2}
    • 我阅读了大量文档,但我需要澄清如何获取所有 5 本书的 ID。如果可以,请帮助我。
    • 您的数据库中有多少历史书籍?您是否有包含示例数据的种子脚本或数据库转储,以便我可以在本地恢复并进行测试?
    • 对不起。我犯了一个小错误。你是对的。我只有一本历史书。但我有两本书喜欢。在我尝试这种方式之后: Like.collection.aggregate([ {"$group" => { "_id" => "$book_id", "likes" => {"$sum" => 1} }}, {" $sort" => { "likes" => -1}}, {"$limit" => 5 } ]) 我得到了 2 本书,顺序正确。
    【解决方案2】:

    我找到了另一种使它起作用的方法。 我已将 counter_cash 添加到模型 Like 和 History:

    class Like
      include Mongoid::Document
      field :rate, type: Integer
      belongs_to :book, counter_cache: :likes_count
      belongs_to :user
    end
    
    class History
      include Mongoid::Document
      field :taken_in, type: DateTime
      field :returned_in, type: DateTime
      belongs_to :book, counter_cache: :histories_count
      belongs_to :user
    end
    

    之后,我使用一个查询来获得喜欢和历史最多的前 5 本书:

    @top_books = Book.all.order_by(likes_count: :desc, histories_count: :desc).limit(5)
    

    我认为这是一种可能的方法。可能会帮助某人。请告诉我,如果我犯了任何错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-06
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多