PHP MongoDB按键选择字段(不同)

时间:2014-02-02 10:10:45

标签: php mongodb aggregation-framework

我有一个世界各地的彩票游戏数据库。 这就是每个文档的样子:

enter image description here

如果国家/地区拥有州(加拿大,美国),则每个游戏都可以显示在不同的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。

任何人都可以帮助优化此查询吗?

非常感谢!

2 个答案:

答案 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 }}
])

所以这里有一些奇特的阶段:

  1. 投放仅需要的字段
  2. 对游戏进行分组,并将每个国家和州推入自己的阵列
  3. 现在解开各个国家/地区以获得每个国家/地区一条记录
  4. 在保留游戏和州字段数组的同时对国家/地区进行分组
  5. 项目 - 选项 - 使记录看起来更自然。 $ group messes with _id
  6. 解除状态以获得每个州的一条记录
  7. 在保留游戏和国家计数的同时对各州进行分组
  8. 投射更自然的东西
  9. 按照你喜欢的方式排序 - 选项 - 。在这种情况下,游戏的名称
  10. 唷!一个相当重要的聚合但它确实显示了解决问题的方法。

    <强>声明:

    我已经在这里做了巨大的假设,你的数据确实已经有了意义,而且每个国家和/或每个州都没有多个游戏记录。额外的“我没有这样做”部分是你的代码没有在国家内分辨出那些“我也没有这样做” :-P

    您可以添加 $ group 阶段来执行此操作。编程的一部分乐趣是学习和研究如何自己做事。所以,如果不是完美契合,这应该是一个好的开始。

    reference是学习如何应用此处使用的所有运算符的一个非常好的地方。一次应用一个阶段(数据大小允许),以便了解每个步骤的进展情况。