I am looking for optimized FQL way getting latest photos per user_id, the only one I can think now is to get aid's (album id's) and query each aid for photos ... (this is lots of querying)
You can use subquery, should be like so:
SELECT object_id, src_small
FROM photo
WHERE aid IN (SELECT aid FROM album WHERE owner = me())
ORDER BY created DESC LIMIT 1
hope this helps
Related
I am having trouble writing a query using Django ORM, I want to find the latest record in each group. I am putting chat messages in the model and I want to find the latest chat of each user and show chats latest chat of each user and with the latest user's chat on the home screen just like in WhatsApp, Skype or similar apps. Currently, I am using the following query,
Chats.objects.all().order_by('user_id', '-date').distinct('user_id')
Using this I am able to get the latest chat of each user but I am not able to get the sequence correct. The result of the query is in the order of which the users were created in the database which I understand is correct, but I want to show the user who sent the latest chat at the top.
My Models.py
class Chats(models.Model):
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
chat = models.CharField(max_length=1023, null=True, blank=True)
date = models.DateTimeField(auto_now_add=True)
Thank you so much, Please let me know if any other information is required.
Option 1: Order on the Django/Python layer
The items are first sorted by user_id, and only in case of a tie, it takes the one with the latest date. But that means that you eventually get for each user a Chats object, ordered by the user_id.
I think here your only option is to sort it at the Django/Python level, so wrap it into a list, and sort by the date:
from operator import attrgetter
items = list(Chats.objects.order_by('user_id', '-date').distinct('user_id'))
items.sort(key=attrgetter('date'), reverse=True)
# work with items
and then render the items in the template.
Option 2: Annotate the User model instead
Another option is to annotate the User model and thus work with a QuerySet of User objects:
from django.db.models import Max, OuterRef, Subquery
User.objects.filter(
chats__isnull=False
).annotate(
last_date=Max('chats__date'),
last_message=Subquery(
Chat.objects.filter(user_id=OuterRef('pk')).order_by('-date').value('chat')[:1]
)
).order_by('-last_date')
Here the User objects will have an extra attribute .last_date with the latest date time of the object, and .last_message with that message.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I have two models user and recordings, But I don't have any relation between them I have stored user id in recordings (there can be multiple recordings of one user). and I want the latest recording of user with user object how can I achieve that
class Recording(models.Model):
userid = models.IntegerField()
Hi welcome to stackoverflow.
Please ask your question with some of your code.
I think you can try this:
users = User.objects.all().extra( select={
'last_reco':
'SELECT recordings.field_name FROM recordings WHERE '
'recordings.userid = '
'User.id ORDER BY id DESC LIMIT 1',
})
note: recordings is your recording db name
Than you can access last recording with last_reco attr of user object
I have 2 tables, the relation is one to many, "Book" (id, name, author) -> "BookStatus" (id, status, date). I want to get all the books with their LAST status (according the field 'date') in a queryset. How can I accomplish that?
After that, how could I show that field (status) through my model "Book", something like Book.last_status.
Thanks in advance
Unfortunately this isn't easy to do through the ORM. The reason is that the SQL required for this is surprisingly complex. First you need to fetch the latest status date, then join the status matching that status.
If you need only access to the latest status on Python side, then you can use book.statuses.latest() (generates a query per model), or possibly a property on the model:
#property
def latest_status(self):
latest_status = None
for status in self.statuses.all():
if latest_status is None or latest_status.date < status.date:
latest_status = status
return latest_Status
Now you can use latest_status on Python side to fetch the latest status of the book. If you add prefetch_related when fetching books, accessing latest_status will not generate a query.
If you need access to the latest status when querying things become much more complicated. I have often used a solution where I create views in to the database for latest items, then use those views through the ORM. So, something like this in the database:
CREATE VIEW latest_book_status_view AS (
SELECT null AS id,
book_status.book_id,
book_status.id AS status_id
FROM book_status
WHERE book_status.date = (SELECT max(inner_status.date)
FROM book_status inner_status
WHERE inner_status.book_id = book_status.book_id)
);
In models.py:
class LatestBookStatus(models.Model):
# Note the null id column above. It will be used as fake primary key
# for this model.
book = models.OneToOneField(Book, null=True, on_delete=models.DO_NOTHING, related_name='latest_status')
status = models.OneToOneField(BookStatus, null=True, on_delete=models.DO_NOTHING)
class Meta:
db_table = "latest_book_status_view"
managed = False
Now you should be able to issue queries where you filter on status:
Book.objects.filter(latest_status__status__date__gte=today())...
And you can fetch the latest status by:
qs = Book.objects.select_related('latest_status__status')
# access it
qs[0].latest_status.status.date
Unfortunately this setup is complex and comes with some problems. For example, when testing you will need some way to generate the views in to the testing database. Django 1.7 migrations and RunSQL operation is one way to do this.
In short: if you need access to latest status on Python side, use the property approach. If you need access to the latest status on SQL side, be prepared for a more comlex solution. One possible solution is given above.
Be sure to set nice related_name and setup proper get_latest_by for BookStatus.
books = Book.objects.prefetch_related('statuses')
books[0].statuses.latest()
How do I access friends likes with FQL? I can see it in the Graph API:
https://graph.facebook.com/1111111/likes
... but I can't seem to figure out how to do it in FQL.
fql?q=SELECT uid, page_id from page_fan where uid IN(SELECT uid2 from friend where uid1=me())
You can try this in your api explorer to get user friends likes.
You can do this by querying url_like table:
SELECT url FROM url_like WHERE user_id IN (
SELECT uid2 FROM friend WHERE uid1 = me()
)
You cannot however get list of likes by friends for: photo, album, event, group, note, link, video, application, status, check-in, review, comment, post.
This info is located in like table but to query it based on user_id you need read_stream permissions from that user...
EDIT: Added Graph API Explorer Example to easily preview this:
http://developers.facebook.com/tools/explorer?method=GET&path=fql%3Fq%3DSELECT%20url%20FROM%20url_like%20WHERE%20user_id%20IN%20(SELECT%20uid2%20FROM%20friend%20WHERE%20uid1%20%3D%20me())
I run a lab annotation website where users can annotate samples with tags relating to disease, tissue type, etc. Here is a simple example from models.py:
from django.contrib.auth.models import User
from django.db import models
class Sample(models.Model):
name = models.CharField(max_length = 255)
tags=models.ManyToManyField('Tag', through = 'Annot')
class Tag(models.Model):
name = models.CharField(max_length = 255)
class Annot(models.Model):
tag = models.ForeignKey('Tag')
sample = models.ForeignKey('Sample')
user = models.ForeignKey(User, null = True)
date = models.DateField(auto_now_add = True)
I'm looking for a query in django's ORM which will return the tags in which two users agree on the annotation of same tag. It would be helpful if I could supply a list of users to limit my query (if someone only believes User1 and User2 and wants to find the sample/tag pairs that only they agree on.)
I think I understood what you need. This one made me think, thanks! :-)
I believe the equivalent SQL query would be something like:
select t.name, s.name, count(user_id) count_of_users
from yourapp_annot a, yourapp_tag t, yourapp_sample s
where a.tag_id = t.id
and s.id = a.sample_id
group by t.name, s.name
having count_of_users > 1
While I try hard not to think in SQL when I'm coming up with django model navigation (it tends to get in the way); when it comes to aggregation queries it always helps me to visualize what the SQL would be.
In django we now have aggregations.
Here is what I came up with:
models.Annot.objects.select_related().values(
'tag__name','sample__name').annotate(
count_of_users=Count('user__id')).filter(count_of_users__gt=1)
The result set will contain the tag, the sample, and the count of users that tagged said sample with said tag.
Breaking it apart for the folks that are not used to django aggregation:
models.Annot.objects.select_related()
select_related() is forcing all tables related to Annot to be retrieved in the same query
This is what will allow me to specify tag__name and sample__name in the values() call
values('tag__name','sample__name')
values() is limiting the fields to retrieve to tag.name and sample.name
This makes sure that my aggregation on count of clients will group by just these fields
annotate(count_of_users=Count('user__id'))
annotate() adds an aggregation as an extra field to a query
filter(count_of_users__gt=1)
And finally I filter on the aggregate count.
If you want to add an additional filter on what users should be taken into account, you need to do this:
models.Annot.objects.filter(user=[... list of users...]).select_related().values(
'tag__name','sample__name').annotate(
count_of_users=Count('user__id')).filter(count_of_users__gt=1)
I think that is it.
One thing... Notice that I used tag__name and sample__name in the query above. But your models do not specify that tag names and sample names are unique.
Should they be unique? Add a unique=True to the field definitions in the models.
Shouldn't they be unique? You need to replace tag__name and sample__name with tag__id and sample__id in the query above.