如何在不将整个数组加载到内存中的情况下修改数组单个子文档?



我正在使用Node.jsv8.12.0,MongoDBv4.0.4和Mongoosev5.3.1

我想在不更改其在数组索引中的位置的情况下更新嵌入数组子文档。并且无需在内存中加载整个数组,因为该数组将来可能会变得非常大。


我花了很多时间寻找如何实现这一目标,但没有运气。

我尝试使用 Mongo 的$elemMatch来加载仅包含单个相关数组子文档的文档,但这不会让我以任何实用的方式保存子文档。

我还研究了 Mongoose 数组set方法,但为此您需要有子文档数组索引,所以这意味着我需要将整个数组加载到内存中,然后找到子文档索引。

有什么方法可以实现我想要的吗?理想情况下,通过 Mongoose 抽象,因此所有 Mongoose 中间件(如验证、插件等)都会启动。

实际上在提交这个问题后立即找到了答案。

对于将来查找它的任何人,您可以将特殊$运算符与$set结合使用。(不过,我不确定这是否使用了猫鼬中间件。我需要围绕这一点做一些测试)。


下面是一些代码示例,它使用_id查询某个子文档,然后使用$set更新该子文档属性someProperty,该使用与查询的子文档数组位置/索引匹配的特殊运算符$

var doc = await SomeModel.findOneAndUpdate(
{'someArray._id': 'xxx'},
{'$set': {'someArray.$.someProperty': 'someValue'}},
); 

不过,这仍然不是我想要的 100%。因为返回的doc仍然有完整的子文档数组(我假设它仍然加载到内存中?),而且似乎我不能将$elemMatch$set结合使用。

就我而言,在

更远的道路上,我可能会重新设计数据库架构,以便这些嵌入的子文档将是它们自己的文档,只有 ObjectID 引用"父"文档。


一些资源:

https://docs.mongodb.com/manual/reference/operator/update/positional/

https://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate