Повышение производительности и удобство использования Facebook FQL

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

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

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

  • Он имеет очень низкую производительность
  • Я не могу найти способ повторить эти данные следующим образом:

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

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

Ответы

Ответ 1

Если у вас n страницы, ваш script выполняет запросы n+1. Это главный недостаток вашего script. Это является причиной низкой производительности.

Вы можете использовать пакетный запрос для объединения запросов. Вы можете использовать ниже script для достижения желаемого. Я объединил эти запросы n+1 только с одним пакетным запросом. Таким образом, он будет медленнее, чем ваш script.

Я также исправил часть echo. Теперь script отобразит результат, как вы указали в своем вопросе.

// 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

В настоящий момент вы делаете два отдельных обращения к базе данных 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() только для того, чтобы понять.

ИЗМЕНИТЬ

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

Ответ 3

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

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-ссылок).

Чтобы решить эту проблему, я могу предложить вам две вещи.

  • Используйте команду multi-curl для извлечения нескольких команд одновременно. Это действительно ускорит ваш script, поскольку сразу несколько запросов уменьшат общее время.

  • Но выше решение будет работать в некоторой степени. Если вы запрашиваете много данных, вам нужно искать в другом месте, поскольку php не поддерживает многопоточность. Вы можете использовать java или node.js в качестве альтернативы и использовать redis-сервер (не недооценивайте его) как конвейер между PHP скрипт и java или node.js, используя его pub/sub facility. По моему мнению, это лучшая альтернатива, и я использовал ее для сбора более сотни тысяч записей, и она никогда не терпит неудачу.

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

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

Дипак