
Question:
I have a contact and a lead. They are completely two independent models. I have a leads page where I can query against leads, sort by leads and do other work on leads. Also, a contact can be created without a lead. However, a contact can has_one
lead. So I set up my models like so:
class Contact
include Mongoid::Document
has_one :lead
field :reference_number
field :some_date
end
class Lead
include Mongoid::Document
belongs_to :contact
field :status
end
Here is the problem. On the leads page, I want to sort leads by the reference_number which is an attribute of the contact. Because Contact and Lead are independent models, I cannot embed a lead into a contact, because I need to query leads on their own. So embed_one
is NOT a solution. The other option I first tried was sorting using ruby, but with 10,000+ documents, this was extremely slow and quickly faded as a solution:
Lead.order_by( id: all.sort_by { |lead| lead.contact.reference_number }.map(&:id) )
So the only remaining solution is using some type of cache. First, I tried using a hash field like this:
class Lead
...
field :denormalized_fields, type: Hash, default: {}
But this is not good either, because I still cannot sort by key/value pairs in a hash. This would not work:
Lead.order_by(denormalized_fields['reference_number'] => 'asc')
So I only have one remaining idea, but I am not sure if this is a good solution either. I introduce a new document called ParentAttribute:
class ParentAttribute
include Mongoid::Document
field :reference_number
end
class Contact
include Mongoid::Document
has_one :parent_attribute
has_one :lead
end
class Lead
include Mongoid::Document
belongs_to :contact
embeds_one :parent_attribute
end
Now when I create a contact, rather than storing fields in Contact, I store it in ParentAttribute. And a Contact will still has_one
lead, but I can also query against the attributes in Lead:
Lead.order_by(:'parent_attributes.reference_number' => 'asc')
I have no other ideas. Can I get some insights into my issue here?