Reputation: 35
I have 2 tables with millions of records:
First table is Subscription
and second table is Message
.
In Subscription
table, I have 3 indexes:
subscription_id
msisdn
reporting_id
However, in Message
table, I only have 2 indexes:
message_id
reporting_id
I have msisdn
in Message
table but it is not indexed.
So, I have a dashboard UI that let me search for Message
.
I want to search Message
using msisdn
but since msisdn
is not indexed, the query is taking forever!
but I want to put the idea of "Indexing msisdn
in Message
table" as plan B.
So my Plan A is(which is where I need help for):
Since both table has indexed reporting_id
, I want to search for Message
using subscription.msisdn
in the dashboard, and then from there, I want to use the subscription.reporting_id
and list all the Message
with that subscription.reporting_id
.
Something like subscription.reporting_id = message.reporting_id
.
I have the view
, controller
and model
for these 2 tables,
I tried doing this in both models
has_many :message, foreign_key: :reporting_id
in Subscription.rb
and
belongs_to :subscription
in Message.rb
but it didn't work.
In my view
, the search_field for MSISDN
is currently search for record from subscription.msisdn
Does anyone knows how can I achieve that?
PS: I want to prevent from editing the table structure.
Upvotes: 1
Views: 1136
Reputation: 35
Found the solution!
In my Message.rb
, I did:
belongs_to :subscription, foreign_key: :reporting_id, primary_key: :reporting_id
and it generated this query
SELECT `subscription`.* FROM `subscription` WHERE `subscription`.`reporting_id` = '1eaa7a61fe635005c81df347b1a7c401' LIMIT 1
Upvotes: 0
Reputation: 36
have to add primary key as well
has_many :message, foreign_key: :reporting_id, primary_key: :reporting_id
in Subscription.rb
Upvotes: 1
Reputation: 1776
If you want to establish a has_many :messages
association in the Subscription class, you'll need to specify the primary_key.
class Subscription < ApplicationRecord
has_many :messages, foreign_key: "reporting_id", primary_key: "reporting_id"
end
With this, the SQL generated will look like this:
SELECT "messages".* FROM "messages" WHERE "messages"."reporting_id" = $1 [["reporting_id", "#{reporting_id}"]]
The primary_key ensures the reporting_id
value of the Subscription
model is used, else it will default to the id column.
However, rather than establishing this association which doesn't seem exactly normalized(atleast 3NF), you can just have a query to find all messages using the msisdn and reporting_id. Something like this should still be effective:
Message.
joins("INNER JOIN subscriptions ON subscriptions.reporting_id = messages.reporting_id").
merge(Subscription.where(msisdn: "#{value}"))
Upvotes: 2