2012-04-05 51 views
1

我访问了Facebook Graph API以获取代表我的订阅源(我的Facebook墙)上的最新帖子的JSON对象。然后,我使用PHP Mongo Driver将它保存到一个名为feeds的MongoDB集合中。使用PHP驱动程序深入查询MongoDB子集两级深入使用PHP驱动程序

//$post['feed']['data'] contains the Facebook JSON object of wall posts 
//create a mongo instance 
$mongo = new Mongo(); 
//access the feeds collection 
$feeds = $mongo->changeup->feeds; 
//dump the feed right into mongo 
$feeds->insert($post['feed']['data']); 

这是在读回被放入mongo中的整个对象之后,其中一个数组看起来像。

我只向你展示一个,但它给了我多个,每个索引,下一个是[1] => Array()等等...一些结构不同,因为一些包含[故事]字段,其他字段包含[消息]字段,有些字段包含两者。

Query: 
$cursor = $feeds->find(); 

foreach ($cursor as $feed) { 
print_r($feed); 
} 

Result: 
[0] => Array 
     (
      [id] => 505212695_10150696450097696 
      [from] => Array 
       (
        [name] => John Doe 
        [id] => 505212695 
       ) 

      [story] => "Text of a story I posted on my wall..." 
      [story_tags] => Array 
       (
        [38] => Array 
         (
          [0] => Array 
           (
            [id] => 15212444 
            [name] => John Doe 
            [offset] => 38 
            [length] => 10 
            [type] => user 
           ) 

         ) 

       ) 

      [type] => status 
      [application] => Array 
       (
        [name] => Share_bookmarklet 
        [id] => 5085647995 
       ) 

      [created_time] => 2012-04-04T05:51:21+0000 
      [updated_time] => 2012-04-04T05:51:21+0000 
      [comments] => Array 
       (
        [count] => 0 
       ) 

) 

的问题是,我不想随便找整个集合,我想找到只有那些说[消息]这些阵列和[故事]字段,然后随便找个它们的内容并没有什么其他。

我想接受一个子集,两层深:

//this works, however, I'm only able to get the 0 array 
$cursor = $feeds->find(array(), array('0.story' => true)); 

如何通过所有阵列过滤器?

我希望我的最终结果是这样的:

Array 
(
    [_id] => MongoId Object 
     (
      [$id] => 4f7db4dd6434e64959000000 
     ) 

    [0] => Array 
     (
      [story] => "Text of a story I posted on my wall..." 
     ) 
    [1] => Array 
     (
      [story] => "Text of a story I posted on my wall..." 
     ) 
    [2] => Array 
     (
      [story] => "Text of a story I posted on my wall..." 
      [message] => "In this case message text exists as well..." 
     ) 
    [3] => Array 
     (
      [message] => "Text of a message I posted on my wall..." 
     ) 

    etc... 
) 

回答

2

我相信最初的问题与各供文档数据结构开始。注意你的对象只是一个id,然后是一个递增的数字键,这就是它。最理想的是你在顶层插入一个带有键和值的实际对象结构。目前,因为您直接将facebook数据直接转储到mongo中而不进行格式化,驱动程序将您的数组映射到键/值。现在每个Feed文档都有不定数量的匿名对象。

请参阅本:http://www.php.net/manual/en/mongo.writes.php

我会想你的饲料文档看起来应该会是这样的:

{ 
    "_id" : ObjectId("4f7db4dd6434e64959000000"), 
    "posts" : 
    [ 
     { 
      "story" : "Text of a story I posted on my wall...", 
      "message" : "In this case message text exists as well...", 
     }, 
     { 
      "story" : "Text of a story I posted on my wall...", 
      "message" : "In this case message text exists as well...", 
     } 
    ], 
    "posts_meta1": "some val", 
    "posts_meta2": "other data" 
} 

注意,它包含了“上岗”顶级键,用你的阵列发布下面的对象。这解决了多个问题。您可以使用顶级关键字进行索引,而不是“数字”,您可以拥有更清洁的根级别来添加更多的Feed字段,并且可以干净地实现查找查询。

一个简单的查找可能是这样的:

// Return all feed docs, and only include the posts.story field 
db.feeds.find({}, {"posts.story": 1}) 

更先进的查询可能是这样的:

// Return an feed document that either contains a posts.story 
// field, or, contains a posts.message field 
db.feeds.find({ 
    $or: [ 
     {$exists: {"posts.story": true}}, 
     {$exists: {"posts.message": true} 
    ] 
}) 

简而言之,从Facebook返回的数据应该首先被格式化成对象结构,然后插入到mongo中。例如,日期应该插入为适当的日期对象,而不是原始字符串:http://www.php.net/manual/en/class.mongodate.php。这可以让你在mongo中进行基于日期的查询,并且php驱动程序还会确保来回转换它们,以便它们更适合你的语言。

+0

非常感谢,作品! – Allen 2012-04-05 23:24:58

1

没有看到Facebook发送的JSON数据,很难说出story_tags字段中的结构应该是什么样子。您可能需要从Facebook和力json_decode来转换成PHP关联数组的JSON解码:

$ar = json_decode($post['feed']['data'], true); 

“真”这里的标志迫使它处理数据作为关联数组。

然后你会插入如下:

$feeds->insert($ar); 

无论哪种方式,我倾向于将数据重组的东西,将其存储在数据库之前适合您的需求更好 - 这将让你除其他事项外,更有效地使用索引。如果您真的需要存储来自Facebook的整个响应,您可以始终将其存储为嵌套对象:

$ar['raw'] = $post['feed']['data']; 
相关问题