MongoDB:如何在单个查询中执行多个dedeferrence?

时间:2014-07-29 13:52:41

标签: mongodb

有几个集合,即CountryProvinceCityUniv

就像现实世界一样,每个国家都有几个省,每个省都有几个城市,每个城市都有几所大学。

我怎么知道大学是否在某个国家?例如,country0可能有一些大学,他们的_id是什么?

这些收藏中的文件如下所示:

{
    _id:"country0",
    provinces:[
    {
        $ref:"Province",
        $id:"province0"
    },
    ...
    ] 
}

{
    _id:"province0",
    belongs:{$ref:"Country", $id:"country0"},
    cities:[
    {
        $ref:"City",
        $id:"city0"
    }
    ...
    ]
}

{
    _id:"city0",
    belongsTo:{$ref:"Province",$id:"province0"},
    univs:[
    {
        $ref:"Univ",
        $id:"univ0"
    }
    ...
    ]
}

{
    _id:"univ0",
    address:{$ref:"City", $id:"city0"}
}

如果只有两个集合,我知道fetch()可能有用。

此外,python驱动程序可能很有用,但我不能很好地了解它们的性能,因为我无法在db.system.profile文件中使用.py

1 个答案:

答案 0 :(得分:1)

MongoDB不进行连接。需要N次查询才能从N个集合中获取信息。在这种情况下,为了获得一个阵列中给定国家的大学的_id,可以执行以下操作(在mongo shell中):

> var country = db.countries.findOne({ "_id": "country0" });
> var province_ids = [];
> country.provinces.forEach(function(province) { province_ids.push(province["$id"]); });
> var provinces = db.provinces.find({ "_id": { "$in": province_ids });
> var city_ids = [];
> provinces.forEach(function(province) { province.cities.forEach(function(city) { city_ids.push(city["$id"]); }); });
> var cities = db.cities.find({ "_id": { "$in": city_ids } });
> univ_ids = [];
> cities.forEach(function(city) { city.univs.forEach(function(univ) { univ_ids.push(univ["$id"]); }); });

使用belongsTo字段也可以使用类似的步骤完成相同的操作。这很麻烦,似乎应该有更好的方法。有!规范化数据。各个国家都有拥有大学城市的省份,但这种关系是固定的,而不是巨大的基数。对于像“特定国家的大学是什么?”这样的问题。我建议将省文件完全存放在国家和大学文件中,完全在城市文件中。您可以将城市存储在省级文档中,也可以直接存储在国家/地区文档中,但省或国家可能有数百或数千个城市,这可能是一个文档的信息太多(MongoDB中每个文档限制为16MB)。在城市的国家和大学中拥有省份可以减少必要的查询次数。

另一种选择是在每个子文档中存储更多信息。基本上你有一个森林(树木的集合):国家是省的父母,他们是大学父母的城市的父母。 belongsTo字段是父引用。您可以存储对所有祖先的引用,而不仅仅是父级。然后查找某个国家的所有大学就是大学馆藏的一个问题。

> db.universities.findOne();
{
    _id: "univ0",
    city: "city0",
    province: "province0",
    country: "country0"
}

> db.universities.find({ "country": "country0" });

最适合您的架构设计取决于您的应用程序需要回答的查询类型及其相对频率和重要性。我无法从你的问题中确定这一点,所以我不能坚定地推荐一种模式而不是另一种模式。

关于效果和db.system.profile集合的小问题,请注意db.system.profile是一个集合。您可以使用驱动程序从.py文件中查询它。