I'm tryin to get specific keywords that MAY be related ONLY to specific users and the return the relationships.
Keyword.where(text: ['key1', 'key2'])
.tagged_users(:u, :rel)
.where(uid: [100, 101])
.pluck(:rel).each_with_object({}) do |rel, obj|
uid = rel.to_node.uid
keyword = rel.from_node.text
obj[uid] ? obj[uid] << keyword : obj[uid] = [keyword]
end
Assuming we have only one relationship with User 100 tagged with Keyword 'key2' the desired result is { 100 => ['key2'] }
The above code works, but for each rel
it's performing 2 queries to the db; one for rel.to_node
and one for rel.from_node
.
I was hoping there is a solution to 'eager load' the rel.from_node
and rel.to_node
so only one query will be executed for the entire snippet.
(Another solution would be to run for each keyword and getting it's tagged users but this is also requires many queries.)
The solution was to add with_associations
so we don't even need the relation object.
def self.uids_to_keywords(keywords, user_ids)
Keyword.where(text: keywords).tagged_users.with_associations(:keywords)
.where(user_id: user_ids).each_with_object({}) do |user, obj|
obj[user.user_id] = keywords & user.keywords.map(&:text)
end
end