Давайте возьмем простой запрос FQL, чтобы получить все ссылки, которыми друзья пользователя поделились со вчерашнего дня, например:

SELECT link_id, title, url, owner, created_time
FROM link
WHERE
    created_time > strtotime('yesterday') AND
    owner IN (
        SELECT uid2 FROM friend WHERE uid1 = me()
    )
LIMIT 100

Если у пользователя 50 друзей, это будет отлично. Но если у пользователя сотни друзей, Facebook чаще всего возвращает ошибку.

Параметры:

  1. Ограничьте количество запросов на выбор друзей до 50 . Конечно, это сработает, но каждый раз будут отображаться одни и те же друзья. Если вам не нужен канал только для Лиги плюща , это не очень поможет.
  2. Пакетные запросы . Создайте пакет запросов с использованием смещений и ограничьте каждый до 50. К сожалению, здесь нет никаких улучшений.
  3. Loop It - пока что это лучшее, что я нашел. Просмотрите те же запросы, которые вы создали для пакетного запроса, но выполняйте это по одному с несколькими вызовами запросов api fql. Но даже это хит и промах.

Как правильно запросить Facebook, чтобы добиться успешных результатов?

Примечания:

  • Я использую последнюю версию Facebook php sdk, 3.1.1
  • Я также попытался расширить параметры по умолчанию для таймаутов завивки в base_facebook.php

Распространенные ошибки, связанные с тайм-аутом:

1 .

Fatal error:  Uncaught Exception: 1: An unknown error occurred thrown in /..../facebook/php-sdk/src/base_facebook.php on line 708

Строка 708 - ошибка исключения:

// results are returned, errors are thrown
if (is_array($result) && isset($result['error_code'])) { 
    throw new FacebookApiException($result);
}

2 .

Fatal error: Uncaught CurlException: 52: SSL read: error:00000000:lib(0):func(0):reason(0), errno 104 thrown in /..../facebook/php-sdk/src/base_facebook.php on line 814
8
Ryan 30 Авг 2011 в 23:20

3 ответа

Лучший ответ

Вы должны выполнить цикл, используя limit / offset, как вы сказали, или кешировать список друзей заранее, как предлагает puffpio.

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

Наконец, для потомков я открываю задачу по оптимизации таблицы ссылок, чтобы она могла работать эффективнее, когда она фильтруется по времени.

2
Drew Hoskins 30 Авг 2011 в 20:35

Некоторые движки баз данных плохо или вообще не оптимизируют ключевое слово IN. Они могут выполнять предложение in для каждой результирующей строки вашего запроса. Можете ли вы присоединиться к таблицам ссылок и друзей вместо использования IN с подзапросом?

Вы можете найти

Было бы лучше кэшировать друзей пользователя и обновлять их только изредка. Другими словами, запустите этот запрос

SELECT uid2
FROM friend
WHERE uid1 = me()

Кешировать список пользователей и запускать

SELECT link_id, title, url, owner, created_time
FROM link
WHERE
    created_time > strtotime('yesterday') AND
    owner IN (/*your user list here*/)
LIMIT 100

Таким образом, вы не выполняете внутренний запрос все время. На самом деле список друзей пользователя не имеет высокой текучести, поэтому вам не нужно обновлять его так часто, как получение ссылок для общего доступа.

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

1
sakibmoon 13 Июл 2013 в 07:58