Mongodb Meteor发布集合中字段的不同值
我被困在《流星》中一个非常简单的场景中:Mongodb Meteor发布集合中字段的不同值,mongodb,meteor,Mongodb,Meteor,我被困在《流星》中一个非常简单的场景中: 我有一个包含许多字段的庞大集合,其中一些包含相当多的文本 我想创建一个搜索该集合的页面 集合中每个项目的字段之一是“类别” 我想让用户能够按类别进行筛选 为此,我需要只发布集合中category字段的不同值 我想不出一个方法来做到这一点,而不公布整个收藏,这需要花费太长的时间。我如何只发布不同的类别,并使用它们填充下拉列表 额外的问题和一些相关的问题:如何在不发布整个集合的情况下发布集合中所有项目的计数?这些模式可能会对您有所帮助。以下是发布计数的出
- 我有一个包含许多字段的庞大集合,其中一些包含相当多的文本
- 我想创建一个搜索该集合的页面
- 集合中每个项目的字段之一是“类别”
- 我想让用户能够按类别进行筛选
- 为此,我需要只发布集合中category字段的不同值
额外的问题和一些相关的问题:如何在不发布整个集合的情况下发布集合中所有项目的计数?这些模式可能会对您有所帮助。以下是发布计数的出版物:
/*****************************************************************************/
/* 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();
});
这些模式可能对您有所帮助。以下是发布计数的出版物:
/*****************************************************************************/
/* 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();
});
一个很好的起点是将
类别规范化为一个单独的数据库集合
但是,假设这不可能或不实用,最好(尽管不完美)的解决方案是发布集合的两个单独版本,一个只返回整个集合的类别
字段,另一个只返回选定类别集合的所有字段。这将如下所示:
// 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游标组装类别数组客户端(例如,通过使用下划线的u.pull和u.uniq方法获取类别并删除任何DUP)。但是数据集会小得多,因为您现在只处理单字段文档
(请注意,理想情况下,您希望在publish函数中使用Mongo的distinct()方法仅发布不同的类别,但这不可能直接发布,因为它会返回无法发布的数组)
但是,假设这不可能或不实用,最好(尽管不完美)的解决方案是发布集合的两个单独版本,一个只返回整个集合的类别
字段,另一个只返回选定类别集合的所有字段。这将如下所示:
// 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游标组装类别数组客户端(例如,通过使用下划线的u.pull和u.uniq方法获取类别并删除任何DUP)。但是数据集会小得多,因为您现在只处理单字段文档
(请注意,理想情况下,您希望在publish函数中使用Mongo的distinct()方法仅发布不同的类别,但这是不可能的,因为它会返回一个无法发布的数组)。您可以使用内部this.\u 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();
};
您可以使用内部this.\u 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();
};
回复:奖励问题,发布计数:看看陨石包发布计数。我想这正是你想要的。Re:奖金问题,出版计数:看看陨石包的出版计数。我想这正是你想要的。我还没有在Meteor上测试过它,根据回复,我对它是否有效表示怀疑,但使用mongoDB distinct就可以了
我还没有在Meteor上测试过它,根据回复,我怀疑它是否有效,但使用mongoDB distinct就可以了
谢谢,但这似乎很复杂。我不确定所有的userId/角色都和我的问题有什么关系。谢谢,但这看起来很复杂。不确定所有的userId/角色与我的问题有什么关系。没有真正解决问题的具体问题。如何在不公布整个收藏的情况下做到这一点?并没有真正解决问题的具体问题。如何在不发布整个收藏的情况下做到这一点?你不能像在Meteor中那样使用mongo distinct。Mongo驱动程序不支持它。有一些软件包添加了这一功能,但我相信它们只是在获取的数组上使用\uuq.uniq
技巧。我不相信目前有一个好的方法可以得到清晰的反应结果。你不能像在Meteor中那样使用mongo distinct。Mongo驱动程序不支持它。有一些软件包添加了这一功能,但我相信它们只是在获取的数组上使用\uuq.uniq
技巧。我不相信目前有一种好的方法可以得到明显的反应性结果。