我想知道如何查询数据库,以获取满足“store”{name}字段的所有结果,但此“store”保存为“_id”,我使用.populate()获取信息
/**示例:await product.find({store:{name:“specific store”}})*/
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"
}
})
基本上,我想实现的是从DB中提取具有特定'商店'的所有产品,但我仍然无法做到这一点,我感谢任何帮助来解决这个问题,无论是参考还是合适的查询示例,提前感谢
我试过这个:
const p = await Product.find({})
.populate({
path: 'store',
match: { name: { $eq: 'Store1' } },
select: 'name -_id',
})
但它返回整个集合,而不进行过滤,我收到这样的东西:
[{
_id:1,
...
store:null,
...
}, {
_id:2,
...
store:{name:"Store1"},
...
}, {
_id:3,
...
store:{name:"Store2"},
...
}]
2条答案
按热度按时间1mrurvl11#
正如@M.CaglarTUFAN所提到的,你不能根据子文档来过滤父文档。重构模式是一个不错的选择。
但是,如果你无法做到这一点,你可以使用$lookup和$match使用mongodb聚合框架来实现你想要的结果,如下所示:
如果您的产品集合很大(数百万个文档),请记住这将对所有文档执行
$lookup
,因此效率可能很低。但是,如果不重构模式,这是对数据库的最佳单次调用。第二个选项涉及2个数据库查询。
1.从stores集合中获取所需存储的
_id
。1.然后使用该结果查询products集合并填充匹配记录。
dgtucam12#
首先想到的解决方案是使用
Array.filter()
方法手动过滤数据。这就像下面所示的那样简单:正如你所看到的,这可以很好地帮助少量的检索数据,并且很容易实现。但是如果你想在数据库级别上应用这样的过滤器,那么我们需要改变你的产品的模式。因为根据Mongoose文档,不可能在查找时过滤数据。我引用以下理由:
例如,假设你
populate()
一个故事的author
和author
不满足match
。那么故事的author
将是null
。一般来说,没有办法让
populate()
根据故事author
的属性过滤故事。例如,下面的查询不会返回任何结果,即使author
被填充。如果你想按作者的名字过滤文章,你应该使用denormalization。
我建议您阅读MongoDB的官方博客文章。
我们可以应用博客文章中提到的不同类型的反规范化,但我将提供其中一种类型的代码。首先,我们需要更改您的产品架构:
我们没有将
store
字段定义为Store
模型的引用,而是反规范化并添加了id
(进行应用程序级连接)和name
(过滤)字段。之后,我们可以轻松地获取和过滤指定商店名称的产品:这样,我们将始终通过
store.name
字段过滤结果。如果我们想提供id
和name
字段以外的存储数据,我们需要进行应用程序级连接:正如你所看到的,使用反规范化有一些优点和缺点。当你想更新一个商店的名称时,你还需要更新该商店的所有占用产品。这种更新可能是昂贵的。由于这个原因,如果你要对产品进行大量的读取操作(使用商店名称过滤),而对商店进行不频繁的名称更新,那么反规范化是一个很好的选择,那么这是一个很好的解决方案。