Повышение производительности и удобства использования Facebook FQL - PullRequest
14 голосов
/ 28 марта 2012

Я пытаюсь получить информацию со страниц, которые я являюсь администратором в Facebook.
Что делает мой код, он получает идентификаторы страниц, с которыми я хочу работать через mySQL.Я не включил эту часть.

После этого я получаю page_id, name и fan_count каждого из этих идентификаторов facebook и сохраняю в fancounts[].

У меня две проблемы сit.

  1. У него очень низкая производительность
  2. Я не могу найти способ отобразить данные следующим образом:

Мои вопросы,Как можно изменить код для повышения производительности и отображения данных, как указано выше?Я читал о fql.multiquery.Можно ли его использовать здесь?

Пожалуйста, предоставьте мне примеры кода.Спасибо

Ответы [ 3 ]

12 голосов
/ 30 марта 2012

В данный момент вы делаете два отдельных звонка в базу данных 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, поэтому, возможно, вам придется адаптировать ее для вашего веб-приложения, если вы используете стороннюю библиотеку. Все ваши данные сохраняются в $fql_url. Все, что вам нужно сделать, это пройтись по нему и вывести на экран информацию, которую вы хотите. Если вы хотите увидеть сводку всего, что в нем содержится, подумайте об использовании print_r() или var_dump() только для того, чтобы получить ваши подшипники.

EDIT

Причина, по которой вы получаете пустой массив для второго запроса, заключается в том, что у вас, похоже, нет разрешений для таблицы 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>";
    }
}
5 голосов
/ 31 марта 2012

Если у вас есть 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>";
   }
}
2 голосов
/ 05 апреля 2012

Вы можете попробовать что угодно, но ваш код не будет работать быстро, потому что вы нарушаете золотое правило высокоскоростного веб-приложения. Что вы на самом деле делаете, пишите сейчас:

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. По моему мнению, это лучшая альтернатива, и я использовал ее, чтобы получить более ста тысяч записей, и она никогда не дает ошибок.

И еще одна вещь, в которой я не могу вам помочь, это скорость вашего интернет-соединения;)

Надеюсь, это решит вашу проблему:)

Дипак

...