ActiveRecord querying on multiple joins - ruby-on-rails-4

I have a users table associated with posts,
posts associated with comments,
comments associated with likes(status: 1,2,3,4). How can I sort the users based on likes count where status having 2 or 3 or 4.
Below I have tried:
named scope in likes model to get status with 1,2,3,4
Post.joins(comments: :likes).merge(Like.status_count)
But failing to the sort based on count. Any help

For ordering active record objects you can use order method, For Example
Assume a Users Database and i want to order it based on name, then we can do
User.order(:name) //Returns Users on ascending order of name
User.order(name :desc) //Returs Users in descending order of name
Similary you can try
Post.joins(comments: :likes).merge(Like.active.order(:status_count))
The documentation for the order method can be found in this link

Related

loopback query based related model

let's say I have Order model that hasMany Product(product_id, name, order_id) and Product belongs to Order
I want to find only those orders that have product with specific product_id.
According to https://loopback.io/doc/en/lb3/Include-filter.html
this should work, but it doesn't
getOrders?filter={"include":{"relation":"Product","scope":{"where":{"product_id":"6"}}}}
that kid of filter shows all orders no matter if it has product with id 6 or not.
where do I go wrong?
Your query should show you all orders, but it will include only products that id fits your requirements. But it may depend on db connector you're using. Based on what you've wrote I guess it's mongo, so it's not possible.
Instead, you could turn around the query and look for products where product_id is 6 and include order relation. So the query would look like this:
getProducts?filter={"where": {"product_id": 6}, "include": "orders"}

How to filter django-taggit top tags

Suppose you have a database with User objects running behind a Djano app
and you want to use django-taggit to tag User objects so you can retrieve subgroups using some convenient filtering.
Additionally you have a Dashboard where you want to display interesting statistics about used tags to glean some information about the subgroups that exists within your Users.
How would you access and display information about the top X tags
used within the Django app?
How would you access only the top X tags of an already filtered
subgroup of the User object?
While there are already a number of posts on SO that describe similar problems most of these describe workarounds or contain scattered information.
In order to make this information easier to find I will post a simple rundown of how to achieve some basic stuff using features of django-taggit that are officially supported but are not present in the official documentation.
How would you access and display information about the top X tags
used within the Django app?
In order to access and display information about the top tags used within the Django app you can use the built in function most_common like so:
top_tags = User.tag.most_common()
This returns a queryset containing all of the tags placed on a User instance ordered from most used descending order.
So say we have 3 tags: ["vegetables", "fruits", "candy"] and 10 users have a fruits tag, 4 users have a vegetables tag and only 1 user has the candy tag the returned order would be: ["fruits", "vegetables", "candy"]
Accessing more information about the tags returned can be done like so:
for tag in top_tags:
print(tag.name) #the name of the tag
print(tag.num_times) # the number of User objects tagged
Additionally if you are only interested in the top 3 tags then you can
access them like this:
top_tags = User.tag.most_common()[:3]
Where you can replace 3 with X where X is the number of items you want returned.
How would you access only the top X tags of an already filtered
subgroup of the User object?
Since Jul 12, 2016 the most_common() function actually has some additional arguments that you can specify. First of all you can specify a min_count which filters out the top tags that fall below a certain threshold. As an illustration using the tags from the previous example:
top_tags = User.tag.most_common()[:3]
returns all three tags as specified earlier but using
top_tags = User.tag.most_common(min_count=2)[:3]
only returns ["fruits", "vegetables"] this is because only 1 User object was tagged with candy meaning that it falls below the min_count of 2
An additional argument that you can provide to most_common is extra_filters this enables you to provide an object containing additional filter values that you want to filter the tags by.
One usage example would be:
filtered_users = User.objects.filter(age=20, is_delete=False)
top_tags = User.tag.most_common(
min_count=1, extra_filters={
'user__in': filtered_users
}
)
Here we create a filtered queryset of User objects that we then provide to the extra_filters argument to limit the tag search to a specific subgroup

