我的Meteor项目中有以下数据结构:
- 具有属于用户(作者)的一组list-id的用户
- 实际包含列表中所有数据的列表
现在我正在尝试将用户的所有列表发布到客户端。这是一个简单的例子:
if (Meteor.isClient) {
Lists = new Meteor.Collection("lists");
Deps.autorun(function() {
Meteor.subscribe("lists");
});
Template.hello.greeting = function () {
return "Test";
};
Template.hello.events({
'click input' : function () {
if (typeof console !== 'undefined')
console.log(Lists.find());
}
});
}
if (Meteor.isServer) {
Lists = new Meteor.Collection("lists");
Meteor.startup(function () {
if ( Meteor.users.find().count() === 0 ) {
Accounts.createUser({ //create new user
username: 'test',
email: 'test@test.com',
password: 'test'
});
//add list to Lists and id of the list to user
var user = Meteor.users.findOne({'emails.address' : 'test@test.com', username : 'test'});
var listid = new Meteor.Collection.ObjectID().valueOf();
Meteor.users.update(user._id, {$addToSet : {lists : listid}});
Lists.insert({_id : listid, data : 'content'});
}
});
Meteor.publish("lists", function(){
var UserListIdsCursor = Meteor.users.find({_id: this.userId}, {limit: 1}).lists;
if(UserListIdsCursor!=undefined){
var UserListIds = UserListIdsCursor.fetch();
return Lists.find({_id : { $in : UserListIds}});
}
});
Meteor.publish("mylists", function(){
return Meteor.users.find({_id: this.userId}, {limit: 1}).lists;
});
//at the moment everything is allowed
Lists.allow({
insert : function(userID)
{
return true;
},
update : function(userID)
{
return true;
},
remove : function(userID)
{
return true;
}
});
}
但是发布列表无法正常运行。任何想法如何解决这一问题?我也发布“mylists”以保证用户可以访问“list”字段。
答案 0 :(得分:3)
Lists = new Meteor.Collection('lists');
if (Meteor.isClient) {
Tracker.autorun(function() {
if (Meteor.userId()) {
Meteor.subscribe('lists');
Meteor.subscribe('myLists');
}
});
}
if (Meteor.isServer) {
Meteor.startup(function() {
if (Meteor.users.find().count() === 0) {
var user = {
username: 'test',
email: 'test@test.com',
password: 'test'
};
var userId = Accounts.createUser(user);
var listId = Lists.insert({data: 'content'});
Meteor.users.update(userId, {
$addToSet: {lists: listId}
});
}
});
Meteor.publish('lists', function() {
check(this.userId, String);
var lists = Meteor.users.findOne(this.userId).lists;
return Lists.find({_id: {$in: lists}});
});
Meteor.publish('myLists', function() {
check(this.userId, String);
return Meteor.users.find(this.userId, {fields: {lists: 1}});
});
}
Lists
集合(无需声明两次)。lists
发布功能。myLists
发布功能。发布需要返回游标,游标数组或虚假值。您无法返回一组id(此代码无论如何都无法访问,因为您需要执行fetch
或findOne
)。重要说明 - 这将发布另一个具有lists
字段的用户文档。在客户端上,它将与现有用户文档合并,因此只有登录用户才能拥有lists
。如果您希望所有用户都在客户端上拥有该字段,那么我建议您只将其添加到用户配置文件中。警告:在编写本文时,如果附加了其他列表项,则不会发布它们,因为lists
发布功能只会在用户登录时重新运行。要使其正常工作,您需要reactive join
答案 1 :(得分:2)
这里真正的问题是架构。
不要存储“此用户拥有这些列表”,例如,针对用户集合。存储“此列表归该用户所有”
通过更改您的示例以在每个ownerId
上添加List
字段,然后发布变得容易 - 并且被动反应。
它还消除了对myLists
发布的需求,因为您只需查询客户端的列表。
修改:如果您的架构在每个userIds
上都包含List
字段,那么对于非所有者来说,发布也是微不足道的。
Lists = new Meteor.Collection('lists');
if (Meteor.isClient) {
Deps.autorun(function() {
if (Meteor.userId()) {
Meteor.subscribe('lists.owner');
Meteor.subscribe('lists.user');
}
});
}
if (Meteor.isServer) {
Lists._ensureIndex('userIds');
Lists._ensureIndex('ownerId');
Meteor.startup(function() {
if (Meteor.users.find().count() === 0) {
var user = {
username: 'test',
email: 'test@test.com',
password: 'test'
};
var userId = Accounts.createUser(user);
var listId = Lists.insert({data: 'content', ownerId: userId});
}
});
//XX- Oplog tailing in 0.7 doesn't support $ operators - split into two publications -
// or change the schema to include the ownerId in the userIds list
Meteor.publish('lists.user', function() {
check(this.userId, String);
return Lists.find({userIds: this.userId});
});
Meteor.publish('lists.owner', function() {
check(this.userId, String);
return Lists.find({ownerId: this.userId});
});
}
答案 2 :(得分:0)
Meteor.users.find()返回许多项目的游标,但您尝试使用
访问.lists
Meteor.users.find({_id: this.userId}, {limit: 1}).lists;
您需要改为使用findOne。
Meteor.users.findOne({_id: this.userId}).lists;
此外,您在存储在用户集合中的阵列上运行.fetch()
。如果这是._id字段数组,则不需要提取。
你不能在你的第二次发布中做.lists
,因为它必须检查一个光标列出客户端,所以只能使用Meteor.users.find(..),因为你只能发布游标