从多个MongoDB集合中查找带有限制的文档,并使用Mongoose作为返回sorting列表

如果我有不同types的文档,每个文档都在自己的集合中,是否有一种方法可以search所有集合中的文章,并将它们作为按照date戳记sorting的单个列表进行返回?

此外,我需要:

  • 能够从所有collections中总共确定我需要的post数量
  • 这些post应该按照相同的标准来sorting – 这意味着post的数量将与每个collections不同
  • 为了能够开始收集抵消(例如,从第201号邮件开始,给我100个职位)。

如果我将所有文档保存在同一个集合中,这个任务将会非常简单,但是也需要一个dynamic的,基本上没有logging的模式,因为每个文档都会有很大的不同,除了一些参数,如date。

那么,是否有办法将我的文档保存在定义好的模式中,每个文档都在不同的集合中,但是仍然能够完成上述过程?

为了论证的缘故,下面是模式如何分解:

var InstagramPostSchema = new Schema({ date: Date, imageUrl: String, ... }) var TwitterPostSchema = new Schema({ date: Date, message: String, ... }) 

如果我做了一个普遍的模式,它可能是这样的:

 var SocialPostSchema = new Schema({ date: Date, type: String, postData: {} }) 

什么是这样做的首选方式?

理想的方法是,如果我可以编写从共同的基本模式inheritance的独立模式,但我不熟悉Mongoose和MongoDB,知道是否有本地的方式来做到这一点。

有一个很好的方法来做到这一点,这也是一个更好的,有一些改善你的最终build议,这是使用鉴别器。

基本的想法是,有一个基本的模式具有共同的属性,甚至没有任何属性,你要从中定义你的主要集合。 然后每个其他架构inheritance和共享相同的集合。

作为一个基本的示范:

 var async = require('async'), util = require('util'), mongoose = require('mongoose'), Schema = mongoose.Schema; mongoose.connect('mongodb://localhost/test'); function BaseSchema() { Schema.apply(this,arguments); this.add({ date: { type: Date, default: Date.now }, name: { type: String, required: true } }); } util.inherits(BaseSchema,Schema); var socialPostSchema = new BaseSchema(); var instagramPostSchema = new BaseSchema({ imageUrl: { type: String, required: true } }); var twitterPostSchema = new BaseSchema({ message: { type: String, required: true } }); var SocialPost = mongoose.model('SocialPost', socialPostSchema ), InstagramPost = SocialPost.discriminator( 'InstagramPost', instagramPostSchema ), TwitterPost = SocialPost.discriminator( 'TwitterPost', twitterPostSchema ); async.series( [ function(callback) { SocialPost.remove({},callback); }, function(callback) { InstagramPost.create({ name: 'My instagram pic', imageUrl: '/myphoto.png' },callback); }, function(callback) { setTimeout( function() { TwitterPost.create({ name: "My tweet", message: "ham and cheese panini #livingthedream" },callback); }, 1000 ); }, function(callback) { SocialPost.find({}).sort({ "date": -1 }).exec(callback); } ], function(err,results) { if (err) throw err; results.shift(); console.dir(results); mongoose.disconnect(); } ); 

输出:

 [ { __v: 0, name: 'My instagram pic', imageUrl: '/myphoto.png', __t: 'InstagramPost', date: Wed Aug 19 2015 22:53:23 GMT+1000 (AEST), _id: 55d47c43122e5fe5063e01bc }, { __v: 0, name: 'My tweet', message: 'ham and cheese panini #livingthedream', __t: 'TwitterPost', date: Wed Aug 19 2015 22:53:24 GMT+1000 (AEST), _id: 55d47c44122e5fe5063e01bd }, [ { _id: 55d47c44122e5fe5063e01bd, name: 'My tweet', message: 'ham and cheese panini #livingthedream', __v: 0, __t: 'TwitterPost', date: Wed Aug 19 2015 22:53:24 GMT+1000 (AEST) }, { _id: 55d47c43122e5fe5063e01bc, name: 'My instagram pic', imageUrl: '/myphoto.png', __v: 0, __t: 'InstagramPost', date: Wed Aug 19 2015 22:53:23 GMT+1000 (AEST) } ] ] 