Group user likes based on page category

Is there a way by which we can group user’s facebook likes based on the category of the pages, when I request from Graph API /[user-id]?fields=likes what I get is array of user’s likes in reverse chronological order. I need to group these likes based on the page’s category like Entertainer, Comedians, Celebrity, Artist, Actor/Director, etc categories should be grouped in a one category (say Personalities) and other pages like TV Show, Movie, TV Series, etc to be grouped in other category (let’s say Movies)
No, you would have to do any sorting on your own, after getting all the entries. You can use paging to get all entries: https://developers.facebook.com/docs/graph-api/using-graph-api/#paging

How to write query of group by

I have model named IssueFlags with columns:
id, created_at, flags_id, issue_id, comments
I want to get data of unique issue_id (latest created) with info about flags_id, created_at and comments
By sql it's working like this:
SELECT created_at, flags_id, issue_id, comments
FROM Issues_issueflags
group by issue_id
How to do the same in Django? I tried to wrote sth in shell, but there is no attribute group by
IssueFlags.objects.order_by('-created_at')
This above return me only the list of ordered data.
Try doing this way:
from django.db.models import Count
IssueFlags.objects.values('created_at', 'flags_id', 'issue_id', 'comments').order_by('-created_at').annotate(total=Count('issue_id'))
I have written annotate(total=Count('issue_id')) assuming that you would have multiple entries of unique issue_id (Note that you can do all possible types of aggregations like Sum, Count, Max, Avg inside . Also, there already exists answers for, doing group by in django. Also have a look at this link or this link. Also, read this django documentation to get a clear idea on when to place values() before annotate() and when to place it after, and then implement the learning as per your requirement.
Would be happy to help if you have any further doubts.

Django - how to filter a queryset on multiple reverse lookup matches

I have two models: Order and OrderStatus.
Don't worry about Order, but OrderStatus has the following fields:
order = models.ForiegnKey(Order)
status = models.CharField (choice that can be either ORDERED, IN_TRANSIT, or RECEIVED)
OrderStatuses are created when the Order changes status, so initially there's just an ORDERED status, then later an ORDERED and IN_TRANSIT status, then later an ORDERED, IN_TRANSIT, and RECEIVED status all exist as foriegn keys to one Order. This is to keep track of timings, etc.
I want to find all Orders which have all three statuses. In other words, all orders that have been received and are valid because they have the other two statuses.
This is returning an empty set:
Order.objects.filter(Q(orderstatus__status=OrderStatus.ORDERED) &
Q(orderstatus__status=OrderStatus.IN_TRANSIT) &
Q(orderstatus__status=OrderStatus.RECEIVED))):
... but this is working fine:
Order.objects.filter(orderstatus__status=OrderStatus.ORDERED)
.filter(orderstatus__status=OrderStatus.IN_TRANSIT)
.filter(orderstatus__status=OrderStatus.RECEIVED)
What's the difference here? Is there any way to simplify? I thought this was what Q objects are for.
This means a query where all the fields are required
Order.objects.filter(Q(orderstatus__status=OrderStatus.ORDERED) &
Q(orderstatus__status=OrderStatus.IN_TRANSIT) &
Q(orderstatus__status=OrderStatus.RECEIVED))):
This means that the third filter is applying on the result of second filter and the second filter is applying on the result of first filter
Order.objects.filter(orderstatus__status=OrderStatus.ORDERED)
.filter(orderstatus__status=OrderStatus.IN_TRANSIT)
.filter(orderstatus__status=OrderStatus.RECEIVED)
If you want to do something where you want to get the Order objects if their status is ORDERED, RECEIVED OR IN_TRANSIT you can also do something like this
Order.objects.filter(orderstatus__status__in=[OrderStatus.ORDERED, OrderStatus.IN_TRANSIT, OrderStatus.RECEIVED])