mongo模式(嵌入与引用)

时间:2011-10-12 18:47:53

标签: mongodb database

我们假设我正在设计像Foursquare这样的服务,该服务根据用户位置跟踪用户签到。我使用MongoDB作为后端。

这里的前提是用户可以登录到某个位置,因此架构中的集合可能如下所示:

db.places.find()
{ "_id" : ObjectId("4e6a5a58a43a59e451d69351"), "address" : { "street" : "2020 Lombard     St", "city" : "San Francisco", "state" : "CA" }, "latlong" : [ 37.800274, -122.434914 ], "name" : "Marina Sushi", "timezone" : "America/Los_Angeles" }
{ "_id" : ObjectId("4e6a59c3a43a59e451d69350"), "address" : { "street" : "246 Kearny St", "city" : "San Francisco", "state" : "CA" }, "latlong" : [ 37.79054, -122.40361 ], "name" : "Rickhouse", "timezone" : "America/Los_Angeles" }

db.users.find()
{ "_id" : ObjectId("4e936bc1da06d5e081544b8b"), "_class" : "com.gosociety.server.common.model.User", "email" : "goso@gosociety.com", "password" : "asdfasdf"}

所以在上面的集合中,我们有地方和用户。用户可以“登记”到某个地方,因此当用户登记时,我们会在数据库中保留该记录。办理登机手续将包括:办理登机手续的时间(UTC)和备注(150个字符),以及是否将其发送到他的Facebook Feed(布尔值)。

根据描述,我可以想到Mongo中架构设计的两种选择:

  • 创建一个签入集合,并使用mongo生成的引用ID将其存储在User集合中,并将Places集合存储为每个集合中的签入[]。通过这种方式,可以轻松确定每个用户和每个场地的汇总统计数据。

  • 不要'创建签入集合,但使用相同的签入信息更新地方和用户数据。

我相信我在mongo文档中读到,如果聚合的数据几乎从不显示而没有包含聚合信息的Object,则应直接使用聚合。如果我们按照foursquare应用使用的方法,只有在我们查看其个人资料或在我们查看其地点详细信息时放置签到统计信息时,它才会向用户显示总体签到。

这里的任何建议都将非常感谢。

感谢。

2 个答案:

答案 0 :(得分:3)

我个人会选择一个单独的集合,主要是为了保持用户/位置对象的小,因为每个用户/位置可以有一个无限制的签到#。如果您在checkin集合中的user_id / timestampl和place_id / timestamp上放置索引,那么对特定用户或地点的查询将是有效的。使用单独集合的第二个好处是,当MongoDB变得太大时,它不必继续移动您的用户或放置对象。相反,它将继续附加到checkins集合,这应该是非常有效的(每个分片每秒1000次插入10次)。

我还应该提一下,我将签入ID存储在地方或用户文档中,因为在checkins文档中对place_id或user_id建立索引可以获得相同的性能优势

答案 1 :(得分:0)

我同意Rick的意见,但您可能希望在地点/用户文档(例如totalCheckinCount)中存储关于签到的汇总数据,以便快速检索。

这对于Rick强调的增长/移动问题是安全的,因为简单的聚合数据有限地增长在O(1),不像存储实际的签到本身,当然会在O(n)增长,其中n是签到数量。