我试图从购物车集合的项目数组中查找(并更新)特定对象。购物车文档网看起来像这样
{
_id: ObjectId("661fb9ddc2b236ae8703ba92"),
display_id: '38bd6126-02a1-47b9-b567-00aaf2eb076f',
user_id: ObjectId("661137f22a31832ceb92ddbc"),
items: [
{
product_id: ObjectId("6622376051d5886f39ac7365"),
size: ObjectId("660d444d0d7716ee24129675"),
qty: 3
},
{
product_id: ObjectId("662214f8cc5306f999369e99"),
size: ObjectId("660d444d0d7716ee24129675"),
qty: 2
},
{
product_id: ObjectId("662214f8cc5306f999369e99"),
size: ObjectId("660d444d0d7716ee24129674"),
qty: 2
}
],
__v: 4
}
我试图运行的查询是
db.carts.find({user_id: new ObjectId("661137f22a31832ceb92ddbc"), "items.product_id": new ObjectId("662214f8cc5306f999369e99"), "items.size":new ObjectId("660d444d0d7716ee24129675")}, {"items.$":1})
或者在猫鼬中
const doc = await Cart.findOne({
user_id: user_id,
"items.product_id": product_id,
"items.size": oldSize
},{"items.$":1})
理想情况下它应该返回这个对象:
{
product_id: ObjectId("662214f8cc5306f999369e99"),
size: ObjectId("660d444d0d7716ee24129675"),
qty: 2
}
但它返回这个:
{
product_id: ObjectId("6622376051d5886f39ac7365"),
size: ObjectId("660d444d0d7716ee24129675"),
qty: 3
},
请告诉我我做错了什么。
使用子文档时查询可能会令人困惑。对于你当前的查询,它实际上是以 AND 的方式查询 3 件事:
user_id: 661137f22a31832ceb92ddbc
items
的文档product_id: 662214f8cc5306f999369e99
items
的文档size: 660d444d0d7716ee24129675
请注意,对于#2 和#3,它们不需要是相同的子文档。换句话说,也可以返回具有 2 个仅满足 #2 或 #3 的单独子文档的文档。
对于您的情况,您的文档具有同时满足 #2 和 #3 的项目,但您的投影子句(即
{"items.$":1}
)只是要求返回数组中的第一个元素。那么,您可以做什么来确保 #2 和 #3 匹配相同的子文档?您可以使用
$elemMatch
。通过这种方式,您还可以$
在投影子句中使用位置运算符。蒙戈游乐场
事实上,如果您发现自己
items
最常工作的级别,建议您将items
条目“扁平化”到单独的文档中,如下所示。您可能会获得一些好处,例如更简单的查询和索引带来的性能提升。蒙戈游乐场