我存储用户活动数据:当用户访问当前文章,主题或个人消息时,向他显示在他离线时添加了多少新评论和消息。
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
,并找到我需要通过它嵌入文档的活动。
哪种方式更有效地存储和搜索数据?
我的普通用例是:
我有一个用户和一个帖子,所以我用这个数据获取site_activity,以查看这个用户上次访问帖子的日期。
与我的第一个选项:
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上创建唯一索引,那将是非常好的。它将帮助你控制文件的数量。您可以进行唯一性验证(额外的查询),但如果您有惟一索引,那么就没有必要这样做了。验证的唯一好处是如果存在重复项会出现验证错误,但是index将静默地忽略重复项,除非您以安全模式持久化。
如果您还希望持久化历史站点活动,您可以使用如下结构:
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中日志分析数据库的最佳模式设计,也许它会有所帮助。