【问题标题】:How to filter the values of a model column, that don't exist in the database?如何过滤数据库中不存在的模型列的值?
【发布时间】:2016-06-01 09:08:33
【问题描述】:

给定一个模型 ID 数组:

ids = [1, 2, 3]

如何获取数据库中尚不存在的 id 数组?我能做到:

ids.reject { |id| Model.exists?(id: id) }

但我不想为每个 id 进行单独的数据库查询。在单个数据库查询中获取不存在的 id 的方法是什么?

【问题讨论】:

  • 不确定 RoR 语法,但 SQL 方法是;创建一个包含 [1,2,3] 的数据集,然后找出目标表中不存在的数据集...SELECT sample.* FROM (SELECT 1 AS id UNION ALL SELECT 2 AS id UNION ALL SELECT 3 AS id) sample LEFT JOIN target ON target.id = sample.id WHERE target.id IS NULL
  • @MatBailie +1 提供纯 SQL 解决方案

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


【解决方案1】:

如果您使用的是 rails 4 或更高版本,您可以使用如下所示

ids = [1, 2, 3]
existing_ids = Model.where(id: ids).ids
ids - existing_ids

如果您使用的是 rails 3,则需要

ids = [1, 2, 3]
existing_ids = Model.where(id: ids).pluck(:id)
ids - existing_ids

阅读更多关于 pluckids herehere 的信息。

感谢Stefan 向我指出ids 方法。

【讨论】:

  • 你可以用.ids代替.pluck(:id)
  • 谢谢@Stefan。这对我来说是新鲜事。我正在更新答案。
【解决方案2】:

TL;DR : 如果ids 是您要检查的 id 数组,而 MyModel 是您的模型的名称,那么以下是不存在的 id 数组:ids - MyModel.where(id: ids).pluck(:id)


MyModel.where(id: ids) 将返回 MyModel 的所有记录,其 id 与您的 ids 数组的值之一匹配。但是,如果您添加 .pluck(:id) 将返回一个仅包含这些记录的 id 的数组。所以MyModel.where(id: ids).pluck(:id) 是与您的ids 数组值匹配的记录ID 数组。

然后您可以使用减号运算符来区分两个数组。 array1 - array2 只返回array1 中不在array2 中的元素。

所以把所有东西放在一起你就得到了ids - MyModel.where(id: ids).pluck(:id)

【讨论】:

  • 感谢您的回答。两件事:您不需要 all 来代替 pluck,您可以直接执行 MyModel.pluck(:id) 并且 Sebin 的答案更有效率,因为它可能会实例化一个较小的数组(还没有 bench-虽然标记了它)。
  • @AlexPopov 看来你没有看到我的编辑,但我已经编辑了我的答案以使其更有效,正如你所说的那样;)
猜你喜欢
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
  • 2020-10-24
  • 1970-01-01
相关资源
最近更新 更多