考虑这种情况,我有一个派对对象,这个派对对象有一些关于派对,位置,时间,嘉宾等的信息字段。 它还有一些字段可以为某些信息字段设置隐私,例如showLocation,showGuests等。 这些将隐藏未被邀请的用户的此信息。
我怎样才能向客户端发送"显示"的字段。领域是真的吗?
当我发布单个项目时,我可以使用以下内容:(合并不是真正的功能)
Meteor.publish("party", function (_id) {
var party = Parties.findOne({_id: _id});
var fields = merge(
{name: 1, title: 1, creatorUserId: 1},
(party.showLocationAndDate ? {location: 1, date: 1} : null),
(party.showGuests ? {guests: 1} : null)
);
return Parties.find({_id: _id}, {fields: fields});
});
当我发布多个项目但只有一个条件时,我可以使用以下内容:
Meteor.publish("parties", function () {
var fieldsWithLocation = {
name: 1,
title: 1,
creatorUserId: 1,
location: 1
};
var fieldsWithoutLocation = {
name: 1,
title: 1,
creatorUserId: 1
};
//return multiple cursors
return [
Parties.find({showLocation: true}, {fields: fieldsWithLocation}),
Parties.find({showLocation: false}, {fields: fieldsWithoutLocation})
];
});
但是,在发布多个项目时,如何使用几个条件字段优雅地完成此操作?
答案 0 :(得分:1)
1)基于Michel Floyds“全部订阅!”解决方案,从这样的发布中返回多个游标:
return [
Identities.find(query, options),
Identities.find(merge(query, {showLocation: true}), {fields: {location: 1}}),
Identities.find(merge(query, {showGuests: true}), {fields: {guests: 1}}),
];
2)添加名为“publicX”的第三个字段,并在编辑/创建带有“showX”的项目时填充/清空该字段,然后包括 字段说明符中的此字段,而不是真正的“X”字段。 如果您还希望按这些字段进行排序或过滤,则此解决方案是唯一有效的方法,这样您就可以在查询和字段说明符中使用publicX而不是“X”。
3)自己使用观察并更严格地控制结果:
Meteor.publish("activeParties", function () {
var self = this;
var query = {active: true};
//Observe the collection query for acivity
var handle = Parties.find(query).observeChanges({
//Runs one time first on all matching documents and sends them to the client
//also runs each time a document is added
added: function (id, fields) {
if(!fields.showLocation) { //User choose to hide field
delete fields.location; //Remove field from document
}
//etc.. add as many more conditional fields here as wanted
self.added("Parties", id, fields ); //Sends the new document to the client
},
//Runs each time a matching document was updated, getting the id and only the changed fields
changed: function (id, fields) {
if("showLocation" in fields) { //check if showLocation was updated
if(!fields.showLocation) {
fields.location = undefined; //marks field for deletion on client
}
else {
//Needed because "fields" only contains the changed fields, so we need to pull the actual value from the DB
//You should probably test here that the doc still exist first
fields.location = Parties.findOne({_id: id}, {location: 1}).location;
}
}
//etc.. add as many more conditional fields here as wanted
self.changed("Parties", id, fields ); //Sends the changes to the client
},
//Runs each time a document is removed
removed: function (id) {
self.removed("Parties", id );
},
});
self.ready(); //Tell the client that all the data was published
//Runs when the client unsubscribes from this publish
self.onStop(function () {
//Stops observing the collection
//important because otherwise it would continue observing even after unsubscribing
handle.stop();
});
});
这个解决方案可能是“低级别”,但它非常灵活,可以适应不同的需求,甚至涉及许多领域的复杂条件,所有这些都在服务器端,因此不会向客户端发送私人数据。
答案 1 :(得分:0)
三个选项:
transform
功能
forEach()
答案 2 :(得分:0)
经过进一步的反思,你最初的想法是在正确的轨道上,但这里有一个稍微不同(可能更流行)的方式来思考这个问题。
为每个集创建一个发布并订阅它们全部!
Meteor.publish('partiesWithLocations',function(){
... unique logic for this publication
return Parties.find({showLocation: true}, {fields: fieldsWithLocation});
});
Meteor.publish('partiesWithoutLocations',function(){
... unique logic for this publication
return Parties.find({showLocation: false}, {fields: fieldsWithoutLocation});
});
好消息是即使您的逻辑导致重叠的出版物,您仍然可以在客户端中获得正确的数据集。