是否有可能从集合发布具有多个条件字段的项目?

考虑这种情况,我有一个party对象,这个party对象有关于派对,位置,时间,客人等的一些信息字段。它也有一些字段为一些信息字段设置隐私,如showLocation, showGuests等等。这些将隐藏这个信息从没有被邀请的用户。

我怎样才能只发送给客户的“显示”字段为真的字段?

当我发布一个单一的项目,我可以使用这样的事情:(合并不是一个真正的function)

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}) ]; }); 

但是,在发布多个项目时,如何优雅地使用一些条件字段呢?

1)基于Michel Floyds“订阅他们所有! 解决scheme,像这样从发布中返回多个游标:

 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”的字段,并在编辑/创build具有“showX”的项目时填充/清空该字段,然后将该字段包含在字段说明符中而不是真正的“X”字段中。 这个解决scheme是唯一的工作,如果你也想sorting或过滤这些领域,这样你可以在查询和字段说明符中使用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(); }); }); 

这个解决scheme可能是“低层次的”,但是它非常灵活,可以适应不同的需求,甚至涉及到很多领域的复杂条件,而且都在服务器端,所以没有私人数据被发送到客户端。

三个选项:

  1. 在创build集合时定义一个transform函数
  2. 使用服务器上的cursor.map()对每个文档运行callback,并根据您的要求包含/排除字段。 产生的对象是一个数组而不是一个游标,但客户端会很高兴地使用它。
  3. 在服务器端使用cursor.fetch() ,然后使用forEach()处理结果数组

经过进一步的思考,你原来的想法是正确的,但是这里有一个稍微不同的(也可能比较stream行)来思考这个问题。

为每组创build一个出版物并订阅它们!

 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}); }); 

好的是, 即使你的逻辑结果在重叠的出版物,你仍然会得到正确的数据集在客户端。