在MongoDB的查询中,$elemMatch不会将条件视为逻辑与运算符
我基于属性模式设计了一个产品模式。目标是让用户能够使用不同参数查询数据。
产品模式:
const AttributeSchema = new Schema({
k: { type: String, required: true },
v: { type: Schema.Types.Mixed, required: true },
}, { _id: false });
const ProductSchema = new Schema({
title: { type: String, required: true },
category:{ type: String, required: true },
specs: [AttributeSchema] // Applying the Attribute Pattern here
});
ProductSchema.index({ "specs.k": 1, "specs.v": 1 });
const Product=new model('Product',ProductSchema);
module.exports=Product;
产品路由:
router.get('/api/product', async (req, res) => {
const { key, value } = req.query;
const products = await Product.find({
specs: { $elemMatch: { k: key, v: value } }
});
});
MongoDB中的示例存储数据
{
"title": "shoe1",
"category": "shoe",
"specs": [
{
"k": "color",
"v": "red"
},
{
"k": "brand",
"v": "nike"
}
],
},
{
"title": "shoe2",
"category": "shoe",
"specs": [
{
"k": "color",
"v": "red"
},
{
"k": "brand",
"v": "adidas"
}
],
}
例如,用户的查询如下:
/api/product?key=brand&value=adidas&key=color&value=red
查询返回与至少一个条件匹配的所有文档。它本应只返回阿迪达斯的鞋款,但由于与条件 color = "red" 匹配,耐克的鞋款也被返回。看起来查询在对 $elemMatch 采用了“或”条件,而不是“且/并且”条件。
下面的代码通过使用 "$and" 运算符来解决这个问题,但我不想在代码中指定任何属性、搜索参数和条件,因为它应该在用户执行查询时由查询参数动态指定。
临时解决方案:
const products = await Product.find( { $and: [
{ specs : { $elemMatch : { k: "brand", v: "adidas" } } },
{ specs : { $elemMatch : { k: "color", v: "red" } } }
]});
感谢你的帮助。
解决方案
问题出在查询构造上。这段代码适用于单个键/值对,但当传入多个 key 和 value 参数时,req.query.key 和 req.query.value 将变成数组。一个 $elemMatch 不能匹配 specs 数组中的多种不同对象。你需要为每个键/值对构建一个 $elemMatch,并使用 $and 将它们组合起来。
router.get('/api/product', async (req, res) => {
const keys = Array.isArray(req.query.key) ? req.query.key : [req.query.key];
const values = Array.isArray(req.query.value) ? req.query.value : [req.query.value];
const products = await Product.find({
$and: keys.map((k, i) => ({
specs: {
$elemMatch: {
k: k,
v: values[i]
}
}
}))
});
res.json(products);
});
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。