mongo 模式(嵌入与参考)[重复]
Posted
技术标签:
【中文标题】mongo 模式(嵌入与参考)[重复]【英文标题】:mongo schema (embedding vs reference) [duplicate] 【发布时间】:2011-12-06 09:28:54 【问题描述】:假设我正在设计一个像 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 提要(布尔值)。
根据描述,我可以想到 Mongo 中模式设计的两种替代方案:
创建一个 checkin 集合,并使用 mongo 生成的引用 id 将其存储在 User 集合中,并将 Places 集合作为每个集合中的 check-ins []。这样就可以很容易地确定每个用户和每个场所的汇总统计数据。
不要创建签到集合,而是使用相同的签到信息更新地点和用户数据。
我相信我在 mongo 文档中读到,如果在没有包含聚合信息的对象的情况下几乎从不显示正在聚合的数据,则应该直接使用聚合。如果我们按照foursquare应用程序使用的方法,它只会在我们查看用户的个人资料时显示用户的总签到或在我们查看他们的地点详细信息时的地点签到统计信息。
这里的任何建议将不胜感激。
谢谢。
【问题讨论】:
【参考方案1】:我个人会使用单独的集合,主要是为了使您的用户/地点对象保持较小,因为每个用户/地点可以有无限的签入次数。如果您在 checkins 集合中的 user_id/timestamp 和 place_id/timestamp 上放置索引,则查询特定用户或地点将是有效的。使用单独集合的第二个好处是,当 MongoDB 变得太大时,它不必继续移动您的用户或放置对象。相反,它只会继续追加到 checkins 集合中,这应该是非常有效的(每个分片每秒插入 1000 次中的 10 次)。
我还应该提到,我不会将签到 ID 存储在地点或用户文档中,因为您可以从签到文档中的 place_id 或 user_id 索引中获得相同的性能优势.
【讨论】:
【参考方案2】:我同意 Rick 的观点,尽管您可能希望将关于签到的汇总数据存储在您的场所/用户文档(例如 totalCheckinCount)中以便快速检索。
这对于 Rick 强调的增长/移动问题是安全的,因为简单的聚合数据在 O(1) 处有界地增长,这与存储实际签到本身不同,后者当然会在 O(n) 处增长,其中 n 是签到次数。
【讨论】:
以上是关于mongo 模式(嵌入与参考)[重复]的主要内容,如果未能解决你的问题,请参考以下文章