代码之家  ›  专栏  ›  技术社区  ›  Patricio Sard

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

  •  -1
  • Patricio Sard  · 技术社区  · 6 年前

    我正在Rails中开发一个API,其中 users messages 桌子。阿尔索 用户 有性别( gender_id country_id )也有公民身份( civil_status_id 信息 由创建 admins

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

    enter image description here

    现在我必须制定以下要求

    管理员应该能够创建目标为 用户 取决于其属性(国家、性别或公民地位)。此外,管理员应该能够将消息声明为全局消息,在本例中为“all” 用户 应该接收它,但也应该允许例外。例如,管理员希望向所有国家的用户发送消息,但俄罗斯和中国的用户除外。

    问题是我不是Rails/SQL专家,但我想让这一点更有效率,这样如果明天应用程序有一万或十万用户,服务器就会快速响应。

    所以我想

    countries_messages , genders_messages civil_statuses_messages ). 这些表的记录表示 信息 countries , civil_statuses genders .

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

    enter image description here

    方法1

    当管理员指定消息是全局消息时,除了来自id为3的国家的消息外,我可以添加到 例如(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的国家的人发送消息,则我应将记录(国家id:2,消息id:2)添加到 ,但在相反的情况下,如果我向每个国家(id为2的国家除外)发送了消息,则我还应将记录(国家id:2,消息id:2)添加到 国家信息 .

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

    然后,当前用户应该读取的消息的重试将如下所示:

    global_messages = Message.where(global: true).ids
    
    country_messages = current_user.country.messages
    gender_messages = current_user.gender.messages
    civil_status_messages = current_user.current_status.messages
    
    excluded_country_messages_ids = country_messages.where(global: true).ids
    excluded_gender_messages_ids = gender_messages.where(global: true).ids
    excluded_civil_status_messages_ids = civil_status_messages.where(global: true).ids
    
    @messages = Message.find(global_messages + country_messages + gender_messages + civil_status_messages - excluded_country_messages_ids - excluded_gender_messages_ids - excluded_civil_status_messages_ids)
    

    有更多的方法可以做到这一点,所以我想收到建议,或者如果你看到我可以做同样的改进,那么告诉我。如果有什么你不懂的,就问。

    1 回复  |  直到 6 年前
        1
  •  0
  •   codenamev    6 年前

    根据数据库的选择,您可能需要考虑将消息“attributes”(国家、性别,…)存储在消息表的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