题
在 MongoDB 中存储嵌套集(如注释树)的最佳实践是什么?
我的意思是,每个评论都可以有家长评论和儿童评论(答案)。
像这样存储它们:
{
title: "Hello",
body: "Please comment me!",
comments: [
{
author: "Peter",
text: "Hi there",
answers: [
{
author: "Peter",
text: "Hi there",
answers: [
{ author: "Ivan", text: "Hi there" },
{ author: "Nicholas", text: "Hi there" }
]
},
{ author: "Ivan", text: "Hi there" },
{ author: "Nicholas", text: "Hi there" },
]
},
{ author: "Ivan", text: "Hi there" },
{ author: "Nicholas", text: "Hi there" },
]
}
这并不酷,因为我们不能在没有 map/reduce 的情况下请求“Peter 评论的所有帖子”。
解决方案
我认为没有完美的解决方案 - 取决于哪些操作是你的应用程序更重要。我相信硅谷内幕店嵌套的MongoDB例如意见。这确实让你提到更难查询。
一种选择是储存在顶层在后阵列中的所有评论者的列表。认为,由于非规范化的数据。然后,你就可以找到其中涉及一定评论员的所有帖子。然后向下钻取,您使用的map / reduce或db.eval()来获取内嵌套的职位信息。
另一个注意 - 如果你正在处理一个单一的文件,db.eval()可能是体重轻于的map / reduce。 $其中也是一种选择,但可以是缓慢的,所以我喜欢上述附加“的评论者名单” - 不是也容易索引数组太(见“多键”在docs)
其他提示
在 dm 的帖子 Dwight Merriman 的链接中提到使用路径键并进行正则表达式匹配
{
path : "a.b.c.d.e.f"
}
另一种方法是使用数组
{
path : ["a", "b", "c", "d", "e", "f"]
}
db.test.ensureIndex({path: 1})
这应该会变得相当快。
如果每个节点只能位于单个路径中,那么您无需担心它在列表中的位置
db.test.find({path: "a"})
会找到“a”的所有孩子
我可能会使用节点的 _id 而不是路径名。
更新
- 需要注意的一件事是索引中只能有一个数组。
请小心对您的查询使用解释
db.test.find({路径:{$在:[“a”,“b”]})
给你
db.test.find({path: {$in: ["a", "b"]}}).explain()
{
"cursor" : "BtreeCursor path_1 multi",
"nscanned" : 2,
"nscannedObjects" : 2,
"n" : 1,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"path" : [
[
"a",
"a"
],
[
"b",
"b"
]
]
}
}
但
db.test.find({path: {$all: ["a", "b"]}}).explain()
{
"cursor" : "BtreeCursor path_1",
"nscanned" : 1,
"nscannedObjects" : 1,
"n" : 1,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"path" : [
[
"a",
"a"
]
]
}
}
只使用第一个元素,然后扫描 b 的所有匹配结果。
如果 a 是您的根元素或位于大多数记录中,那么您将对记录进行近乎完整的扫描,而不是进行有效的索引查询。
不隶属于 StackOverflow