Question

I'm trying to query Facebook for the last 50 photos posted by my friends.

Sounds easy enough, right? So far I've found two different approaches using FQL, and neither works.

Photo Method [Explorer]

SELECT pid, owner, src_big, caption, created
FROM photo WHERE owner IN (
  SELECT uid1 FROM friend WHERE uid2=me()
) ORDER BY created DESC LIMIT 50

The problem with this is that it's doing a depth-first search when I really want a breadth first search. It's going through my friends list, finding the first friend with a bunch of photos, and then giving me back her most recent photos, ignoring more recent photos from friends further down on my friends list.

Stream Method [Explorer]

SELECT pid, owner, src_big, caption, created 
FROM photo where pid in (
  SELECT attachment.media.photo.pid
  FROM stream 
  WHERE filter_key IN (
    SELECT filter_key FROM stream_filter WHERE uid=me()
  ) AND type = 247
  ORDER BY created_time DESC 
  LIMIT 50
)

This is much closer to what I want, except that it's giving me photos from pages, too, and I only want photos from friends. As far as I can tell, there is no way to filter uid by type (e.g. friend, page, etc.).

What am I missing? Is there a third way? Is this impossible?

Was it helpful?

Solution

I tried your query and timeout error encountered(by this time):

enter image description here

Your main key should put filter_key with app_2305272732 in the first place to return photo only, instead of filter by type=247 afterward, so you can get more results:

SELECT pid, owner, src_big, caption, created FROM photo where pid IN(SELECT attachment.media.photo.pid FROM stream WHERE filter_key='app_2305272732' AND actor_id IN(SELECT uid1 FROM friend WHERE uid2=me()) AND created_time<=now() ORDER BY created_time DESC LIMIT 200)

As you can see, the actor_id only include friends, but the response can be faster(~2 seconds for 2000 friends) if you put actor_id directly, so you may consider to cache the friends id (depends on your app flow).

actor_id IN(FRIEND_ID1,FRIEND_ID2,FRIEND_ID3...)

Also, there's no guarantee to get 50 photos in once, but you can navigate to next page by created_time(Get from last photo's created field). Even thought the created time from photo table may slightly different(~1 seconds) than stream table, but it should acceptable.

created_time<CREATED

Finally, you should increase the limit, so you can get more result at once. I found 200 is acceptable and i'm able to get more than 20 photos in one page.

LIMIT 200

Update:

You should use source_id instead of actor_id, to get much more results. So the correct query is:

SELECT pid, owner, src_big, caption, created FROM photo where pid IN(SELECT attachment.media.photo.pid FROM stream WHERE filter_key='app_2305272732' AND source_id IN(SELECT uid1 FROM friend WHERE uid2=me()) AND created_time<=now() ORDER BY created_time DESC LIMIT 200)

The LIMIT parameter can be decrease if you do this query, let's say LIMIT 50, so your single query can be faster and avoid timeout request failed(if the photos data is too many and too heavy), it's depends on your decision.

I have to remind you, you can't simply use created from photo table to query next page of stream table, because a feed may contains many photos and the created time for each photos can be much more different(the distinct can be in hours!). So you should consider to do multiquery to retrieve created_time of stream table if you want to do next page, for example:

{"query1":"SELECT attachment.media.photo.pid, created_time FROM stream WHERE filter_key='app_2305272732' AND source_id IN(SELECT uid1 FROM friend WHERE uid2=me()) AND created_time<=now() ORDER BY created_time DESC LIMIT 200", "query2":"SELECT pid, owner, src_big, caption, created FROM photo where pid IN(SELECT attachment.media.photo.pid FROM #query1)"}

Also, please note that ORDER BY created DESC is sort the feed, not photo, so it's normal if you see the create time is not in the order.

You may consider to do comparison for every single photo's created time with next page's created_time, and only show the photo which are currently earlier than next page's created_time. For example, if the next page created_time is 5.00 PM, and you have the photo A with created time at 2.00 PM(get from first page). You can just hold on the photo A until the next page created_time is older than 2.00 PM, so you can display photo A to the user. Of course, you have to do sorting after you insert photo A to current page's photos.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top