【问题标题】:Rails 3: How to get all Posts which ids are not in a given list?Rails 3:如何获取所有 ID 不在给定列表中的帖子?
【发布时间】:2011-05-20 04:00:00
【问题描述】:

要获取所有 publisher_id 等于 10、16 或 17 的帖子,我这样做:

Post.where(:publisher_id => [10, 16, 17])

我如何获得publisher_id 不等于到 10、16 或 17 的所有帖子(即除了这三个之外的所有可能的 id)?

【问题讨论】:

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


    【解决方案1】:

    只需执行一个:

    Post.where(["publisher_id NOT IN (?)", [10, 16, 17]])
    

    【讨论】:

    • 我不确定为什么需要额外的[]。这很好用:Post.where("publisher_id NOT IN (?)", [10, 16, 17])。谢谢!
    • 只是 Rails 2 以前的语法中带有 :conditions 选项的旧习惯;)不客气。
    【解决方案2】:

    在 Rails 4 中我们可以像下面那样做

    Post.where.not(:publisher_id => [10, 16, 17])
    

    它将生成如下所示的 SQL

    SELECT "posts".* FROM "posts"  WHERE ("posts"."publisher_id" NOT IN (10, 16, 17))
    

    【讨论】:

      【解决方案3】:

      未经测试,但应该像(使用 metawhere gem):

      Post.where( :id.not_eq => [10,16,17] )
      

      【讨论】:

        【解决方案4】:

        在 Rails 3 中使用 Arel 的“纯”ActiveRecord 语法,您可以执行以下操作:

        Post.where( Post.arel_table[:publisher_id].not_in([10, 16, 17]) )
        

        【讨论】:

          【解决方案5】:

          此页面上的每一个答案都是错误的,因为这些答案都不适用所有数组情况,尤其是只有一个元素的数组

          这是一个使用此页面上的任何“所谓”解决方案将失败的示例:

          @ids = [1]
          Post.where("publisher_id NOT IN (?)", @ids)
          #ERROR
          Post.where("publisher_id NOT IN (?)", [4])
          #ERROR
          #...etc
          
          #ALSO
          @ids = []
          Post.where("publisher_id NOT IN (?)", @ids)
          #ERROR
          Post.where("publisher_id NOT IN (?)", [])
          #ERROR
          #...etc
          
          #The problem here is that when the array only has one item, only that element is 
          #returned, NOT an array, like we had specified
          
          #Part of the sql that is generated looks like:
          #...WHERE (publisher_id NOT IN 166)
          
          #It should be:
          #...WHERE (publisher_id NOT IN (166))
          

          此页面上唯一真正走上正轨并处理这个非常重要案例的答案是@Tudor Constantin's。但问题是他实际上并没有展示使用他的方法来解决 OP 发布的真正抽象示例问题的“方式”(不仅仅是使用硬编码的数字)。

          这是我的解决方案,在给定要排除的 id 数组的情况下动态查找不在 Activerecord 关联中的 id,这将与 n 个元素的数组一起使用(...包括 n=1 和 n=0)

          @ids = [166]
          @attribute = "publisher_id"
          @predicate = "NOT IN"
          @ids = "(" + @ids.join(",") + ")"
          if @ids == "()"
            #Empty array, just set @ids, @attribute, and @predicate to nil
            @ids = @attribute = @predicate = nil
          end
          
          #Finally, make the query
          Post.where( [@attribute, @predicate, @ids].join(" ") ) 
          
          #Part of the sql that is generated looks like:
          #...WHERE (publisher_id NOT IN (166))
          #CORRECT!
          
          #If we had set @ids = []     (empty array)
          #Then the if statement sets everything to nil, and then
          #rails removes the blank "  " space in the where clause automatically and does
          #the query as if all records should be returned, which
          #logically makes sense!
          

          如果这对您有帮助,请投票!如果您对我的某个 cmets 感到困惑或不理解,请告诉我。

          【讨论】:

            【解决方案6】:

            我用过的解决方案:

            ids = #however you get the IDS
            Post.where(["id not in (?)", [0,*ids])
            
            • 0 的存在意味着它始终包含一个元素(假设没有任何元素的 ID 为 0)
            • ID 变成一个 splat 意味着它永远是一个数组。

            【讨论】:

              【解决方案7】:
              Post.where(" id NOT IN ( 10, 16, 17) ")
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-07-08
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多