有效查询多语言类别和类别项

时间:2015-09-22 19:41:58

标签: mysql ruby-on-rails ruby-on-rails-4

所以我有一点服务器响应时间问题 - 我认为这是由于过时的查询引起的。我有一个主要的查询链需要370毫秒,这显然是一个问题。

以下是要求:

  1. 5种不同的语言
  2. 有几个产品类别(即Cat 1,Cat 2,Cat 3等)
  3. 显示的类别取决于语言。例如,虽然类别1以所有语言显示,但类别2仅在德国和法国显示,但不在英国显示
  4. 每个类别包含x个项目( has_many belongs_to relationship )。有些项目再次以某些语言显示,有些则不是。例如,即使类别2显示在法国和德国,也只有在德国,您可以购买第1项,因此第1项不应在法国展示,而应在德国展出。
  5. 类别和项目确实具有以区域设置命名的布尔字段。这样我就可以通过flag设置是否以特定语言显示类别和项目。
  6. 我的解决方案:

    构建解决方案非常简单。在控制器中,我读出了当前语言环境的所有类别:

    application_controller.rb(因为它在每一页上使用)

    @product_categories = ProductCategory.where("lang_" + I18n.locale.to_s + " = ?", true)
    

    在视图(导航)中,我执行以下操作:

    布局/资产净值/ productnav.html.haml

    - @product_categories.each do |category|
      ...
      - category.products.includes(:product_teasers).where("lang_" + I18n.locale.to_s + " = ? AND active = ?", true, true).in_groups_of(3).each do |group|
        ...
    

    此解决方案的问题是每次我向数据库发出大量查询。使用"包括"没有解决它,因为我无法指定要拉的项目。此外,我需要循环中的in_groups_of(3)在页面上正确显示项目。

    我也在调查memchached解决方案,将查询缓存在一起 - 即Dalli但是,这需要我更改大量代码,因为我猜我需要查询每种语言的所有类别并缓存它们。除此之外,我必须根据语言查询每个项目的每个项目并以某种方式存储在数组中?

    我的问题:

    如何处理?必须有一个更简单,更有效的解决方案。如何有效查询分别缓存这个?

    谢谢!

    更新:

    这里要求的是我的两个模型:

    1。)ProductCategory

    class ProductCategory < ActiveRecord::Base
      translates :name, :description, :slug, :meta_keywords, :meta_description, :meta_title, :header, :teaser, :fallbacks_for_empty_translations => true
      extend FriendlyId
      friendly_id :name, :use => [:globalize, :slugged]
      globalize_accessors :locales => [:at, :de, :ch_de, :ch_fr, :fr, :int_en, :int_fr], :attributes => [:slug]
    
      has_paper_trail
      has_many :products, :dependent => :destroy
    
      validates :name, presence: true, uniqueness: { case_sensitive: false }
      default_scope { includes(:translations) }
    
      private
      def slug_candidates
        [
            [:name]
        ]
      end
    end
    

    2。)产品 每个产品类别都可以有0..n个产品,每个产品必须属于一个类别。

    class Product < ActiveRecord::Base
      translates :slug, :name, :meta_keywords, :meta_description, :meta_title, :teaser, :power_range, :product_page_teaser, :product_category_slider_teaser, :fallbacks_for_empty_translations => true
      extend FriendlyId
      friendly_id :name, :use => :globalize
    
      before_save :change_file_name
    
      searchable do
        text :name, :teaser, :product_page_teaser, :product_category_slider_teaser
        integer :product_category_id
      end
    
      belongs_to :product_category
      has_many :product_teasers, :dependent => :destroy
      has_many :product_videos, :dependent => :destroy
      has_many :product_banners, :dependent => :destroy
      has_many :product_documents, :dependent => :destroy
      has_many :product_tabs, :dependent => :destroy
      has_many :active_relationships, class_name:  "Relationship",
               foreign_key: "follower_id",
               dependent:   :destroy
      has_many :passive_relationships, class_name:  "Relationship",
               foreign_key: "followed_id",
               dependent:   :destroy
      has_many :following, through: :active_relationships, source: :followed
      has_many :followers, through: :passive_relationships, source: :follower
      has_many :references
    
      has_and_belongs_to_many :contacts
    
      accepts_nested_attributes_for :product_teasers, :reject_if => :all_blank, :allow_destroy => true
      accepts_nested_attributes_for :product_tabs, :reject_if => :all_blank, :allow_destroy => true
      accepts_nested_attributes_for :product_videos, :reject_if => :all_blank, :allow_destroy => true
      accepts_nested_attributes_for :product_banners, :reject_if => :all_blank, :allow_destroy => true
      accepts_nested_attributes_for :product_documents, :reject_if => :all_blank, :allow_destroy => true
    
      has_paper_trail
      validates :name, presence: true, uniqueness: { case_sensitive: false }
      default_scope {includes(:translations)}
    
      .... a lot more going on here ...
    
    end
    

    请注意:该类别包含语言标记(布尔值),即lang_at,lang_de,lang_fr等,如果设置,则此类别以该特定语言显示。 SAME适用于产品,因为某些产品并未按类别显示在所有语言中。

    示例:

    @product_categories = ProductCategory.where("product_categories.lang_" + I18n.locale.to_s + " = ?", true)
    
    @products = Product.where("product_categories.lang_" + I18n.locale.to_s + " = ?", true)
    

    我在上面的目的中跳过任何包含 - 它只是为了演示语言逻辑。

1 个答案:

答案 0 :(得分:0)

<强>更新

系统花了很多时间在嵌套循环中循环数据。避免在嵌套循环中获取数据。您必须使用join或includes来更有效地捕获数据。例如:

<强>控制器

@products = Product.includes(:product_category).where("product_categories.lang_" + I18n.locale.to_s + " = ? AND product_categories.active = ?", true, true).group_by(&:category)

查看

- @products.each do |category, products|
  <%= category.name %>
  - products.each do |product|
    <%= product.title %>

需要修复必要的代码。我只是帮助主要查询。例如:active = ?用于product字段或product_categories字段。我希望它可以帮到你。