使用MongoDB嵌套和查询文档

时间:2016-01-30 00:47:10

标签: node.js mongodb mongoose document-database odm

我有一个看起来或多或少的数据结构:

var city = {
  name: String,
  mayor: Person,
  citizens: [Person]
};

我认为我的用例非常适合使用MongoDB,但我有几个问题。上面的模型已经用mongoose实现了,我使用sub documents来嵌入City内的人。显然,公民阵列可能会变得很长,这就是为什么MongoDB看起来是个不错的选择。

这是构建数据的有效方法吗?我想知道,每当我想选择一个城市时,Mongo是否必须进行某种加入,所有的公民(或其中很大一部分)。这显然会破坏使用文档数据库的目的。

此外,在mongo终端中,我尝试db.cities.find({name:'Berlin'}).mayor之类的内容,但我没有得到任何结果。当我尝试db.cities.find({name:'Berlin'})它显示城市时,它也显示市长的对象ID,但不显示mayer / Person的所有属性。

那么如何使用子文档查询并且这是一种很好的工作方式?

1 个答案:

答案 0 :(得分:0)

我建议您使用Populate建立您的架构。 MongoDB中没有joins,但有时我们仍然希望引用其他集合中的文档。这就是人口涌入的地方。

var personSchema = Schema({
  _id     : Number,
  name    : String,
}); 

var Person = mongoose.model('Person', personSchema);

var citySchema = Schema{
  name: String,
  mayor: { type: Schema.Types.ObjectId, ref: 'Person' },
  citizens: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
};

var City = mongoose.model('City', citySchema);

Berlin

一样查询城市
City.find({name: 'Berlin'})
    .populate('mayor')
    .populate('citizens')
    .exec(...)

将从数据库中检索mayorcitizens相关文档。

如果您担心该城市citizens太多,city太大而populate中的人city,则另一个选项是

var personSchema = Schema({
  _id     : Number,
  name    : String,
  cityId  : { type: Schema.Types.ObjectId, ref: 'City' }
}); 

var Person = mongoose.model('Person', personSchema);

var citySchema = Schema{
  name: String,
  mayor: { type: Schema.Types.ObjectId, ref: 'Person' }
};

var City = mongoose.model('City', citySchema);

要使用aggregation查询城市Berlin,以下是示例代码。

City.find({name: 'Berlin'})
    .populate('mayor')
    .exec(function(err, city) {
       Person.aggregate([
          {$group: {cityId: city._id, citizens: {$push: '$name'}}}
          // ...
       ], function(err, result) {
          //...
});