Javascript 填充猫鼬后查找
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31357745/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find after populate mongoose
提问by Monokh
I'm having some trouble querying a document by values matching inside the document after population by mongoose.
我在通过猫鼬填充后通过文档内部匹配的值查询文档时遇到了一些麻烦。
My schemas are something like this:
我的模式是这样的:
var EmailSchema = new mongoose.Schema({
type: String
});
var UserSchema = new mongoose.Schema({
name: String,
email: [{type:Schema.Types.ObjectId, ref:'Email'}]
});
I would like to have all users which have a email with the type = "Gmail" for example.
例如,我希望所有用户都拥有类型为“Gmail”的电子邮件。
The following query returns empty results:
以下查询返回空结果:
Users.find({'email.type':'Gmail').populate('email').exec( function(err, users)
{
res.json(users);
});
I have had to resort to filtering the results in JS like this:
我不得不像这样在 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;
});
Is there any way to query something like this straight from mongoose?
有没有办法直接从猫鼬查询这样的东西?
回答by bardzusny
@Jason Custexplained it pretty well already - in this situation often the best solution is to alter the schema to prevent querying Users
by properties of documents stored in separate collection.
@Jason Cust已经很好地解释了它 - 在这种情况下,通常最好的解决方案是更改架构以防止Users
通过存储在单独集合中的文档的属性进行查询。
Here's the best solution I can think of that will not force you to do that, though (because you said in the comment that you can't).
不过,这是我能想到的最好的解决方案,它不会强迫你这样做(因为你在评论中说你不能)。
Users.find().populate({
path: 'email',
match: {
type: 'Gmail'
}
}).exec(function(err, users) {
users = users.filter(function(user) {
return user.email; // return only users with email matching 'type: "Gmail"' query
});
});
What we're doing here is populating only email
s matching additional query (match
option in .populate()
call) - otherwise email
field in Users
documents will be set to null
.
我们在这里所做的只是填充email
匹配的附加查询(调用中的match
选项.populate()
) - 否则文档中的email
字段Users
将设置为null
.
All that's left is .filter
on returned users
array, like in your original question - only with much simpler, very generic check. As you can see - either the email
is there or it isn't.
剩下的就是.filter
返回的users
数组,就像在您的原始问题中一样 - 只有更简单,非常通用的检查。如您所见 - 要么email
存在,要么不存在。
回答by Jason Cust
Mongoose's populate
function doesn't execute directly in Mongo. Instead after the initial find
query returns a set a documents, populate
will create an array of individual find
queries on the referenced collection to execute and then merge the results back into the original documents. So essentially your find
query is attempting to use a property of the referenced document (which hasn't been fetched yet and therefore is undefined
) to filter the original result set.
Mongoose 的populate
函数不直接在 Mongo 中执行。相反,在初始find
查询返回一组文档后,populate
将find
在引用的集合上创建一组单独的查询来执行,然后将结果合并回原始文档。因此,本质上您的find
查询正在尝试使用引用文档的属性(尚未获取,因此是undefined
)来过滤原始结果集。
In this use case it seems more appropriate to store emails as a subdocument array rather than a separate collection to achieve what you want to do. Also, as a general document store design pattern this is one of the use cases that makes sense to store an array as a subdocument: limited size and very few modifications.
在这个用例中,将电子邮件存储为子文档数组而不是单独的集合来实现您想要做的事情似乎更合适。此外,作为通用文档存储设计模式,这是将数组存储为子文档的用例之一:有限的大小和很少的修改。
Updating your schema to:
将您的架构更新为:
var EmailSchema = new mongoose.Schema({
type: String
});
var UserSchema = new mongoose.Schema({
name: String,
email: [EmailSchema]
});
Then the following query should work:
那么下面的查询应该可以工作:
Users.find({'email.type':'Gmail').exec(function(err, users) {
res.json(users);
});