MongoDB查询优化

我希望从我的用户模型中检索几个信息,如下所示:

var userSchema = new mongoose.Schema({ email: { type: String, unique: true, lowercase: true }, password: String, created_at: Date, updated_at: Date, genre : { type: String, enum: ['Teacher', 'Student', 'Guest'] }, role : { type: String, enum: ['user', 'admin'], default: 'user' }, active : { type: Boolean, default: false }, profile: { name : { type: String, default: '' }, headline : { type: String, default: '' }, description : { type: String, default: '' }, gender : { type: String, default: '' }, ethnicity : { type: String, default: '' }, age : { type: String, default: '' } }, contacts : { email : { type: String, default: '' }, phone : { type: String, default: '' }, website : { type: String, default: '' } }, location : { formattedAddress : { type: String, default: '' }, country : { type: String, default: '' }, countryCode : { type: String, default: '' }, state : { type: String, default: '' }, city : { type: String, default: '' }, postcode : { type: String, default: '' }, lat : { type: String, default: '' }, lng : { type: String, default: '' } } }); 

在主页我有一个位置的filter,您可以从国家或城市浏览用户。

所有的字段也包含在那里的用户数量:

 United Kingdom All Cities (300) London (150) Liverpool (80) Manchester (70) France All Cities (50) Paris (30) Lille (20) Nederland All Cities (10) Amsterdam (10) Etc... 

这在主页,那么我也有学生和教师的网页,我只想了解这些国家和城市有多less教师的信息…

我想要做的是创build一个查询到MongoDB检索所有这些信息与一个单一的查询。

目前查询看起来像这样:

 User.aggregate([ { $group: { _id: { city: '$location.city', country: '$location.country', genre: '$genre' }, count: { $sum: 1 } } }, { $group: { _id: '$_id.country', count: { $sum: '$count' }, cities: { $push: { city: '$_id.city', count: '$count' } }, genres: { $push: { genre: '$_id.genre', count: '$count' } } } } ], function(err, results) { if (err) return next(); res.json({ res: results }); }); 

问题是我不知道如何获得我需要的所有信息。

  • 我不知道如何获得每个国家的总用户的长度。
  • 我有每个国家的用户的长度。
  • 我有每个城市的用户长度。
  • 我不知道如何得到相同的,但具体的stream派。

是否有可能在Mongo中使用单个查询来获取所有这些信息?

除此以外:

创buildless量的承诺2,3不同的要求,这样的Mongo:

 getSomething .then(getSomethingElse) .then(getSomethingElseAgain) .done 

我确定每次存储指定的数据会更容易,但是: 当数据库中的用户数超过5000/10000时,是否有利于性能?

很抱歉,我还在学习过程中,我认为这些对于理解MongoDB性能/优化是至关重要的。

谢谢

你想要的是一个“分面search”的结果,你持有当前结果集中匹配项的统计信息。 随后,虽然有一些产品“出现”在一个响应中完成所有工作,但您必须考虑到大多数通用存储引擎将需要多个操作。

使用MongoDB,您可以使用两个查询来获得结果,另一个查询结果信息。 这会给类似的结果,从专门的search引擎产品,如Solr或ElasticSearch提供分面的结果。

但为了有效地做到这一点,您希望以有效的方式将其包含在文档中。 你想要的一个非常有效的forms是使用一系列标记化的数据:

  { "otherData": "something", "facets": [ "country:UK", "city:London-UK", "genre:Student" ] } 

所以“factets”是文档中的单个字段,而不是多个位置。 这使得索引和查询非常容易。 然后,您可以有效地汇总您的结果,并获得每个方面的总计:

 User.aggregate( [ { "$unwind": "$facets" }, { "$group": { "_id": "$facets", "count": { "$sum": 1 } }} ], function(err,results) { } ); 

或者更符合$match一些标准:

 User.aggregate( [ { "$match": { "facets": { "$in": ["genre:student"] } } }, { "$unwind": "$facets" }, { "$group": { "_id": "$facets", "count": { "$sum": 1 } }} ], function(err,results) { } ); 

最终给出如下回应:

 { "_id": "country:FR", "count": 50 }, { "_id": "country:UK", "count": 300 }, { "_id": "city:London-UK", "count": 150 }, { "_id": "genre:Student": "count": 500 } 

这样的结构很容易遍历和检查属于“国家”的离散的“国家”和“城市”,因为数据被连字符“ – ”连贯地分开。

试图在数组内混合文档是一个坏主意。 还有一个16MB的BSON大小限制也是值得尊重的,从这些限制结果(尤其是如果你正在试图保留文档内容)混合在一起的结果最终肯定会在响应中被超过。

对于这样简单的事情,然后从这样的查询中得到结果的“总数”,然后总结一个特定方面types的元素。 或者只是发出一个.count()操作相同的查询参数:

 User.count({ "facets": { "$in": ["genre:Student"] } },function(err,count) { }); 

如此处所述,特别是在执行结果的“分页”时,获得“结果计数”,“方面计数”和实际的“结果页”的angular色都被委托给服务器的“单独”查询。

将这些查询中的每一个提交到服务器并没有什么不妥,然后将一个结构合并到模板或应用程序中,看起来非常像来自提供这种响应的search引擎产品之一的分面search结果。


结论

因此,在你的文档中join一些东西来标记一个地方的方面。 标记化的string数组适用于此目的。 对于“ $all ”和“ $all ”等查询表单,对于“或”和“与”方面select组合中的条件也适用。

不要试图混合结果或嵌套添加,只是为了匹配某些感知的层次结构,而是遍历所收到的结果,并在令牌中使用简单的模式。 这很简单

针对内容运行分页查询,作为单独的查询或整体计数。 试图推动数组中的所有内容,然后限制只是为了得到计数是没有意义的。 这同样适用于RDBMS解决scheme来做同样的事情,其中​​分页结果计数和当前页面是单独的查询操作。

在MongoDB博客上有关于使用MongoDB进行分面search的更多信息也解释了一些其他选项。 还有一些关于使用mongoconnector或其他方法与外部search解决scheme集成的文章。