从MySql查询转换查询到mongoDB查询usin php驱动程序

时间:2013-11-21 15:02:45

标签: php mongodb

我必须使用 php

将此查询从 mysql 转换为 mongoDB
SELECT `member_id`, `social_network_id`, `content_type_id` from recent_activity where  content_type_id  = 10  AND social_network_id = 9 group by member_id  order by  recent_activity_id  desc limit 5

我需要结果如:

array(2) {
        ["content_id"]=>
        string(6) "122558"
        ["member_id"]=>
        string(6) "180306",
        ["content_type_id"]=>
        string(6) "10",
        ["social_network_id"]=>
        string(6) "9",
      },
      array(2) {
        ["content_id"]=>
        string(6) "122549"
        ["member_id"]=>
        string(6) "180305",
        ["content_type_id"]=>
        string(6) "10",
        ["social_network_id"]=>
        string(6) "9",
      },
      array(2) {
        ["content_id"]=>
        string(6) "122528"
        ["member_id"]=>
        string(6) "180304",
        ["content_type_id"]=>
        string(6) "10",
        ["social_network_id"]=>
        string(6) "9",
      },

我尝试将聚合框架作为

 $result = $collection->aggregate(array(
            '$match' => array('content_type_id'=>"10", "social_network_id"=>"9"),
            '$project' => array('content_type_id'=>1, "social_network_id"=>1, "content_id"=>1),
            '$group' => array('_id' => array('member_id'=>'$member_id')),
            '$sort'  => array('_id'=>-1),
            '$limit' => 5,
        ));

但我收到了这个错误

["errmsg"]=>
  string(80) "exception: A pipeline stage specification object must contain exactly one field."

我试过

$result = $collection->aggregate(array(
                    '$match' => array('content_type_id'=>"10", "social_network_id"=>"9"),
                    '$project' => array("_id"=>'$content_id' ,'content_type_id'=>1),
                    '$group' => array('_id' => array('content_id'=>'$content_id', 'member_id'=>'$member_id')), 
                )
            );

我试过这个:

$array = array(
                array('$match' => array('content_type_id'=>"10", "social_network_id"=>"9")),
                array(
                    '$group' => array(
                        "_id" => array("member_id" => '$member_id'),
                    ),
                ),
                array('$limit'=>20),
                array('$sort'=>array('_id'=>-1)),
            );
        $results = $collection->aggregate($array);

但是结果不符合我的期望,分组运行良好,但只返回member_id和其他字段

array(2) {
  ["result"]=>
  array(2) {
    [0]=>
    array(1) {
      ["_id"]=>
      array(1) {
        ["member_id"]=>
        string(5) "18036"
      }
    }
    [1]=>
    array(1) {
      ["_id"]=>
      array(1) {
        ["member_id"]=>
        string(6) "180306"
      }
    }
  }
  ["ok"]=>
  float(1)
}

并返回其他字段

所以我需要获得由成员分组的成员的最新5个活动,因此结果应该是5个成员,其中5个活动有不同的成员ID,并列出每个成员的所有数据

我的收藏数据如:

{ "_id" : ObjectId("528e0b3d33df1b21228dc6a0"), "content_id" : "122542", "content_type_id" : "10", "date_added" : ISODate("2013-11-10T14:06:17Z"), "member_id" : "180306", "platform_id" : "2", "social_network_id" : "91" }

{ "_id" : ObjectId("5291a7a733df1bc3048b4567"), "content_id" : "122542", "content_type_id" : "10", "date_added" : ISODate("2013-11-10T14:06:17Z"), "member_id" : "180326", "platform_id" : "2", "social_network_id" : "9" }


{ "_id" : ObjectId("5291a7a733df1bc3048b4567"), "content_id" : "220252", "content_type_id" : "10", "date_added" : ISODate("2013-11-10T14:06:17Z"), "member_id" : "180316", "platform_id" : "2", "social_network_id" : "9" }

{ "_id" : ObjectId("5291a7a733df1bc3048b4567"), "content_id" : "110252", "content_type_id" : "10", "date_added" : ISODate("2013-11-10T14:06:17Z"), "member_id" : "180316", "platform_id" : "2", "social_network_id" : "9" }

我是mongoDB的新手我花了很多时间来转换这个查询并解决这个错误,任何人都可以帮助我

由于

3 个答案:

答案 0 :(得分:2)

解决方案

  

exception:管道阶段规范对象必须只包含一个字段。

$result = $collection->aggregate(array(
    array('$match' => array('content_type_id'=>"10", "social_network_id"=>"9")),
    array('$project' => array("_id"=>'$content_id' ,'content_type_id'=>1)),
    array('$group' => array('_id' => array('content_id'=>'$content_id', 'member_id'=>'$member_id')))
));

请注意包装每个管道的数组

答案 1 :(得分:1)

正确的查询是:

$array = array(
            array('$match' => array('content_type_id'=>"10", "social_network_id"=>"9")),
            array('$project' => array( 'member_id'=>1, 'social_network_id'=>1, 'content_type_id'=>1)),
            array('$group' => array("_id" => array("member_id" => '$member_id', 'social_network_id'=>'$social_network_id', 'content_type_id'=>'$content_type_id'))),
            array('$limit'=>20),
            array('$sort'=>array('recent_activity_id'=>-1)),
        );
$results = $collection->aggregate($array);

使用:

  • $match过滤初始集合以进行汇总
  • $project重塑了 结果文档:添加新字段或包含来自的字段 原始文件
  • $group要分组,不要忘记包含您要选择的所有字段。

关于您的架构设计的说明:

考虑更改您的架构以避免分组(生产速度慢)

你可以使用这样的结构:

{ 
  member_id: 1, 
  shared_contents: [ { social_network_id: 'fb', content_type_id: 1234 }, { ... } ],
  recent_activity_id: 12345
}

正如您所看到的,您可以在文档中包含子文档数组,这样就可以准备好提取数据了。 (确保这不会干扰您的应用程序的其他用例)


<强>更新: 还要返回聚合项的所有ID,将$addToSet添加到$ group和$ project:

array('$project' => array( 'member_id'=>1, 'social_network_id'=>1, 'content_type_id'=>1, 'content_id'=>1)),

array('$group' => array("_id" => array("member_id" => '$member_id', content_ids: { $addToSet: "$content_id" }, 'social_network_id'=>'$social_network_id', 'content_type_id'=>'$content_type_id'))),

答案 2 :(得分:0)

您有包含member_idrecent_activity_id的记录,并且您希望为每个成员返回最近的五个活动(针对特定的社交网络和内容类型)。

目前无法完全在MongoDB中完成。您需要this feature才能使用,但尚未实施。您可以获得的最接近的是,您可以返回每个成员的所有最近活动,然后将该数组限制为客户端的前五个成员。

以下是您对最近所有活动的处理方式:

db.recent_activity.aggregate( [
    { $match : { content_type_id:10, social_network_id:9} },
    { $sort  : { recent_activity_id:-1} },
    { $group : { _id : { member_id:"$member_id", 
                         content_type_id:"$content_type_id", 
                         social_network_id:"$social_network_id" 
                 },
                 activity : { $push : "$recent_activity_id" }
               }
    }
] );

如果使用$slice operator is implemented in aggregation framework,那么您可以将活动数组限制为最新的五种,但在当前版本中也不可用。