我有一个世界各地的彩票游戏数据库。 这就是每个文档的样子:
如果国家/地区拥有州(加拿大,美国),则每个游戏都可以显示在不同的country_code或state_code中。
选择所有game_id' s然后选择它所属的所有国家/地区和/或状态,如下所示:
// get all games
// $colCurrent = MongoCollection Object
$gamesRes = $colCurrent->distinct('game_id');
foreach($gamesRes as $gameId) {
$disCountries = $colCurrent->distinct('country_code',array('game_id' => $gameId));
$disStates = $colCurrent->distinct('state_code',array('game_id' => $gameId));
}
我认为这是不恰当的方式,因为它对数据库进行了大量查询。 我尝试过使用聚合函数,但它只选择1个字段,如distinct。
任何人都可以帮助优化此查询吗?
非常感谢!
答案 0 :(得分:1)
根据您要实现的目标和数据集的大小,您可以采取一些不同的方法。
使用mongo
shell中的Aggregation Framework的一些示例(MongoDB 2.2 +):
1)找到所有游戏并为每个游戏创建一组唯一的country_code和state_code值:
db.games.aggregate(
{ $group: {
_id: { gameId: "$game_id" },
countries: { $addToSet: "$country_code" },
states: { $addToSet: "$state_code" }
}}
)
2)查找所有游戏,并通过gameId,country_code和state_code的唯一组合进行分组,包括计数:
db.games.aggregate(
{ $group: {
_id: {
gameId: "$game_id",
country_code: "$country_code",
state_code: "$state_code"
},
total: { $sum: 1 }
}}
)
在第二个示例中,请注意用于分组的_id
可以包含多个字段。
如果您不想对集合中的所有文档进行分组,则可以从$match
operator开始,将管道限制为所需的数据,从而提高这些聚合的效率($match
也可以利用合适的指数。)
答案 1 :(得分:0)
假设您指的是每个game_name的不同国家/地区的总数和不同状态的总数(假设每个game_id一个,并且这更具可读性[如果需要可以互换])
作为mongo shell发布,一般清晰,根据需要适应您的驱动程序和语言:
db.lottery.aggregate([
{$project: { country_code: 1, state_code: 1, game_name: 1 } },
{$group: {
_id: "$game_name",
countries: {$addToSet: "$country_code"},
states: {$addToSet: "$state_code"}
}},
{$unwind: "$countries"},
{$group:{ _id: { id: "$_id", states: "$states" }, country_count: {$sum: 1 } }},
{$project: { _id: 0, game: "$_id.id", countries: "$country_count", states: "$_id.states" }},
{$unwind: "$states"},
{$group: { _id: { id: "$game", countries: "$countries" }, state_count: {$sum: 1 } }},
{$project: { _id: 0, game: "$_id.id", countries: "$_id.countries", states: "$state_count" }},
{$sort: { game: 1 }}
])
所以这里有一些奇特的阶段:
唷!一个相当重要的聚合但它确实显示了解决问题的方法。
<强>声明:强>
我已经在这里做了巨大的假设,你的数据确实已经有了意义,而且每个国家和/或每个州都没有多个游戏记录。额外的“我没有这样做”部分是你的代码没有在国家内分辨出那些“我也没有这样做” :-P
您可以添加 $ group 阶段来执行此操作。编程的一部分乐趣是学习和研究如何自己做事。所以,如果不是完美契合,这应该是一个好的开始。
reference是学习如何应用此处使用的所有运算符的一个非常好的地方。一次应用一个阶段(数据大小允许),以便了解每个步骤的进展情况。