根据许多多对多关系返回记录列表的最快方法

时间:2018-10-06 22:44:06

标签: sql ruby-on-rails performance ruby-on-rails-5 query-performance

我正在Rails中开发一个API,其中存在usersmessages表。 users也有性别(gender_id),属于一个国家(country_id),并且具有公民身份(civil_status_id),并且messages被创建由admins

到目前为止,我有这个模型。

enter image description here

现在我必须制定以下要求

  

管理员应能够根据其属性(国家,性别或公民身份)创建针对users的消息。另外,管理员应该能够将一条消息声明为全局消息,在这种情况下,“全部” users应该会收到它,但也应允许例外。例如,在管理员希望向除俄罗斯和中国以外的所有国家/地区的用户发送消息的情况下。

问题是我不是Rails / SQL专家,但是我想高效地做到这一点,以便如果明天应用程序有1万或10万用户,则服务器会快速响应。

所以我在想以下问题

首先创建3个多对多关系(countries_messagesgenders_messagescivil_statuses_messages)。这些表的记录表示messagescountriescivil_statusesgenders之间的关系。

然后创建一个表单,管理员可以在该表单中创建一条消息,在该表单中,管理员可以通过几个选择框来选择要访问的用户的属性。用于创建消息的表单还应该具有一个复选框,以确定消息是否为全局消息,如果已标记,则我认为所选国家,性别和公民身份将是管理员想要排除的类别,即如果管理员想要向系统中的所有人发送消息,但来自加拿大的人除外,他应该标记全局选项并在选择框中选择加拿大国家(显然,这将在视图中说明)。

到现在为止,我有了这个模型。

enter image description here

我确实怀疑哪种方法更有效地返回与用户相对应的消息。

方法1

当管理员指定一条消息是全局消息时,除了来自ID为3的国家/地区的消息,然后我可以向countries_messages记录中添加诸如(country_id:1,message_id:2),(country_id:2,message_id: 2),(country_id:4,message_id:2),...等,即与ID为2的国家/地区以外的每个国家/地区建立联系。

然后重新获取当前用户应阅读的消息,如下所示:

global_messages = Message.where(global: true).ids

country_messages = current_user.country.messages.ids
gender_messages = current_user.gender.messages.ids
civil_status_messages = current_user.current_status.messages.ids

@messages = Message.find(global_messages + country_messages + gender_messages + civil_status_messages)

方法2

其他方式可能是将该消息与排除的国家/地区建立联系,即,如果我专门为ID为2的国家/地区的人发送消息,则应在{{中添加记录(country_id:2,message_id:2) 1}},但是相反,如果我向ID为2的国家/地区以外的每个国家/地区发送了一条消息,那么我还应该将记录(country_id:2,message_id:2)添加到countries_messages

在这种情况下,我可以知道是否排除了来自阿根廷的男性和男性的信息,例如,该信息是否具有全球性,并且与代表阿根廷和男性的国家/地区和性别记录相关联。

然后,当前用户应阅读的消息的检索将是这样的:

countries_messages

可能会有更多的方法来执行此操作,所以我想收到建议,或者如果您看到我可以进行改进以告诉您。如果有不明白的地方,问。

1 个答案:

答案 0 :(得分:0)

根据您的数据库选择,您可能需要考虑将消息“属性”(国家,性别,...)存储在消息表的jsonb列中。它还可以包含user_ids属性以简化操作。这些查询可能看起来有些有趣,但是您可以将范围扩大到范围中,以清除代码中的内容,甚至添加索引来加快速度。

Here is a great article on using jsonb with indexes in Rails with postgresql

您可以做的另一种选择是使用多态引用制作一个UserMessage连接表,该表可以将不同的属性与消息和用户相关联:

class UserMessage < ApplicationRecord
  belongs_to :user
  belongs_to :message
  belongs_to :messageable_type # e.g. "Country"
  belongs_to :messageable_id # e.g. some Country id
end