MongoDB嵌套文档插入值报错:位置运算符匹配失败排查
问题描述
现有MongoDB文档
{ "_id": { "$oid": "63cf19337c2df5fe442a2b69" }, "createdAt": { "$date": { "$numberLong": "1674516787623" } }, "updatedAt": { "$date": { "$numberLong": "1675035206032" } }, "clientIp": "89.132.225.21", "products": { "6cc5a480-91f0-4aa8-975c-013d6bd155a3": { "currency": "EUR", "title": "VVV", "price": "12", "barionId": "aa@aa.hu", "ratingTimeLength": 12 } } }
尝试的更新代码
const userId = req.query.userId const productId = req.query.productId const token = authorization.slice(7) const userJWT = jwt.verify(token, process.env.JWT_SECRET) as JwtPayload const ObjectId = require('mongodb').ObjectId const id = new ObjectId().toHexString() await collection.updateOne( { _id: ObjectId(userId), [`products.${productId}`]: { $exists: true } }, { $set: { [`products.$.payments.${id}`]: { createdAt: new Date(), createdBy: userJWT.userId, }, }, }, { upsert: true } )
触发的错误
2023-01-29T23:43:33.653Z 1a42849c-d5aa-4127-8fdc-9169c1c6c405 ERROR MongoServerError: The positional operator did not find the match needed from the query.
补充信息
在Compass中执行以下查询能正常返回目标文档:
{"_id": ObjectId("63cf19337c2df5fe442a2b69"),"products.6cc5a480-91f0-4aa8-975c-013d6bd155a3": {"$exists": true}}
请问问题出在哪里?
问题原因与解决方法
问题根源
MongoDB的**位置运算符$**仅用于匹配数组中的元素,而你的products是嵌套的键值对对象,不是数组。查询条件能匹配到存在的字段,但位置运算符无法定位到对象属性,因此触发报错。
解决方法
无需使用位置运算符,直接通过完整字段路径更新即可,将$set中的路径从products.$.payments.${id}改为products.${productId}.payments.${id}:
await collection.updateOne( { _id: ObjectId(userId), [`products.${productId}`]: { $exists: true } }, { $set: { [`products.${productId}.payments.${id}`]: { createdAt: new Date(), createdBy: userJWT.userId, }, }, }, { upsert: true } )
额外说明
只有当products是数组类型(如products: [ {...}, {...} ])时,位置运算符$才会生效,用来匹配查询条件中第一个符合的数组元素。当前数据结构下,直接通过productId拼接路径就能精准定位目标子文档。
内容的提问来源于stack exchange,提问作者János
相关产品推荐
相关产品推荐

