1

I'm working on an existing app which has the structure (simplified and) described below. One of our new queries is to find all activity in a company which is rather complicated and non-performant to build. It seems hard to write the query in ActiveRecord, so, I'm trying to use Scenic and build a Materialized View since this query is going to be mostly read-only.

So, we have Person, Group, Project, Report, Update and ActivityReceipt along with some join models. A person belongs to various groups and various projects.

My goal is to get show a feed of group activity of all of groups that a member is part of, so I'm looking to performantly fetch Activity by group, along with the author information, sorted by time and it seems like a materialized view with the following columns would make that happen:

activity_receipt_id, group_id, person_id
class Person < ApplicationRecord
  has_many :groups
  has_many :projects

end

class Membership < ApplicationRecord
  # id, group_id, person_id
  belongs_to :group
  belongs_to :person

end

class Company < ApplicationRecord
  has_many :projects
  has_many :people

end

class GroupDonation < ApplicationRecord
  # id, group_id, project_id
  belongs_to :group
  belongs_to :project_id

end

class Project < ApplicationRecord
  has_many :group_donations
  has_many :people
end

class ActivityReceipt < ApplicationRecord
  # polymorphic belongs_to relation to 'postable' which are reports, & updates
  # so, it has id, postable_id, and postable_type as columns and then other specific metadata
  belongs_to :postable
end

class Report < ApplicationRecord
  # project_id, membership_id and other specific metadata
  belongs_to :project
  belongs_to :membership #to track the author

  has_one :activity_receipt
end

class Update < ApplicationRecord
  # project_id, membership_id and other specific metadata
  belongs_to :project
  belongs_to :membership #to track the author

  has_one :activity_receipt
end

Conceptually, the query is for all the given group_ids, fetch the associated projects and then their associated reports & updates, and then their activity receipts which is eventually needed. I'm not very familiar with writing SQL to generate a view so I have been struggling on how to make such a materialized view with polymorphic relations, and if it is even possible / recommended

Here is what I have so far:

SELECT groups.id AS group_id, people.id AS people_id, activity_receipts.id as activity_receipt_id
FROM groups
JOIN group_donations ON group_donations.group_id = groups.id
JOIN projects ON projects.id = group_donations.group_id
JOIN reports ON reports.project_id = project.id
JOIN updates ON updates.project_id = project.id
JOIN activity_receipts ON 
// Stuck here
halfer
  • 19,824
  • 17
  • 99
  • 186
geoboy
  • 1,172
  • 1
  • 11
  • 25
  • To my understanding, a materialized view is just like a normal table except that you can't insert data into it. So you can use it in the query like a normal table. In case, you don't know what a materialized view is, this article may be helpful https://spin.atomicobject.com/2018/04/09/postgres-materialized-views/ – vidang Feb 29 '20 at 08:40

0 Answers0