2012-11-30 36 views
10

鉴于以下与100,000名朋友竞争的模式,我有兴趣为我的需求找到最高效的模式。MongoDB嵌入与数组子文档性能

文档1(指数上USER_ID)

{ 
"_id" : "…", 
"user_id" : "1", 
friends : { 
    "2" : { 
     "id" : "2", 
     "mutuals" : 3 
    } 
    "3" : { 
     "id" : "3", 
     "mutuals": "1" 
    } 
    "4" : { 
     "id" : "4", 
     "mutuals": "5" 
    } 
} 
} 

文档2

{ 
"_id" : "…", 
"user_id" : "1", 
friends : [ 
    { 
     "id" : "2", 
     "mutuals" : 3 
    }, 
    { 
     "id" : "3", 
     "mutuals": "1" 
    }, 
    { 
     "id" : "4", 
     "mutuals": "5" 
    } 
]} 

我似乎无法找到的任何信息(化合物的多键上user_id的& friends.id指数)子字段检索的效率。我知道mongo在内部将数据实现为BSON,所以我想知道这是否意味着投影查找是二进制O(log n)?

具体来说,给定一个user_id来查找是否存在friend_id的朋友,那么每个模式上的两个不同查询会如何比较? (假设上述索引)请注意,返回的内容并不重要,只有在朋友存在时才返回null。

Doc1col.find({user_id : "…"}, {"friends.friend_id"}) 
Doc2col.find({user_id : "…", "friends.id" : "friend_id"}, {"_id":1}) 

另外值得关注的是$ set修饰符是如何工作的。对于架构1,给定查询Doc1col.update({user_id : "…"}, {"$set" : {"friends.friend_id.mutuals" : 5}),friends.friend_id上的查找工作如何?这是一个O(log n)操作(其中n是朋友的数量)?

对于模式2,查询Doc2col.update({user_id : "…", "friends.id" : "friend_id"}, {"$set": {"friends.$.mutuals" : 5})与上述数据的比较如何?

+3

与数组样式(Doc2)一起使用,动态键几乎从来都不是正确的方法。另外,不要使用明智的引号(这不是合法的语法,而且很难阅读)。 – JohnnyHK

+1

我想Doc2会像一些额外的存储空间一样用完,但是@JohnnyHK说Doc1并不是一个好方法,请相信我使用Doc1的人的问题数量,然后意识到他们必须转向Doc2来做任何事情与他们的架构... – Sammaye

+0

感谢您的意见。 @Sammaye为什么Doc2会占用几个字节的额外存储空间?你指的是索引吗?顺便说一句聪明的报价是从复制粘贴 –

回答

1

如果一个人的主要需求是将数据呈现给用户界面以便于管理,那么doc1更可取。其简单的使用投影{}, {friends.2 : 1}

DOC2是你最强的对手,只过滤出所需的数据,因为你的使用情况不关心结果注意,它并不真正的问题是怎么返回和索引将加快取。

上DOC2的顶部允许更清洁的语法

db.doc2.findOne({user_id: 1, friends.id : 2}) 

db.doc1.findOne({ $and : [{ user_id: 1 }, { "friends.2" : {$exists: true} }] }) 

最后值得注意的是,然而,一个可以创建DOC1一个sparse index(并使用$存在),但你有10万个朋友的可能性 - 每个朋友都需要一个稀疏的索引 - 这使得这个荒谬。反对合理数量的条目说人口统计学性别[男性,女性],年龄组[0-10,11-16,25-30,]或更多impt事物[杜松子酒,威士忌,伏特加,...]