在MongoDB中存储数据的有效方法:嵌入式文档与单个文档

我存储用户活动数据:当用户访问当前文章,主题或个人消息时,向他显示他在离线时添加了多少新评论和消息。

class SiteActivity include Mongoid::Document include Mongoid::Timestamps belongs_to :user belons_to :activity, polymorphic: true end 

在这种情况下,我为每个文档存储一条记录。

另一种选择是使用嵌入式文档,因此所有用户活动都将存储在一个文档中:

 class SiteActivity include Mongoid::Document belongs_to :user embeds_many :user_activities validates :user_id, uniqueness: true end class UserActivity include Mongoid::Document include Mongoid::Timestamps embedded_in :site_activity belongs_to :activity, polymorphic: true end 

所以现在我不需要搜索所有SiteActivities(许多记录)但我可以为current_user获取一个user_activity并通过它嵌入文档找到我需要的活动。

哪种方式更有效地存储和搜索数据?

我的普通用例是:

我有一个用户和一个post,所以我使用这些数据获取site_activity,以查看此用户上次访问post的日期。

我的第一个选择:

 activity = SiteActivity.where(user_id: current_user.id, activity_id: post.id, activity_type: post.class) 

第二个

 user_activity = SiteActivity.where(user_id: current_user.id) activity = user_activity.user_activities.where(activity_id: post.id, activity_type: post.class) 

如果可能的话,最好使用第一种方法(单个文档)并使用上限集合,因为您不希望快速增长的集合(mongoid将支持2.2中的上限集合,这将在本周末出来我猜测)。

第二种方法(嵌入式文档),您需要先为用户获取根文档,然后遍历应用程序中的数组,以查找与您要查找的post相关的活动。 由于查找嵌入式文档时语法的相似性,Mongoid可能会让它看起来像是在db中完成的一切,但它真的迭代了数组。

由于您在进行查询之前已经拥有了user_id,activity_id和activity_type,并且您不希望在查找特定活动时从db检索用户的整个活动列表,因此我更倾向于第一种情况。 应用程序中的计算(搜索)会少得多,网络流量也会少得多。

使用单个文档方法,如果您还在user_id,activity_id,activity_type上创建唯一索引,那将会很棒。 它将帮助您包含文档数量。 您可以进行唯一性validation(额外查询),但如果您拥有唯一索引,那么这几乎是不必要的。 如果存在重复,validation的唯一好处是validation错误,但索引将静默忽略重复条目,除非您保持安全模式。

如果您还希望保留历史站点活动,则可以使用以下结构:

 class SiteActivity include Mongoid::Document include Mongoid::Timestamps belongs_to :user belongs_to :activity, polymorphic: true index [:user_id, :activity_id, :activity_type], :background => true, :unique => true field :last_access_time, :type => Time # last_access_times just here for history, not used field :last_access_times, :type => Array, :default => [] end activity = SiteActivity.find_or_initialize_by(:user_id => current_user.id, :activity_id => post.id, :activity_type => post.class) time = Time.now.utc activity.last_access_time = time activity.last_access_times << time activity.save 

似乎昨天讨论了类似的话题。 查看mongodb中日志分析数据库的最佳可能架构设计也许它会有所帮助。