流星在集合中发布不同的字段值

时间:2014-06-26 00:21:41

标签: mongodb meteor

我在Meteor中遇到了一个非常简单的场景:

  • 我收集了很多字段,其中一些字段包含很多字段。

  • 我想创建一个搜索该集合的页面。

  • 该集合中每件商品的其中一个字段是"类别"。

  • 我想让用户按该类别进行过滤。

  • 为此,我需要只发布集合中类别字段的不同值。

我无法找到一种方法来做到这一点,而不会发布太长时间的整个集合。如何只发布不同的类别并使用它们来填充下拉列表?

奖金问题并且有些相关:如何在不发布整个集合的情况下发布集合中所有项目的计数?

5 个答案:

答案 0 :(得分:1)

使这更容易的一个好的起点是将categories规范化为单独的数据库集合。

然而,假设这是不可能或不实际的,最好的(虽然不完美)解决方案是发布集合的两个单独版本,一个只返回整个集合的categories字段,另一个返回所有仅适用于所选类别的集合的字段。这看起来如下:

// SERVER
Meteor.startup(function(){

  Meteor.publish('allThings', function() {

    // return only id and categories field for all your things 
    return Things.find({}, {fields: {categories: 1}});

  });

  Meteor.publish('thingsByCategory', function(category) {

    // return all fields for things having the selected category
    // you can then subscribe via something like a client-side Session variable
    // e.g., Meteor.subscribe("thingsByCategory", Session.get("category"));

    return Things.find({category: category});
  });
});

请注意,您仍然需要从Things光标组装客户端类别数组(例如,通过使用下划线的_.pluck和_.uniq方法来获取类别并删除任何重复项)。但是,由于您现在只使用单字段文档,因此数据集会小得多。

(注意,理想情况下,您希望在发布函数中使用Mongo的distinct()方法仅发布不同的类别,但这不可能直接,因为它返回一个无法发布的数组)。

答案 1 :(得分:0)

您可以使用内部this._documents.collectionName仅将新类别发送到客户端。跟踪要删除的类别会变得有点难看,因此您最终可能最终会维护单独的“类别”集合。

示例:

Meteor.publish( 'categories', function(){
  var self = this;
  largeCollection.find({},{fields: {category: 1}).observeChanges({
    added: function( id, doc ){
      if( ! self._documents.categories[ doc.category ] ) 
        self.added( 'categories', doc.category, {category: doc.category});         
    },
    removed: function(){
      _.keys( self._documents.categories ).forEach( category ){
        if ( largeCollection.find({category: category},{limit: 1}).count() === 0 )
          self.removed( 'categories', category );
      }
    }
  });

  self.ready();    
};

答案 2 :(得分:0)

Re:奖金问题,发布计数:看看陨石包发布计数。我认为那就是你想要的。

答案 3 :(得分:-1)

这些模式可能对您有所帮助。这是一份发布计数的出版物:

/*****************************************************************************/
/* Counts Publish Function
/*****************************************************************************/

// server: publish the current size of a collection
Meteor.publish("countsByProject", function (arguments) {
  var self = this;

    if (this.userId) {
        var roles = Meteor.users.findOne({_id : this.userId}).roles;
        if ( _.contains(roles, arguments.projectId) ) {

              //check(arguments.video_id, Integer);



              // observeChanges only returns after the initial `added` callbacks
              // have run. Until then, we don't want to send a lot of
              // `self.changed()` messages - hence tracking the
              // `initializing` state.

              Videos.find({'projectId': arguments.projectId}).forEach(function (video) {
                  var count = 0;
                  var initializing = true;
                  var video_id = video.video_id;
                  var handle = Observations.find({video_id: video_id}).observeChanges({
                    added: function (id) {
                      //console.log(video._id);
                      count++;
                      if (!initializing)
                        self.changed("counts", video_id, {'video_id': video_id, 'observations': count});
                    },
                    removed: function (id) {
                      count--;
                      self.changed("counts", video_id, {'video_id': video_id, 'observations': count});
                    }
                    // don't care about changed
                  });



                  // Instead, we'll send one `self.added()` message right after
                  // observeChanges has returned, and mark the subscription as
                  // ready.
                  initializing = false;
                  self.added("counts", video_id, {'video_id': video_id, 'observations': count});
                  self.ready();

                  // Stop observing the cursor when client unsubs.
                  // Stopping a subscription automatically takes
                  // care of sending the client any removed messages.
                  self.onStop(function () {
                    handle.stop();
                  });


              }); // Videos forEach


        } //if _.contains
    } // if userId

  return this.ready();  

});

这是一个从特定领域创建新集合的人:

/*****************************************************************************/
/* Tags Publish Functions
/*****************************************************************************/

// server: publish the current size of a collection
Meteor.publish("tags", function (arguments) {
  var self = this;

    if (this.userId) {
        var roles = Meteor.users.findOne({_id : this.userId}).roles;
        if ( _.contains(roles, arguments.projectId) ) {

                var observations, tags, initializing, projectId;
                initializing = true;
                projectId = arguments.projectId;
                observations = Observations.find({'projectId' : projectId}, {fields: {tags: 1}}).fetch();
                tags = _.pluck(observations, 'tags');
                tags = _.flatten(tags);
                tags = _.uniq(tags);

                var handle = Observations.find({'projectId': projectId}, {fields : {'tags' : 1}}).observeChanges({
                    added: function (id, fields) {
                      if (!initializing) {
                        tags = _.union(tags, fields.tags);
                        self.changed("tags", projectId, {'projectId': projectId, 'tags': tags});
                      }
                    },
                    removed: function (id) {
                      self.changed("tags", projectId, {'projectId': projectId, 'tags': tags});
                    }
                });

                initializing = false;
                self.added("tags", projectId,  {'projectId': projectId, 'tags': tags});
                self.ready();

                self.onStop(function () {
                    handle.stop();
                });

        } //if _.contains
    } // if userId

  return self.ready();  

});

答案 4 :(得分:-1)

我没有在Meteor上测试它,根据回复,我对它会起作用持怀疑态度,但使用mongoDB distinct会有所帮助。

http://docs.mongodb.org/manual/reference/method/db.collection.distinct/