在使用mongoose填充文档后,我在通过文档内部的匹配值查询文档时遇到了一些问题。
我的模式如下:
var EmailSchema = new mongoose.Schema({
type: String
});
var UserSchema = new mongoose.Schema({
name: String,
email: [{type:Schema.Types.ObjectId, ref:'Email'}]
});
我想有一个电子邮件类型为“Gmail”的所有用户为例。
以下查询返回空结果:
Users.find({'email.type':'Gmail').populate('email').exec( function(err, users)
{
res.json(users);
});
我不得不在JS中采用如下方式过滤结果:
users = users.filter(function(user)
{
for (var index = 0; index < user.email.length; index++) {
var email = user.email[index];
if(email.type === "Gmail")
{
return true;
}
}
return false;
});
有没有办法直接从 Mongoose 那里查询到这样的东西?
3条答案
按热度按时间mwngjboj1#
@Jason Cust已经解释得很清楚了-在这种情况下,最好的解决方案通常是更改模式,以防止通过存储在单独集合中的文档的属性来查询
Users
。这是我能想到的最好的解决方案,不会强迫你这样做,虽然(因为你在评论中说,你不能)。
我们在这里所做的是只填充
email
的匹配附加查询(.populate()
调用中的match
选项)-否则Users
文档中的email
字段将被设置为null
。剩下的就是返回的
users
数组上的.filter
,就像你最初的问题一样--只是有一个更简单、更通用的检查。8nuwlpux2#
Mongoose的
populate
函数并不直接在Mongo中执行,而是在初始的find
查询返回一组文档之后,populate
将在引用的集合上创建一个find
查询数组,然后执行并将结果合并到原始文档中。(尚未提取,因此为undefined
)来过滤原始结果集。在此用例中,将电子邮件存储为子文档数组而不是单独的集合来实现您想要的功能似乎更合适。此外,作为一种通用的文档存储设计模式,这是将数组存储为子文档有意义的用例之一:有限的尺寸和很少的修改。
正在将架构更新为:
那么下面的查询应该可以工作:
uubf1zoe3#
我找不到任何其他的解决方案,除了使用聚合。这将是更麻烦的,但我们将使用查找。