新手问题 [电子商务] 商品属性筛选问题

stephen · 2015年03月12日 · 最后由 liupingok 回复于 2017年05月09日 · 3454 次阅读

现在的思路是,用户每点击一下属性下的属性值,就会向后台发送一次请求,然后根据返回的数据更新这几个。 每次发送数据,会把已经点击了的作为一个数据,还未点击的作为一个数据,发送到后台。然后根据这两个数据搜索数据库, 得出未选择的属性里,哪些属性值是要禁选的。 但是怎样搜索数据库,我想了很久,试了很多,还不能成功,请教下各位! 数据表设计我是参考 spree 的,如下:

#分类
class Taxon < ActiveRecord::Base
  has_many :products, dependent: :destroy
  has_many :option_types, dependent: :destroy
end
#商品
class Product < ActiveRecord::Base
  belongs_to :taxon
  has_many :product_option_types, dependent: :destroy, inverse_of: :product
  has_many :option_types, through: :product_option_types
  has_many :variants, dependent: :destroy
end
#变体
class Variant < ActiveRecord::Base
  belongs_to :product
  has_many :order_products
  has_many :option_value_variants, dependent: :destroy, inverse_of: :option_value
  has_many :option_values, through: :option_value_variants
end
#属性
class OptionType < ActiveRecord::Base
  has_many :option_values, dependent: :destroy\

  has_many :product_option_types, dependent: :destroy, inverse_of: :option_type
  has_many :products, through: :product_option_types
end
#属性值
class OptionValue < ActiveRecord::Base
  belongs_to :option_type
  has_many :option_value_variants, dependent: :destroy, inverse_of: :variant
  has_many :variants, through: :option_value_variants
end

你是不是想实现像 taobao 买裤子:2 尺 黑色的?? 属性组合呢?

class Variant < ActiveRecord::Base
   include WithOptions
end
module WithOptions
  extend ActiveSupport::Concern

  module ClassMethods
    def find_by_options(options={})
    end

    def collect_by_option_values(option_value_ids = [])
      scope = current_scope
      return scope unless option_value_ids.is_a?(Array)

      option_value_ids.each_with_index do |option_value_id, idx|
        option_value = OptionValue.find_by id: option_value_id
        if option_value.present?
          map_aliased = "product_variant_option_value_maps_#{idx}"
          scope = scope.joins("INNER JOIN product_variant_option_value_maps AS #{map_aliased} ON #{map_aliased}.product_variant_id = product_variants.id").where("#{map_aliased}.option_value_id" => option_value_id)
        end
      end
      return scope.uniq
    end

    def find_by_option_values(option_value_ids = [])
      collect_by_option_values(option_value_ids).first
    end

  end
end

@yangman_wenzhu 是的 @as181920 谢谢,我仔细阅读下

@as181920 请问 current_scope 是什么?太高深,尝试过搜索,还是不是很明白!

ActiveRecord 可以链式调用嘛,where().where().order().select() 等等,在中间环节的对象就可以用过 current_scope 获取到,(返回实例对象是 ActiveRecord::Relation,但是在 class method 里面可以用 current scope 这个方法获取)

然后在 current_scope 上面再加后面的链式调用,就是下面代码的 each 的时候一个个链上去的 current_scope 是 AR 自己的一个方法,所以我用了 scope 临时变量来存,避免和系统方法有冲突。

也可以放到代码中,加断点进去看下,就知道 current scope 获取的是什么东西了。

有错误的地方,其它同学帮指出。

@as181920 那参数应该就是给选中的 option_value_ids 吧?我传递一个 option_value_id 为 69 的,我数据库有,但是返回的是空!

#6 楼 @stephen option_value_ids 是数组 [69],比如红色男款,红色 id 是 69,男款是 79. 参数 [69,79],是正好红色男款 参数 [69],是红色所有款

如果 option_valud_id 是 69,并且和 variant 是有关系的(关联表 product_variant_option_value_maps),如果存的时候没有关联关系,数据层面都不知道他们之间的关系,自然找不到。

我上路了,其它要明天看了。

这种问题,可以考虑 MySQL 之外的解决方案。因为这种搜索方案会越来越复杂。考虑使用 ElasticSearch 的全文索引方案, {key: value} 的属性匹配搜索会高效很多。

@as181920 我也是传递 [69],数据层面也是有联系的·

#9 楼 @stephen 那就看最终 sql 对不对吧

#8 楼 @wppurking 这种核心逻辑方 es 好么,而且要频繁变更和实时更新哦。还是简单点用 postgres 的 hstore 或者 json。

其实更简单就像微店那种加个字段商户自己填写也可以,没必要都搞到 taobao 这么复杂。

@as181920 那如果是商家后台自动生成订单的选择呢?有什么好的交互建议么?有时候觉得 taobao 真的是复杂了点

#12 楼 @stephen 后台自动生成订单?逻辑上也得知道是哪个规格或者是默认规格(无规格商品),才好技术上代码实现。 弄个 string 字段,自由发挥填写规格名称,其实很方便。

@as181920 是商家在后台手动生成订单,他要选择商品。

如果输入一个没规格的名字呢?怎么和后台数据关联?
你的意思是不是比如一件衣服是红色大码,就直接用string保存红色大码,前台也显示红色大码,就是一组属性,直接换成一条用商家自己输入的string代替?

我以前在一个小一点的系统里面用 taggable 实现过,这些属性比较松散。

wppurking 回复

这种筛选用 elasticsearch 如何设计字段?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号