我正在使用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