【问题标题】:Rails, acts_as_taggable_on: how to get all aricles without tagsRails,acts_as_taggable_on:如何获取所有没有标签的文章
【发布时间】:2011-10-20 17:22:50
【问题描述】:

我正在使用acts-as-taggable-on。我有文章模型:

class Article < ActiveRecord::Base
  acts_as_taggable_on :tags
end

我知道如何找到所有带有“tag”标签的文章。根据自述文件,解决方案是:Article.tagged_with("tag")

但是如何找到所有没有标签的文章呢?

【问题讨论】:

    标签: ruby-on-rails ruby tags find acts-as-taggable-on


    【解决方案1】:

    使用经典的 SQL 技巧:左连接,然后选择第二个 ID 为空的行。

    Article.
      joins(%Q{LEFT JOIN taggings ON taggings.taggable_id=articles.id AND taggings.taggable_type='Article'}).
      where('taggings.id IS NULL')
    

    【讨论】:

    • @daniel,没有很好的 Rails 方式来处理复杂的连接。除此之外,请参阅codinghorror.com/blog/2007/10/…
    • 是的,我同意Article.tagged_with(Tag.all.map(&amp;:to_s), :exclude =&gt; true) 更像是 Rails 方式。但我正在使用 Rails 2.3 并希望像 named_scope 一样使用它,所以这是唯一的方法......
    • @petRUShka,同样,这个查询效率更高。
    • 该解决方案在某些情况下不起作用。我遇到了以下情况:一些标签没有被删除,但是 tag_list 是空的。
    • 这是发挥其性能的最佳方式。不要使用Article.tagged_with(..., :exclude =&gt; true) 之类的方式,因为很多类似查询,它有性能问题。
    【解决方案2】:

    根据the source 的acts-as-taggable-on,您可以使用:exclude 选项:

    ##
    # Return a scope of objects that are tagged with the specified tags.
    #
    # @param tags The tags that we want to query for
    # @param [Hash] options A hash of options to alter you query:
    #                       * <tt>:exclude</tt> - if set to true, return objects that are *NOT* tagged with the specified tags
    #                       * <tt>:any</tt> - if set to true, return objects that are tagged with *ANY* of the specified tags
    #                       * <tt>:match_all</tt> - if set to true, return objects that are *ONLY* tagged with the specified tags
    #                       * <tt>:owned_by</tt> - return objects that are *ONLY* owned by the owner
    

    因此,在您的实例中,只需执行以下操作:

    Article.tagged_with("tag", :exclude => true)
    

    编辑:刚刚意识到您要求的文章没有任何标签,在这种情况下,您需要将所有标签的列表提供给该方法:

    Article.tagged_with(Tag.all.map(&:to_s), :exclude => true)
    

    【讨论】:

      【解决方案3】:

      SQL 方式看起来很老套,使用 map 肯定会很慢。

      在这里您可以使用两个查询(rails 4):

      ids = Taggings.where(taggable_type: "Article").collect(&:taggable_id).uniq
      Article.where.not(id: ids)
      

      【讨论】:

        【解决方案4】:

        您可以只使用选择功能。我猜 SQL 解决方案效率更高,但这看起来更好:

        Artical.all.select{|a| a.tags.count == 0 }
        

        【讨论】:

          【解决方案5】:

          我相信这是您从 Rails 5 开始可以做的事情。

          Article.left_joins(:taggings).where(taggings: { tag_id: nil })
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-04-05
            • 2014-03-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多