我正在Rails中开发一个API,其中存在users
和messages
表。 users
也有性别(gender_id
),属于一个国家(country_id
),并且具有公民身份(civil_status_id
),并且messages
被创建由admins
。
到目前为止,我有这个模型。
现在我必须制定以下要求
管理员应能够根据其属性(国家,性别或公民身份)创建针对
users
的消息。另外,管理员应该能够将一条消息声明为全局消息,在这种情况下,“全部”users
应该会收到它,但也应允许例外。例如,在管理员希望向除俄罗斯和中国以外的所有国家/地区的用户发送消息的情况下。
问题是我不是Rails / SQL专家,但是我想高效地做到这一点,以便如果明天应用程序有1万或10万用户,则服务器会快速响应。
所以我在想以下问题
首先创建3个多对多关系(countries_messages
,genders_messages
和civil_statuses_messages
)。这些表的记录表示messages
与countries
,civil_statuses
和genders
之间的关系。
然后创建一个表单,管理员可以在该表单中创建一条消息,在该表单中,管理员可以通过几个选择框来选择要访问的用户的属性。用于创建消息的表单还应该具有一个复选框,以确定消息是否为全局消息,如果已标记,则我认为所选国家,性别和公民身份将是管理员想要排除的类别,即如果管理员想要向系统中的所有人发送消息,但来自加拿大的人除外,他应该标记全局选项并在选择框中选择加拿大国家(显然,这将在视图中说明)。
到现在为止,我有了这个模型。
我确实怀疑哪种方法更有效地返回与用户相对应的消息。
当管理员指定一条消息是全局消息时,除了来自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)
其他方式可能是将该消息与排除的国家/地区建立联系,即,如果我专门为ID为2的国家/地区的人发送消息,则应在{{中添加记录(country_id:2,message_id:2) 1}},但是相反,如果我向ID为2的国家/地区以外的每个国家/地区发送了一条消息,那么我还应该将记录(country_id:2,message_id:2)添加到countries_messages
。
在这种情况下,我可以知道是否排除了来自阿根廷的男性和男性的信息,例如,该信息是否具有全球性,并且与代表阿根廷和男性的国家/地区和性别记录相关联。
然后,当前用户应阅读的消息的检索将是这样的:
countries_messages
可能会有更多的方法来执行此操作,所以我想收到建议,或者如果您看到我可以进行改进以告诉您。如果有不明白的地方,问。
答案 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