【问题标题】:How to exclude an array of ids from query in Rails (using ActiveRecord)?如何从 Rails 中的查询中排除 id 数组(使用 ActiveRecord)?
【发布时间】:2011-06-02 15:43:45
【问题描述】:

我想执行一个 ActiveRecord 查询,该查询返回除具有特定 ID 的记录之外的所有记录。我想排除的 id 存储在一个数组中。所以:

ids_to_exclude = [1,2,3]
array_without_excluded_ids = Item. ???

我不确定如何完成第二行。

背景:我已经尝试过的:

我不确定背景是否必要,但我已经尝试过 .find 和 .where 的各种组合。例如:

array_without_excluded_ids = Item.find(:all, :conditions => { "id not IN (?)", ids_to_exclude })
array_without_excluded_ids = Item.where( "items.id not IN ?", ids_to_exclude)

这些都失败了。 This tip 可能在正确的轨道上,但我还没有成功适应它。任何帮助将不胜感激。

【问题讨论】:

  • 你试过:conditions => [ "id not IN (?)", ids_to_exclude ]吗?注意括号而不是大括号。
  • 在 Rails 3.2.1 中,我最近在查询中使用了这个 MyModel.order('created_at DESC').where('id NOT in (?)', ids_to_exclude).limit(5)

标签: activerecord ruby-on-rails-3 arel active-relation


【解决方案1】:

Rails 4 解决方案:

ids_to_exclude = [1,2,3]
array_without_excluded_ids = Item.where.not(id: ids_to_exclude)

【讨论】:

  • 这是目前最好的选择。
【解决方案2】:

这应该可行:

ids_to_exclude = [1,2,3]
items_table = Arel::Table.new(:items)

array_without_excluded_ids = Item.where(items_table[:id].not_in ids_to_exclude)

而且它完全面向对象,没有字符串 :-)

【讨论】:

  • Arel::Table 是数据库表的抽象,包含一组列。在我的系统上,我使用的是 PostgreSQL,所以该列的类型是 ActiveRecord::ConnectionAdapters::PostgreSQLColumn,它代表了我的数据库列的特征。每列包含列的名称、该列的 DB 类型、默认值、比例、精度特征等。我们需要一个 Table 实例来对 ID 列进行谓词匹配。 'not_in' 方法的类型是 Arel::Predicates,它会直接转换为您想要的 SQL,例如“不在 (1, 2, 3) 中”。
  • @sinisterchipmunk 这是因为为空数组生成的 SQL 将是 SELECT "Items".* FROM "items" WHERE "items"."id" NOT IN (NULL)。与 NULL 的匹配是 UNKOWN。这是一个三值逻辑问题:en.wikipedia.org/wiki/Three-valued_logic
  • 更漂亮的语法:Item.where(Item.arel_table[:id].not_in ids_to_exclude)
  • @marczking 字符串?呃……我觉得恶心;去躺下。
  • 这太棒了。我的用例是每周一次的订单导出,其中包含一些疯狂的数据映射,因为我们的会计已经发展了很长一段时间......我真的需要我的查询作为活动返回记录关系,因为我使用 .to_csv 类方法将我的电子商务订单映射到 csv。由于某种原因,它不适用于数组或 Order 对象,只能用于活动记录关系。我一辈子都想不出如何在我的 .where 活动记录 SQL 查询中打印我们的 id 数组,作为逗号分隔的列表。谢谢斯科特·洛 ^_^
【解决方案3】:

您也可以使用Squeel gem 来完成这样的查询。 它的文档,去here

【讨论】:

    【解决方案4】:

    正如 nslocum 所写,以下内容运行良好:

    Item.where.not(id: ids_to_exclude)
    

    如果您的“要排除的 ID”来自查询(此处带有示例条件),您甚至可以更进一步:

    Item.where.not(id: Item.where(condition: true))
    

    如果您需要过滤另一个模型,这很有用:

    OtherModel.where.not(item_id: Item.where(condition: true))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-08
      • 2015-11-29
      • 2017-12-23
      • 2015-05-19
      • 2014-04-21
      • 1970-01-01
      相关资源
      最近更新 更多