【问题标题】:map(&:id) work but not pluck(:id)map(&:id) 工作但不 pluck(:id)
【发布时间】:2015-08-06 09:04:36
【问题描述】:

在我的部分代码中,我需要获取用户的 ID,但 pluck 没有获取它们。只有map(&:id) 可以做到。我想知道为什么。

我已经写了一个快速而肮脏的代码块来查找发生了什么

  def remove_users user_ids
    p users_to_remove.class
    users_to_remove = self.users.where(id: user_ids)
    if users_to_remove.present?
      self.users -= users_to_remove
      self.save

      p users_to_remove.class
      p users_to_remove
      Rails::logger.info "\n#{users_to_remove}\n"
      users_to_remove_map = users_to_remove.map(&:id)
      p users_to_remove_map
      Rails::logger.info "\nmap id: #{users_to_remove_map}\n"
      users_to_remove_pluck = users_to_remove.pluck(:id)
      p users_to_remove_pluck
      Rails::logger.info "\npluck id: #{users_to_remove_pluck}\n"
      #...
    end
    self.user_ids
  end

谁在我的 test.log 中返回

#<User::ActiveRecord_AssociationRelation:0x007fb0f9c64da8>


map id: [144004]

   (0.3ms)  SELECT "users"."id" FROM "users" INNER JOIN "groups_users" ON "users"."id" = "groups_users"."user_id" WHERE "groups_users"."group_id" = $1 AND "users"."id" IN (144004, 144005)  [["group_id", 235819]]

pluck id: []

在我的测试中

User::ActiveRecord_AssociationRelation
User::ActiveRecord_AssociationRelation
#<ActiveRecord::AssociationRelation [#<User id: 144004, created_at: "2015-08-06 08:55:11", updated_at: "2015-08-06 08:55:11", email: "user_2@test.com", token: "rpf5fqf5bs1ofme6aq66fwtcz", reset_password_token: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, disabled: false, first_name: "John_2", last_name: "Rivers_4", is_owner: false, organisation_id: 235826, encrypted_password: "$2a$04$8ev1j...f6ICL.ezS....", reset_password_sent_at: nil, default_language: nil, uid: nil, api_key: "rmhh...noyn">]>
[144004]
[]

奇怪的是。我有 id 的用户。 map 可以得到它们。 pluck 不是。

我也不懂sql log。如何在 sql 日志中没有任何选择的情况下获得 map id 结果?缓存?

【问题讨论】:

    标签: sql ruby-on-rails ruby-on-rails-4 activerecord


    【解决方案1】:

    pluck 不适用于数组,它适用于 ActiveRecord::Relation,其目标是避免进行完整查询以仅获取 id。

    从 db 中检索所有列后,您只需 map 即可。

    您在执行self.users -= users_to_remove 时创建数组,或者甚至在执行.present? 时创建数组,因为您应该使用.exists?

    【讨论】:

    • 再次感谢本杰明!将在几分钟内验证答案。暂时不能。
    • 但就我而言。 users_to_remove 是一个 ActiveRecord::Relation ?
    • 我在前后添加了 users_to_remove.class。我总是得到 User::ActiveRecord_AssociationRelation。会改变现在吗?存在?。谢谢
    【解决方案2】:

    这一行:

    users_to_remove = self.users.where(id: user_ids)
    

    不会立即触发 SQL 查询。只要您需要这些用户的一些详细信息,它就会发送请求。并将结果缓存在 SQL 缓存中(所以当同一个请求再次发送到 DB 时,它会被 Rails 拦截,永远不会到达数据库)。

    所以当你打电话时:

    users_to_remove.map(&:id)
    

    它使用缓存的结果。但是当你使用

    users_to_remove.pluck(:id)
    

    它重新获取结果,因为实际的 SQL 查询不同。对于#map,它是SELECT * FROM ...,对于#pluck,它是SELECT id FROM...。并且当查询到达数据库时,ID 不再属于“自我”(您在此之前删除了它们),因此它们不会被返回。

    【讨论】:

    • 嗯,我喜欢你的回答。因此,在删除用户然后使用它之前,我在变量中使用 pluck 保存了 ID。谢谢
    猜你喜欢
    • 1970-01-01
    • 2019-01-27
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多