我正在使用Meteor构建一个简单的消息传递应用程序。我在未读消息中遇到的问题。我想返回一个列表,显示用户名(我不关心这一点,请不要专注于这方面,围绕反应性连接/复合材料等)和来自该用户的最新消息我需要返回的内容因此,在下面的发布功能中,是最新的未读消息,但显然只有每个唯一用户ID中的一个。
要做到这一点我试图在我的发布方法中操纵查找查询的结果,但我不清楚如何操纵文档集而不破坏反应性,正如我在目前所展示的那样下面的代码,这是我到目前为止所得到的:
Meteor.publish('unreadmessages', function() {
if (!this.userId) {
throw new Meteor.Error('denied', 'not-authorized');
}
var messageQuery, messages, userGroupQuery, userGroups;
var self = this;
var user = Meteor.users.findOne(self.userId);
var userIdArr = [self.userId]; // for use where queries require an array
var contacts = user.contacts;
// get groups
userGroupQuery = Groups.find({
$or : [
{ owner : self.userId },
{ members : self.userId }
]
}, { // Projection to only return the _id field
fields : { _id:1 }
}
);
userGroups = _.pluck(userGroupQuery.fetch(), '_id'); // create an array of id's
messages = Messages.find({
$or : [
{
$and : [
{ participant : self.userId },
{ userId : { $in : contacts } },
{ readBy : { $nin : userIdArr } }
]
},
{
$and : [
{ groupId : { $in : userGroups } },
{ readBy : { $nin : userIdArr } }
]
},
]
});
// TODO : also handle groups here
uniqueMessages = _.uniq(messages.fetch(), function(msg) {
return msg.userId;
});
return uniqueMessages; // obviously an array and not a cursor - meteor errors out.
});
我意识到我的下划线功能当然是使用并确实返回一个数组,而不是我需要的反应光标。我知道一个解决方案就是简单地选择消息ID然后在消息上运行另一个.find,但是有没有其他/更好/更有效/更自然的方式返回结果集我正在寻找的游标?
答案 0 :(得分:1)
你可以使用observeChanges并使其成为被动的。在added
上,您可以添加字段。我正在使用这个神奇的套餐:meteor-publish-composite,它可以节省您的时间。
使用分页,否则你不会享受表演。
答案 1 :(得分:0)
以下代码确实发布了一个反应性游标并且是一个可行的解决方案,但我想我的问题的关键在于是否有更好的方法来操纵第二个Messages.find
的结果集仍然发布一个反应光标(我正在考虑光标.forEach或.map,但我不知道如何处理这个问题。)
基本上 - 有更好的方法:
Meteor.publish('unreads', function() {
if (!this.userId) {
throw new Meteor.Error('denied', 'not-authorized');
}
// setup some vars
var messageQuery, messages, userGroupQuery, userGroups, uniqeMsgIds;
var self = this;
var user = Meteor.users.findOne(self.userId);
var userIdArr = [self.userId]; // for use where queries require an array
var contacts = user.contacts;
// get groups
userGroupQuery = Groups.find({
$or : [
{ owner : self.userId },
{ members : self.userId }
]
}, { // Projection to only return the _id field
fields : { _id:1 }
}
);
// create an array of group id's that belong to the user.
userGroups = _.pluck(userGroupQuery.fetch(), '_id');
messages = Messages.find({
$or : [
{ // unread direct messages
$and : [
{ participant : self.userId },
{ userId : { $in : contacts } },
{ readBy : { $nin : userIdArr } }
]
},
{ // unread group messages
$and : [
{ groupId : { $in : userGroups } },
{ readBy : { $nin : userIdArr } }
]
},
]
}, { sort : { // put newest messages first
time : -1
}
});
// returns an array of unique documents based on userId or groupId
uniqueMessages = _.uniq(messages.fetch(), function(msg) {
if (msg.groupId) {
return msg.groupId;
}
return msg.userId;
});
// Get the id's of all the latest unread messages (one per user or group)
uniqeMsgIds = _.pluck(uniqueMessages, '_id');
// finally publish a reactive cursor containing one unread message(latest) for each user/group
return Messages.find({
_id : { $in : uniqeMsgIds };
});
});
答案 2 :(得分:0)
继承人最后的工作代码。这确实返回了一个游标,基本上我正在做的是从多个查询/修改中获取结果并将一组id添加到最终的.find查询中。
Meteor.publish('unreads', function() {
if (!this.userId) {
throw new Meteor.Error('denied', 'not-authorized');
}
// setup some vars
var messageQuery,
messages,
userGroupQuery,
userGroups,
uniqeMsgIds;
var self = this;
var user = Meteor.users.findOne(self.userId);
var userIdArr = [self.userId]; // for use where queries require an array
var contacts = user.contacts;
// get groups
userGroupQuery = Groups.find({
$or : [
{ owner : self.userId },
{ members : self.userId }
]
}, { // Projection to only return the _id field
fields : { _id:1 }
}
);
// create an array of group id's that belong to the user.
userGroups = _.pluck(userGroupQuery.fetch(), '_id');
messages = Messages.find({
$or : [
{ // unread direct messages
$and : [
{ participant : self.userId },
{ userId : { $in : contacts } },
{ readBy : { $nin : userIdArr } }
]
},
{ // unread group messages
$and : [
{ groupId : { $in : userGroups } },
{ readBy : { $nin : userIdArr } }
]
},
]
}, { sort : { // put newest messages first
time : -1
}
});
// returns an array of unique documents based on userId or groupId
uniqueMessages = _.uniq(messages.fetch(), function(msg) {
if (msg.groupId) {
return msg.groupId;
}
return msg.userId;
});
/* Get the id's of all the latest unread messages
(one per user or group) */
uniqeMsgIds = _.pluck(uniqueMessages, '_id');
/* finally publish a reactive cursor containing
one unread message(latest) for each user/group */
return Messages.find({
_id : { $in : uniqeMsgIds }
});
});