Mongoid Query DB by Virtual Attribute

2019-08-05 06:16发布

问题:

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.

回答1:

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.