我有这个系列:
Books
[
{
title: Book1,
References: [ObjectId(1), ObjectId(3), ObjectId(5)] <- These are object ids of another collection
Main-Reference: ObjectId(5)
},
{
title: Book2,
References: [ObjectId(2), ObjectId(5), ObjectId(7)]
Main-Reference: ObjectId(5)
}
{
title: Book3,
References: [ObjectId(5), ObjectId(7), ObjectId(9)]
Main-Reference: ObjectId(7)
},
]
我有一个操作,我从书籍集中删除了一个参考 示例:假设我必须从我的集合中删除Reference ObjectId(5) 所以我的新系列变成了这个:
Books
[
{
title: Book1,
References: [ObjectId(1), ObjectId(3)] <- ObjectId(5) is pulled
Main-Reference: ObjectId(1) <- ObjectId(1) is new value as ObjectId(5) is deleted
},
{
title: Book2,
References: [ObjectId(2), ObjectId(7)] <- ObjectId(5) is pulled
Main-Reference: ObjectId(2) <- ObjectId(2) is now main reference
}
{
title: Book3,
References: [ObjectId(7), ObjectId(9)] <- ObjectId(5) is pulled
Main-Reference: ObjectId(7) <- no changes here as ObjectId(7) still exists in References
},
]
目前我正在做的事情:
步骤1:从所有书籍中拉出ObjectId(5),其中References []具有ObjectId(5)
第2步:查询Books集合,其中Main-Reference = ObjectId(5)&amp;使用引用:{$ slice:1} slice从References数组中获取第一个数组元素
第3步:更新在步骤2和步骤2中找到的所有书籍。用我从slice
获得的第一个数组元素替换Main-Reference这对我来说似乎很笨拙,并试图看看是否有更好的方法来做到这一点。
答案 0 :(得分:1)
如果我基本上得到你的要点你基本上想要
在一次更新中完成所有操作,无需通过网络移动文档。
但遗憾的是,这无法做到。这样做的主要问题是无法引用正在更新的文档中的另一个字段的值。即便如此,要在不进行迭代的情况下执行此操作,您还需要访问已更改的数组,以获取新的第一个元素。
也许一种方法是重新思考您的架构,以实现您想要的。我在这里的选择会扩展您的参考文档,并且不需要主参考字段。
似乎您愿意接受更新的假设是,如果删除的引用是主引用,那么您可以将新的主引用设置为数组中的第一个元素。考虑到这一点,请考虑以下结构:
refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ]
通过将这些属性更改为具有oid
属性的文档,该属性将设置为ObjectId,它提供了在文档上具有指定默认值的附加属性的选项。这可以很容易地查询确定哪个Id是主要参考。
现在还要考虑如果从数组中提取oid字段中匹配“object5”的文档会发生什么:
refs: [ { oid: "object1" }, { oid: "object2" } ]
因此,当您根据先前的逻辑查询哪个是main-reference
时,您接受数组中的第一个文档。当然,根据您的应用程序要求,如果您想设置不同的main-reference
,您只需更改文档
refs: [ { oid: "object1" }, { oid: "object2", main: true } ]
现在逻辑仍然是选择具有main属性的数组元素,因为true会优先出现,如上所示,如果该属性不存在于任何元素文档上,则返回第一个元素。
通过所有这些消化,你在所有文档中从该数组中提取对象的所有引用的操作变得非常简单,就像在shell中一样(相同的格式应该基本适用于任何驱动程序):
db.books.update(
{ "refs.oid": "object5" },
{ $pull: { refs: {oid: "object5"} } }, false, true )
查询和更新操作的两个额外参数分别为upsert
和multi
。在这种情况下,upsert
没有多大意义,因为我们只想修改存在的文档,而multi
意味着我们想要更新匹配的所有内容。默认设置是仅更改第一个文档。
当然,我缩短了所有符号,但当然值可以是您的意图的实际ObjectId。假设您main-reference
的主要用法是您检索到文档后,似乎也是合理的。通过遵循概述的逻辑来定义返回main-reference
的查询应该是可能的,但是就目前而言,我已经输入了很多东西并需要休息吃晚餐:)
我认为这为重新思考您的架构提供了一个有价值的案例,以避免线索迭代以实现您想要实现的目标。