我想知道如何对数据库进行查询,得出满足“store”{name}字段的所有结果,但是这个“store”是用“_id”保存的,我使用 .populate() 来带来我的信息
/**示例:await Product.find({store:{name:"具体商店"}})*/
const products = await Product.find({ 'store.name' : "Ejemplo1" })
.populate('store', 'name')
方案如下:
const storeSchema = mongoose.Schema({
_id:"it is added automatically by mongoose",
name: String
})
export default model('Store', storeSchema);
const productSchema = mongoose.Schema({
store: {
type: Schema.Types.ObjectId,
ref: "Store"
}
})
基本上我想要实现的是从数据库中提取具有特定“商店”的所有产品,但我仍然无法做到这一点,我感谢任何解决此问题的帮助,无论是参考还是示例合适的查询,提前谢谢
我尝试过这个: const p = 等待 Product.find({}) .填充({ 路径:'商店', 匹配:{ name: { $eq: 'Store1' } }, 选择:'名称-_id', })
但它返回整个集合并且不进行过滤,我收到如下内容: { _id:1, ... 存储:空, ... } { _id:2, ... 商店:{名称:"商店1"}, ... } { _id:3, ... 商店:{名称:“商店2”}, ... }
我想到的第一个解决方案是使用
Array.filter()
方法手动过滤数据。这很简单,如下所示:
const products = await Product.find({}).populate({
path: 'store',
match: { name: { $eq: 'Store1' } },
select: 'name -_id'
});
const productsFiltered = products.filter(
product => product.store !== null
);
如您所见,这对于检索少量数据很有帮助,并且易于实现。但如果您想在数据库级别应用此类过滤器,那么我们需要更改您产品的架构。因为根据 Mongoose 文档 不可能过滤查找数据。我引用以下推理:
例如,假设您
一个故事的populate()
并且author
不满足author
。那么故事的match
将是author
。null
const story = await Story.
findOne({ title: 'Casino Royale' }).
populate({ path: 'author', name: { $ne: 'Ian Fleming' } }).
exec();
story.author; // `null`
一般来说,无法让
根据故事populate()
的属性来过滤故事。例如,以下查询不会返回任何结果,即使填充了author
。author
const story = await Story.
findOne({ 'author.name': 'Ian Fleming' }).
populate('author').
exec();
story; // null
如果您想按作者姓名过滤故事,您应该使用 denormalization。
我建议您阅读 MongoDB 的官方博客文章。
我们可以应用博客文章中提到的不同类型的非规范化,但我将为其中一种类型提供代码。首先我们需要更改您的产品架构:
const productSchema = mongoose.Schema({
store: {
id: Schema.Types.ObjectId,
name: String
}
});
我们没有将
store
字段定义为对 Store
模型的引用,而是反规范化并添加了 id
(用于进行应用程序级连接)和 name
(用于过滤)字段。之后我们就可以轻松获取并过滤指定店铺名称的商品了:
const p = await Product.find({
'store.name': 'Store1'
}, 'name -_id');
这样,我们将始终根据
store.name
字段过滤结果。如果我们想提供 id
和 name
字段以外的存储数据,我们需要进行应用程序级连接:
// Map each product to retrieve only their store ids and filter out to have unique store ids
const storeIds = p
.map(
product => product.store.id
)
.filter(
(value, index, array) => array.indexOf(value) === index
);
// Retrieve stores with given store ids
const stores = await Store.find({ _id: { $in: storeIds } });
// Join stores with each product's store.id
p.forEach(
product => {
product.store = stores.find(store => store._id.toString() == product.store.id.toString())
}
);
正如您所看到的,使用非规范化有一些优点和缺点。当您想要更新商店名称时,您还需要更新该商店的产品中出现的所有内容。此更新可能会很昂贵。因此,如果您要对产品进行大量读取操作(使用商店名称过滤)并且不经常对商店进行名称更新,那么非规范化是一个不错的选择,那么这是一个很好的解决方案。