BACKGROUND: I have Posts and Users, both of which HABTM Communities. In my Post model, I have a method for calculating a post's relevance to a given user by comparing how many communities they have in common as such:
def relevance(user)
(self.communities & user.communities).length
end
OBJECTIVE: To query Posts either by a given relevance i.e.
Post.where(:relevance => 3)
or
to query all posts and sort them by relevance i.e.
Post.all.desc(:relevance)
I know that the user variable is needed there somewhere, just wondering if something like this is possible or if a workaround exists.
You can do this in mongoDB using Aggregation Framework (new in version 2.2).
You have to have the array of User's communities available. I'll call it userComms in this example - I'm expecting it to be an array with the same type of values that posts.communities are.
db.posts.aggregate( [
{
"$unwind" : "$communities"
},
{
"$match" : {
"communities" : {
"$in" : userComms
}
}
},
{
"$group" : {
"_id" : "$_id",
"relevance" : {
"$sum" : 1
}
}
},
{
"$sort" : {
"relevance" : -1
}
}
]);
This returns a document of the form:
{
"result" : [
{
"_id" : 1,
"relevance" : 4
},
{
"_id" : 6,
"relevance" : 3
},
...
]
}
The result array contains _ids of posts and relevant as computed by adding the number of communities they had in common with user. Then it's sorted (descending) by that sum.