MongoDB查询填充的字段 [英] MongoDB query on populated fields
问题描述
我有一些名为活动的模型,我正在查询(使用Mongoose)。他们的模式如下所示:
I have models called "Activities" that I am querying for (using Mongoose). Their schema looks like this:
var activitySchema = new mongoose.Schema({
actor: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: true
},
recipient: {
type: mongoose.Schema.ObjectId,
ref: 'User'
},
timestamp: {
type: Date,
default: Date.now
},
activity: {
type: String,
required: true
},
event: {
type: mongoose.Schema.ObjectId,
ref: 'Event'
},
comment: {
type: mongoose.Schema.ObjectId,
ref: 'Comment'
}
});
当我查询它们时,我正在填充 actor
,收件人
,事件
和评论
字段(所有参考文献)。之后,我还深入填充事件
字段以获取 event.creator
。以下是我的查询代码:
When I query for them, I am populating the actor
, recipient
, event
, and comment
fields (all the references). After that, I also deep-populate the event
field to get event.creator
. Here is my code for the query:
var activityPopulateObj = [
{ path: 'event' },
{ path: 'event.creator' },
{ path: 'comment' },
{ path: 'actor' },
{ path: 'recipient' },
{ path: 'event.creator' }
],
eventPopulateObj = {
path: 'event.creator',
model: User
};
Activity.find({ $or: [{recipient: user._id}, {actor: {$in: user.subscriptions}}, {event: {$in: user.attending}}], actor: { $ne: user._id} })
.sort({ _id: -1 })
.populate(activityPopulateObj)
.exec(function(err, retrievedActivities) {
if(err || !retrievedActivities) {
deferred.reject(new Error("No events found."));
}
else {
User.populate(retrievedActivities, eventPopulateObj, function(err, data){
if(err) {
deferred.reject(err.message);
}
else {
deferred.resolve(retrievedActivities);
}
});
}
});
这已经是一个相对复杂的查询,但我需要做更多。如果它击中 $或
语句中 {actor:{$ in:user.subscriptions}}
的部分,我还需要确保事件
的隐私
字段等于字符串 public
。我尝试使用 $ elemMatch
,但由于事件必须首先填充,我无法查询其任何字段。我还需要在多个其他查询中实现同样的目标。
This is already a relatively complex query, but I need to do even more. If it hits the part of the $or
statement that says {actor: {$in: user.subscriptions}}
, I also need to make sure that the event
's privacy
field is equal to the string public
. I tried using $elemMatch
, but since the event has to be populated first, I couldn't query any of its fields. I need to achieve this same goal in multiple other queries, as well.
我有没有办法像我所描述的那样实现这种进一步的过滤?
Is there any way for me to achieve this further filtering like I have described?
推荐答案
答案是改变您的架构。
你已陷入从使用关系数据库的历史进入文档数据库开发时,许多开发人员面前的陷阱:MongoDB不是关系数据库,不应该被视为一个。
You've fallen into the trap that many devs have before you when coming into document database development from a history of using relational databases: MongoDB is not a relational database and should not be treated like one.
您需要停止考虑外键和完全标准化的数据,而是尽可能保持每个文档的自包含,考虑如何在文档中最好地嵌入相关的相关数据。
You need to stop thinking about foreign keys and perfectly normalized data and instead, keep each document as self-contained as possible, thinking about how to best embed relevant associated data within your documents.
这并不意味着您也无法维护关联。它可能意味着这样的结构,您只需要嵌入必要的详细信息,并在需要时查询完整记录:
This doesn't mean you can't maintain associations as well. It might mean a structure like this, where you embed only necessary details, and query for the full record when needed:
var activitySchema = new mongoose.Schema({
event: {
_id: { type: ObjectId, ref: "Event" },
name: String,
private: String
},
// ... other fields
});
重新思考您的嵌入策略将极大地简化您的查询并保持查询次数至少。 填充
会快速计算您的数量,随着数据集的增长,这很可能会成为一个问题。
Rethinking your embed strategy will greatly simplify your queries and keep the query count to a minimum. populate
will blow your count up quickly, and as your dataset grows this will very likely become a problem.
这篇关于MongoDB查询填充的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!