1

I'm trying to use the Graph API and the PHP+JS SDK to get a person's friend list, and then go out and get the mutual friends for everyone on the friend list. I can get the friend list easy-peasy as it's just one simple API call. However, the problem arises when trying to get all the mutual friends. Assuming a person has 500 friends, that's 501 different API calls to run the app once, which is way too many.

Fine.

Next idea. Batch up all those API calls and turn 501 into 25. It seemed like a good idea, and that's what I did. Unfortunately, it didn't work. Here's what my code:

KK NVM, I FIXED IT (MOSTLY). IT STILL RUNS REALLY SLOW THOUGH. HERE'S THE NEW CODE:

$userFriends = $facebook->api('/me/friends', 'GET');
$queries = array();
$mutual_friends = array();

foreach ($userFriends[data] as $v1) {
    $queries[] = array('method' => 'GET', 'relative_url' => '/me/mutualfriends/'.$v1[id]);
    if (count($queries)==20){
        $batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
        foreach (range(0,count($queries)-1) as $n) {
            $mutual_friend[] = json_decode($batchResponse[$n]['body'], true);
        }
        $queries = array();
    }
    $batchResponse = $facebook->api('?batch='.json_encode($queries), 'POST');
    foreach (range(0,count($queries)-1) as $n) {
        $mutual_friend[] = json_decode($batchResponse[$n]['body'], true);
    }
}

I have the sneaking suspicion that you're not really supposed to batch API calls like this, but I could be wrong. Also, I've read that FQL is actually a better, preferred method for getting this kind/amount of information, but that would mean that I'd need access to the other people's friend list as well.

The only other solution I can think of would be to throttle the calls, but I don't really want to do that cause I don't want the app to run slowly or have a significant wait period.

Is what I'm trying to do even possible? Am I going about it in the wrong way? Any input or expertise would be greatly appreciated.

2 Answers2

0

In my point of view, FQL is indeed better for this.

Something like this should be answer your problem:

$fql = "SELECT uid1,uid2 FROM friend WHERE uid1 IN ( SELECT uid2 FROM friend WHERE uid1 = me() )";
$friends = $GLOBALS["facebook"]->api(array(
    'method' => 'fql.query',
    'query' => $fql,
));

Concerning the permissions, I think that in each case (batch API or FQL), you need the user's permissions for this.

Edit: In fact, there is an exception during the call which is, in fact, forbidden:

Fatal error: Uncaught Exception: 604: Can't lookup all friends of XXXXXXXX. Can only lookup for the logged in user (YYYYYYYYY), or friends of the logged in user with the appropriate permission thrown in .../php-sdk-v3.1/src/base_facebook.php on line 1039

F2000
  • 380
  • 1
  • 3
  • 13
0

Sorry to switch languages here, but I got this to work well in Ruby using Koala. I'm using a Batch Request as follows:

 friends = @graph_batch.batch do |batch_api|
    batch_api.get_connections("me", "friends", {:limit => 100, :offset => 0}, :batch_args => {:name => "get-friends"})
    batch_api.get_objects("{result=get-friends:$.data.*.id}")
    batch_api.graph_call("method/fql.query", { :query => "SELECT uid1, uid2 FROM friend WHERE uid2 IN ({result=get-friends:$.data.*.id}) AND uid1 IN (SELECT uid2 FROM friend WHERE uid1=me())" }, "post" )
 end

That is,

  1. Graph - Get my friends list - /me/friends
  2. Graph - Get my friends data - /?ids={result=get-friends:$.data.*.id}
  3. FQL - Get all mutual friends - /method/fql.query?query=SELECT uid1, uid2 FROM friend WHERE uid2 IN ({result=get-friends:$.data.*.id}) AND uid1 IN (SELECT uid2 FROM friend WHERE uid1=me())" } (with proper escaping and POST method)

The third query will return a list of elements, uid1, uid2. From there, you have all the data you need to calculate mutual friend counts. In Ruby, I use the following:

 friends[2].clone.delete_if { |r| r['uid2'] != "xxxxxxx" }.count

Basically, I count all elements in the array where uid2 is a specific ID. I'm sure there's better ways to count, but the data is now yours. Hope this helps, and sorry again for switching languages on you (but what's a language mean when you're using an API anyway?).

Edit: You'll only be able to do about 100 rows at a time. You can adjust the limit / offset parameters to page through results.

hayesgm
  • 8,678
  • 1
  • 38
  • 40