14

我试图从我在 Facebook 上担任管理员的页面中获得一些见解。
我的代码做了什么,它通过 mySQL 获取我想要使用的页面的 ID。我没有包括那部分。

在此之后,我得到了每个 facebook ID 的 page_id、name 和 fan_count,并保存在fancounts[].

我有两个问题。

  1. 它的性能非常慢
  2. 我找不到像这样回显数据的方法:

我的问题是,如何修改代码以提高性能并显示上述数据?我读到了 fql.multiquery。可以在这里使用吗?

请为我提供代码示例。谢谢

4

3 回答 3

12

目前,您正在对 Facebook 的数据库进行两次单独的调用,这会减慢一切速度。Facebook 提供了他们的多查询,以便您可以在尽可能少的数据库调用中完成所有操作。因此,您应该考虑使用的调用是:

"query1":"SELECT page_id, name, fan_count FROM page WHERE page_id IN ($pagesIds)"

而且因为它们允许您引用先前的查询,所以您可以在 # 之后包含它:

"query2":"SELECT message FROM stream WHERE source_id IN (SELECT page_id FROM #pages) LIMIT 2"

您需要使用的 PHP 是这样的:

$query = array(
    "pages"=>"SELECT page_id, name, fan_count FROM page WHERE page_id IN ($pagesIds)",
    "messages"=>"SELECT message FROM stream WHERE source_id IN (SELECT page_id FROM #pages) LIMIT 2"
);

$fql_url = $facebook->api(array(
    'method' => 'fql.multiquery',
    'queries' => $query
));

print_r($fql_url);

如果第二个查询未通过,请尝试仅使用此查询测试 FB DB并查看它是否有效。如果查询本身没有返回任何内容,则问题可能出在权限上(即访问敏感表——但我认为情况并非如此)。我经常遇到的另一个问题是 FQL 是如何使用空格来跳闸的,因此请尝试从数组中省略所有可能的空格:

$query = array("pages"=>"SELECT page_id, name, fan_count FROM page WHERE page_id IN ($pagesIds)","messages"=>"SELECT message FROM stream WHERE source_id IN (SELECT page_id FROM #pages) LIMIT 2");

哇,这可读性强……不过,这取自Facebook关于 FQL 的文档,因此如果使用第三方库,您可能需要针对您的 Web 应用程序进行调整。您的所有数据都保存在$fql_url. 您需要做的就是遍历它并回显您想要的信息。如果您想查看它包含的所有内容的摘要,请考虑使用print_r()var_dump()只是为了了解您的方位。

编辑

您收到第二个查询的空数组的原因是您似乎没有该stream表的权限。如果您查看 Facebook 的文档,他们会提到访问此表所需的条件:

要读取您需要的流表

  • read_stream当前会话用户能够查看的所有帖子的权限
  • read_insights查看当前会话用户拥有的主页发布的任何帖子的帖子展示次数的权限

要检查您拥有的权限,您可以运行以下查询:

$check_query = $facebook->api(array(
    "method"    => "fql.query",
    "query"     => "SELECT * FROM permissions WHERE uid=me()"
));

foreach($check_query[0] as $k => $v) {
    if($v === "1") {
        echo "<strong>$k</strong> permission is granted.<br>";
    } else {
        echo "<strong>$k</strong> permission is not granted.<br>";
    }
}
于 2012-03-30T05:26:17.797 回答
5

如果您有n页面,您的脚本会进行n+1查询。这是您的脚本的主要缺点。这就是性能低下的原因。

您可以使用批处理请求来组合查询。您可以使用以下脚本来实现您想要的。我将这些n+1查询组合成一个批处理查询。所以它会比你的脚本快。

我也更正了这echo部分。现在脚本将显示您在问题中所述的输出。

// Get the IDs
$pages = array(); 
$pagesIds = implode(',', $pages);

// fancounts[] holds the page_id, name and fan_count of the Ids I work with
$fancounts = array();
$q = "SELECT page_id, name, fan_count FROM page WHERE page_id IN ({$pagesIds})";
$queries[] = array('method'=>'GET', 'relative_url' => 'method/fql.query?query=' . urlencode($q) );

$messages = array();
foreach( $pages as $id) 
{
   $q = "SELECT message FROM stream WHERE source_id = '$id' LIMIT 2";
   $queries[] = array('method'=>'GET', 'relative_url' => 'method/fql.query?query=' . urlencode($q) );
}

// The batch query
$batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
$pagesFanCounts = json_decode($batchResponse[0]['body'], TRUE);

foreach ($pagesFanCounts as $page)
{       
   $fancounts[] = number_format($page['page_id'],0,'','')."-".$page['name']."-".$page['fan_count'];
}

for($i=0; $i < count($fancounts); $i++) 
{
   echo '</br>',$fancounts[$i],'<br>';
   $temp = json_decode($batchResponse[$i+1]['body'], TRUE);
   foreach ($temp as $msg)
   {
      echo ($msg['message']);
      echo "</br>";
   }
}
于 2012-03-31T04:38:31.450 回答
2

你可以尝试任何东西,但你的代码不会运行得很快,因为你打破了高速网络应用程序的黄金法则。你现在真正写的是:

request1->(wait for response-> download data) -> request2 (wait for response -> 
download data)  -> and so on ......

而你真正应该做的:-

request1->(wait for response-> download data)
request2->(wait for response-> download data)
request3->(wait for response-> download data)
......
......

是的,您应该一次发出多个请求以减少总响应时间。浏览器仅通过这种方式加速页面加载。

我在使用 RSS 提要提取器时遇到了类似的问题(它有巨大的 RSS 链接数据库)。

为了解决这个问题,我可以建议你两件事

  1. 使用 multi-curl 命令一次获取多个命令。它确实会加速您的脚本,因为一次多个请求会减少整体时间。

  2. 但上述解决方案将在一定程度上起作用。如果您要查询大量数据,那么您必须寻找其他地方,因为 php 不支持多线程。您可以使用 java 或 node.js 作为替代方案,并使用 redis 服务器(不要低估它)作为 php 脚本和 java 或 node.js 之间的管道,方法是使用它的 pub/sub 工具。在我看来,这是最好的选择,我已经用它来获取超过数十万条记录,而且它从未失败过。

我无法真正帮助您的另一件事是您的互联网连接速度;)

希望这能解决你的问题:)

迪帕克

于 2012-04-05T19:16:07.050 回答