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

时间:2015-05-29 15:19:58

标签: javascript node.js mongodb meteor

考虑这种情况,我有一个派对对象,这个派对对象有一些关于派对,位置,时间,嘉宾等的信息字段。 它还有一些字段可以为某些信息字段设置隐私,例如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})
        ];
});

但是,在发布多个项目时,如何使用几个条件字段优雅地完成此操作?

3 个答案:

答案 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)

三个选项:

  1. 在您create your collection
  2. 时定义transform功能
  3. 使用服务器上的cursor.map()在每个文档上运行回调,并根据您的要求包含/排除字段。生成的对象是一个数组而不是一个游标,但客户端会很乐意使用它。
  4. 在服务器端使用cursor.fetch(),然后使用forEach()
  5. 处理生成的数组

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

好消息是即使您的逻辑导致重叠的出版物,您仍然可以在客户端中获得正确的数据集。