所以要注意的是,即使我们定义了单独的模型,甚至是单独的模式,所有的项目实际上都在同一个集合中。 作为鉴别器的一部分,每个存储的文档都有一个描述它的types的__t字段。

所以这里真正好的东西是:

  • 您可以将所有内容存储在一个集合中,并一起查询所有对象

  • 您可以为每个模式分离validation规则和/或在“基础”中定义事物,因此不需要多次写出validation规则。

  • 这些对象通过附加的模式“爆炸”到它们自己的类定义中,以便为每个types定义模型。 这包括任何附加的方法。 因此,当您创build或检索数据时,这些是第一类对象。

  • 如果您只想使用“TwitterPost”这样的特定types,那么只需使用该模型,使用该模型“自动”就可以从执行的任何查询操作中自动滤除除“Twitter”post以外的任何内容。

将事物保存在一个集合中是非常有意义的,特别是如果您想要根据不同types的信息尝试聚合数据。

谨慎的一句话是,尽pipe使用这种模式你可以有完全不同的对象,但是通用的做法是明智的。 这在查询或汇总不同types时特别有用。

所以在可能的情况下,尝试将“传统导入”数据转换为更常见的字段格式,并保留每个对象types真正需要的唯一属性。


至于你的问题的第一部分,你想用不同的限制来查询“每个集合”,然后对每个集合的整体结果进行sorting,那么你也可以这样做。

有各种各样的技术,但保持在MongoDBforms,有你用来存储组合的结果,并“sorting”他们的nedb 。 所有这些都是以你习惯的方式完成的:

 var async = require('async'), util = require('util'), mongoose = require('mongoose'), DataStore = require('nedb'), Schema = mongoose.Schema; mongoose.connect('mongodb://localhost/test'); function BaseSchema() { Schema.apply(this,arguments); this.add({ date: { type: Date, default: Date.now }, name: { type: String, required: true } }); } util.inherits(BaseSchema,Schema); var socialPostSchema = new BaseSchema(); var instagramPostSchema = new BaseSchema({ imageUrl: { type: String, required: true } }); var twitterPostSchema = new BaseSchema({ message: { type: String, required: true } }); var SocialPost = mongoose.model('SocialPost', socialPostSchema ), InstagramPost = SocialPost.discriminator( 'InstagramPost', instagramPostSchema ), TwitterPost = SocialPost.discriminator( 'TwitterPost', twitterPostSchema ); async.series( [ function(callback) { SocialPost.remove({},callback); }, function(callback) { InstagramPost.create({ name: 'My instagram pic', imageUrl: '/myphoto.png' },callback); }, function(callback) { setTimeout( function() { TwitterPost.create({ name: "My tweet", message: "ham and cheese panini #livingthedream" },callback); }, 1000 ); }, function(callback) { var ds = new DataStore(); async.parallel( [ function(callback) { InstagramPost.find({}).limit(1).exec(function(err,posts) { async.each(posts,function(post,callback) { post = post.toObject(); post.id = post._id.toString(); delete post._id; ds.insert(post,callback); },callback); }); }, function(callback) { TwitterPost.find({}).limit(1).exec(function(err,posts) { async.each(posts,function(post,callback) { post = post.toObject(); post.id = post._id.toString(); delete post._id; ds.insert(post,callback); },callback); }); } ], function(err) { if (err) callback(err); ds.find({}).sort({ "date": -1 }).exec(callback); } ); } ], function(err,results) { if (err) throw err; results.shift(); console.dir(results); mongoose.disconnect(); } ); 

与以前相同的输出与最新的postsorting第一,除了这次查询发送到每个模型,我们只是从每个结果,并结合起来。

如果更改查询输出并写入组合模型以使用“stream”处理,那么您甚至具有基本相同的内存消耗,并且可能更快地处理来自并行查询的结果。