Select field of field using facebook graph api - facebook-graph-api

does facebook support field of filed for graph api?
For example,
https://graph.facebook.com/[uid]/friends/?fields=events
will give all friends and their events.
Can I also control which field i want in the events by doing something like
<https://graph.facebook.com/[uid]/friends/?fields=events,events__updated_time>
Thanks

You can't do this directly through the Graph API, however the best thing to do with more complex queries is to look into FQL. In your specific example, you can do something like this:
SELECT eid, update_time FROM event WHERE eid IN (SELECT eid FROM event_member WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()))
You can run this against the Graph API by doing:
https://graph.facebook.com/fql?q=SELECT eid, update_time FROM event WHERE eid IN (SELECT eid FROM event_member WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()))
Test this using the Graph API Explorer

Related

How can i filter parents that has at least one active child on parent child relationship model

I have "Category" model which has multiple parent/child relationship.
class Category(models.Model):
pass
class CategoryParent(models.Model):
parent_category = models.ForeignKey("Category", related_name="children", on_delete=models.CASCADE)
child_category = models.ForeignKey("Category", related_name="parents", on_delete=models.CASCADE)
is_active = models.BooleanField(verbose_name=_("Is active?"), default=True)
class CategoryExlusion(models.Model):
browser = models.ForeignKey("Browser", on_delete=models.CASCADE)
country = models.ForeignKey("Country", on_delete=models.CASCADE)
category = models.ForeignKey("Category", on_delete=models.CASCADE)
I want to list all top-level categories that have at least one active child category. If there is a record on the CategoryExlusion list for a category and the requested user's browser and country, that means this category is not active for this user. I can reach the user's browser and country with request.user.browser and request.user.country.
The most difficult issue I'm dealing with is the possibility that my child will have children.
For example, if B, X, D and Y are not active for user's browser and country, A wont be returned by QuerySet even A is active for user's browser and country because there wont be any active child for A.
But, At least one active category (for example x might be active for user's browser and country), A will be returned by QuerySet.
This might be difficult to achieve with django-orm as you noted, because of the tree-like structure. I think you best bet will be to use Django's Raw SQL queries to perform a Recursive Query. With the recursive query, you can select all descendents (children, and grand-children, and so on ) of a specific top-level category. Then you can filter out all the children that are on the exclusion list, or inactive. If there is at least one remaining descendent, the top level category remains in the queryset.
I haven't tested it, but I think the recursive query for a specific top level category would look something like that:
team = Category.objects.raw('''
WITH RECURSIVE descendents(id, is_active, child_category, parent_category) AS (
SELECT id, is_active, child_category, parent_category
FROM category
JOIN category_parent as children on category_parent.parent_category = category.id
WHERE id = <id of the top level category>
UNION ALL
SELECT id, is_active, child_category, parent_category
FROM descendents
JOIN parent_category as children on children.parent_category = descendents.id
)
SELECT * FROM descendents
''')
Break down of the query
SELECT id, is_active, child_category, parent_category
FROM category
JOIN category_parent as children on category_parent.parent_category = category.id
WHERE id = <id of the top level category>
This is the non recursive term, selecting the direct children of the top level category
UNION ALL
SELECT id, is_active, child_category, parent_category
FROM descendents
JOIN parent_category as children on children.parent_category = descendents.id
This is the recursive term, self-referencing the non recursive term, that will select the next generation of children. This will iterate until there is no children left in the tree.
You could use this recursive query for each top level category using Django's Subquery. However at this point you might be better of doing it in python, performing one recursive query for each top level category. Depending on you database and the numbers of categories, you might hit performance issues due to the back-and-forths with the database

Django query on event list: finding most recent events

I have a django model that collects events. It looks roughly like this:
class Events(models.Model):
class EventType(models.TextChoices):
OPEN = ...
CLOSE = ...
OTHER = ...
READ = ...
user = models.ForeignKey(User, on_delete=models.CASCADE)
box = models.ForeignKey(Box, on_delete=models.CASCADE)
event_timestamp = models.DateTimeField(default=django.utils.timezone.now)
event_type = models.CharField(max_length=6, choices=EventType.choices)
Events occur when users do things with boxes.
I have four very related queries I want to do, and I'm not at all sure how to do this without resorting to SQL, which usually isn't the right solution with django.
For box B and user U, is the user most recently open or closed for this box?
For Box B, how many users are in an open state?
For Box B, I'd like to plot day by day how many users are open, so I'd like to get a grouped array of users who opened and closed on each day.
I'd like a table over all boxes of how many users are in an open state.
For example, in SQL these would have forms something like this (not tested code, I'm hoping it's easier to use django's query language):
-- 1
SELECT event_type FROM Events
WHERE event_type in ('OPEN', 'CLOSE')
AND user = U
HAVING max(event_timestamp);
-- 2
SELECT count(*) FROM (
SELECT user, event_type FROM Events
WHERE event_type in ('OPEN', 'CLOSE')
GROUP BY user
HAVING max(event_timestamp)
) as T
WHERE event_type = 'OPEN';
-- 3
// A bit complicated any way I slice it due to the
// mapping from datetime to date.
-- 4
SELECT box, count(user) FROM (
SELECT box, user, event_type FROM Events
WHERE event_type in ('OPEN', 'CLOSE')
GROUP BY box, user
HAVING max(event_timestamp)
) as T
WHERE event_type = 'OPEN'
GROUP BY box;
I've explained my four use cases, but I suspect once I understand one of them, the others will follow. Clearly I've just not grokked something from the docs (I hope).
Many thanks for any pointers.
#jma - I am assuming- For Box B, how many events are in an open state? You mentioned Users are in an open state? But state/event_type(Open,Closed) is tied to the Events model.
box = Box.objects.get(name='B') --- assuming you have a name field in Box entity
events = Events.objects.filter(box=box,event_type='open') #queryset
for event in events:
#your logic here
print(event)
3.For box B and user U, is the event most recently open or closed for this box?
Assuming there can be more than one event for a box B with that user U
box = Box.objects.get(name='B') --- assuming you have a name field in Box entity
user = User.objects.get(username='U') -- you can filter based on any field.
Also, this depends on where you want to implement this functionality. If you are using the Django view then you won't need to query the database for the user object. Since the request object has the user attribute.
In django view, user = request.user
events = Events.objects.filter(box=box,user=user)
for event in events:
status = event.event_type
if status=='Open':
#do something
elif status=='Closed':
#do something
else:
#logic here
Also, just a suggestion
Model name should be singular. Event
If you simply name the event_type field type instead of event_type it's better. We are already in the Event model. So, we don't need to name the fields by tagging the model name as a prefix. However, I would stay away from naming a field type. I prefer category or something else. Same with event_timestamp. You can explicitly name this field to let's say to_be_held_on or created_at (based on your use case)

Django query of table with implicit join on itself

I've read the documentation and looked at other questions posted here, but I can't find or figure out whether this is possible in Django.
I have a model relating actors and movies:
class Role(models.Model):
title_id = models.CharField('Title ID', max_length=20, db_index=True)
name_id = models.CharField('Name ID', max_length=20, db_index=True)
role = models.CharField('Role', max_length=300, default='?')
This is a single table that has pairs of actors and movies, so given a movie (title_id), there's a row for each actor in that movie. Similarly, given an actor (name_id), there's a row for every movie that actor was in.
I need to execute a query to return the list of all title_id's that are related to a given title_id by a common actor. The SQL for this query looks like this:
SELECT DISTINCT r2.title_id
FROM role as r1, role as r2
WHERE r1.name_id = r2.name_id
AND r1.title_id != r2.title_id
AND r1.title_id = <given title_id>
Can something like this be expressed in a single Django ORM query, or am I forced to use two queries with some intervening code? (Or raw SQL?)
Normally I would break this into Actor and Movie table to make it easier to query, but your requirement is there so I will give it a go
def get_related_titles(title_id)
all_actors = Role.objects.filter(title_id=title_id).values_list('pk', flat=True)
return Role.objects.filter(pk__in=all_actors).exclude(title_id=title_id) # maybe u need .distinct() here
this should give you one query, validate it this way:
print(get_related_titles(some_title_id).query)

Message Online Friends

FQL Query
SELECT name, online_presence IN ('active', 'idle') FROM user WHERE online_presence IN ('active', 'idle') AND uid in(SELECT uid2 from friend where uid1= me())
By This Query I am getting friends
Please Anyone Tell Me how can I message these online friends.
Method 1:
Assume:
Your app id is "87741124305"
"4" is one of your friend uid get from FQL query:
SELECT uid, name, online_presence FROM user WHERE online_presence IN
('active', 'idle') AND uid in(SELECT uid2 from friend where uid1=
me())
you want to share a link "https://www.youtube.com/watch?v=VM56POaEEX4"
https://www.youtube.com/facebook_redirect is your app CANVAS_URL
The full link would be:
https://www.facebook.com/dialog/send?app_id=87741124305&to=4&link=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DVM56POaEEX4%26feature%3Dshare&redirect_uri=https%3A%2F%2Fwww.youtube.com%2Ffacebook_redirect
Method 2:
Send email to him.The email address is in the form USERNAME#facebook.com You can get the USERNAME via FQL query:
SELECT uid, username, online_presence FROM user WHERE online_presence
IN ('active', 'idle') AND uid in(SELECT uid2 from friend where uid1=
me())
Please note that, some user doesn't have username. Also, you can't send empty body message.
Method 3:
You may refer to https://developers.facebook.com/docs/chat/ for Jabber/XMPP service.

Run multi-query fql in graph api explorer

Trying to run this in the Graph API Explorer:
"query1":"SELECT uid, message FROM status where uid in (SELECT uid2 from friend where uid1 = me())"
"query2":"SELECT name from user where uid in (select uid from #query1)"
But all I get is:
{ "data": [ ] }
I'm completely new into this. What am I doing wrong?
You most likely have a formatting issue
fql?q={"query1":"SELECT uid, message FROM status where uid in (SELECT uid2 from friend where uid1 = me())", "query2":"SELECT name from user where uid in (select uid from #query1)"}
Works fine for me.