在 Meteor 中,如何将查找查询的处理结果发布为游标?
In Meteor how can I publish processed results of a find query as a cursor?
我正在使用 Meteor 构建一个简单的消息传递应用程序。我在 未读消息 中纠结的部分。我想要 return 一个列表,显示 用户名 (我不关心这个,请不要关注这方面,围绕反应式连接/复合等) 来自该用户的最新消息 我需要return 因此,在下面的发布功能中,是最新的未读消息,但是 显然每个唯一用户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.
});
我意识到我的下划线函数当然是在使用,而且确实是 returning,一个数组而不是我需要的反应式游标。我知道一个解决方案是简单地提取消息 ID,然后在消息上运行另一个 .find,但是是否有另一种/更好/更有效/更自然的方法来 return 带有我正在寻找的结果集的游标为了?
您可以使用observeChanges and makes this reactive. On the added
, you can add fields. I'm using this amazing package: meteor-publish-composite,它可以节省您的时间。
使用分页,否则性能不佳
下面的代码确实发布了一个反应式游标,是一个可行的解决方案,但我想我的问题的症结在于是否有更好的方法来操作倒数第二个 Messages.find
的结果集仍然发布一个反应式游标(我正在考虑 cursor.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 };
});
});
这是最终的工作代码。这确实 return 一个游标,因为基本上我正在做的是从多个查询/修改中获取结果并将一组 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 }
});
});
我正在使用 Meteor 构建一个简单的消息传递应用程序。我在 未读消息 中纠结的部分。我想要 return 一个列表,显示 用户名 (我不关心这个,请不要关注这方面,围绕反应式连接/复合等) 来自该用户的最新消息 我需要return 因此,在下面的发布功能中,是最新的未读消息,但是 显然每个唯一用户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.
});
我意识到我的下划线函数当然是在使用,而且确实是 returning,一个数组而不是我需要的反应式游标。我知道一个解决方案是简单地提取消息 ID,然后在消息上运行另一个 .find,但是是否有另一种/更好/更有效/更自然的方法来 return 带有我正在寻找的结果集的游标为了?
您可以使用observeChanges and makes this reactive. On the added
, you can add fields. I'm using this amazing package: meteor-publish-composite,它可以节省您的时间。
使用分页,否则性能不佳
下面的代码确实发布了一个反应式游标,是一个可行的解决方案,但我想我的问题的症结在于是否有更好的方法来操作倒数第二个 Messages.find
的结果集仍然发布一个反应式游标(我正在考虑 cursor.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 };
});
});
这是最终的工作代码。这确实 return 一个游标,因为基本上我正在做的是从多个查询/修改中获取结果并将一组 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 }
});
});