我目前正在使用Meteor和MongoDB构建应用程序。我有一个3级文档结构,数组在数组中:
{
_id: "shtZFiTeHrPKyJ8vR",
description: "Some title",
categories: [{
id: "shtZFiTeHrPKyJ8vR",
name: "Foo",
options: [{
id: "shtZFiTeHrPKyJ8vR",
name: "bar",
likes: ["abc", "bce"]
}]
}]
}
现在,文档可以在任何级别进行操作。意思是:
description
可以更改1和2很容易。添加或删除新选项也相对容易:
MyCollection.update({ _id: id, "categories.id": categoryId }, {
$push: {
"categories.$.options": {
id: Random.id
name: optionName
}
}
});
但是操纵options
哈希需要在javascript对象上执行此操作。这意味着我首先需要找到我的文档,迭代选项然后再写回来。
至少那就是我现在正在做的事情。但我不喜欢这种做法。
我在考虑的是拆分集合,至少将喜欢放入引用原始文档的自己的集合中。
还是有另一种方式吗?我真的不喜欢我可能的解决方案。
答案 0 :(得分:1)
对于这种查询,通常会使用Mongo position运算符。虽然来自文档。
嵌套数组
位置$运算符不能用于查询 遍历多个数组,例如遍历的查询 嵌套在其他数组中的数组,因为替换了$ 占位符是单个值
因此,本机执行所需操作的唯一方法是使用特定索引。
db.test.update({},{$pull:{"categories.0.options.0.likes":"abc"}})
不幸的是,Mongo不允许轻松获取匹配嵌套文档的索引。
我通常会说,一旦您的查询变得困难,重新审视存储数据的方式可能是个好主意。对于你将推送数据的那些数组,Mongo可能会重新定位大量文档。这绝对是你想要最小化的东西。
因此,此时您需要将数据分成不同的文档甚至集合。
您的第一份文件将如下所示:
{
_id: "shtZFiTeHrPKyJ8vR",
description: "Some title",
categories: [{
id: "shtZFiTeHrPKyJ8vR",
name: "Foo",
options: ["shtZFiTeHrPKyJ8vR"]
}]
}
通过这种方式,您可以轻松添加/删除问题中提到的选项。然后,您需要第二个集合,其中包含代表每个选项的文档。
{
_id: "shtZFiTeHrPKyJ8vR",
name: "bar",
likes: ["abc", "bce"]
}
您可以详细了解参考资料here。这与您在评论中提到的内容类似。这样做的好处是您已经减少了可能的搬迁量。根据您使用数据的方式,您甚至可能会减少网络使用量。
现在对喜欢的内容进行更新很容易。
MyCollection.update({ _id: id}, {
$push: {likes: "value"}
});
但是,这确实要求您对db进行两次查询。虽然在另一方面,你在客户端做的很少,但使用的带宽要少得多。
您需要问自己的其他一些问题是,是否真的需要嵌套深度。可能有一种更简单的方法来实现您的目标,而不需要它变得如此复杂。