草庐IT

php - 保存、组织和查询产品、选项/标签和类别

coder 2023-10-27 原文

首先,让我明确一点,我不要求任何代码;我只是想要一些关于如何实现我将要提出的问题的一般性想法/指导/意见。

我开始构建一个在线电子商务系统(Yii2 + MongoDB,所以,PHP + NoSQL),并且有两个先决条件我不完全确定如何实现而不在我的代码和数据库。

这两个先决条件是相关的,所以我将把它们解释为一个。

与任何其他严肃的电子商务一样,它也有类别。而且,与任何其他严肃的电子商务一样,每个产品都会有 tagsoptions .让我进一步解释一下我所说的 tags/options .

这些是用户在购买产品时可以选择的可用选项,例如颜色或尺寸、 Material 等。

  • 分类

  • 会有多个 general类别以及其他子类别。例如,Electronics可以是一般类别,子类别是 ComputersSmart TVs .然后,MotherboardsRAM可以是 Computers 的子类别.

    这本身可以很容易地存储在数据库中,但问题就在这里:
  • 每个产品在列出它所属的任何类别或上层类别时都应该出现。这意味着如果我(作为最终用户)浏览 Computers 中的所有项目类别,我应该看到 NVIDIA GTX670属于子类别Graphic cards类别 Computers .

  • 我可以通过以下方式保存每个产品:
    {
        _id: asdasfwetrw34tw34t245y45y,
        name: "NVIDIA GTX670",
        price: 99.50,
        ...
        ...
        categories: [
            "Electronics", //<-- just the ID of that group
            "Computers", //<-- just the ID of that group
            "Graphic cards" //<-- just the ID of that group
        ]
    }
    

    但:
  • 我不确定检索某个类别的所有项目(当然还有所有子类别的项目)的查询速度有多快。
  • 我不确定该方法还有什么其他缺点,因此,请随时推荐任何替代模式来存储它。

  • 2. 标签/选项

    这才是真正头疼的地方。

    每个选项可以属于 0 个或多个类别和子类别,因此类别 Woman fashion可以有选项sizecolor , 但类别 Sunglasses ( Woman fashion 的子类别)只能有 color ,甚至是另一组选项,与 Woman fashion 完全不同.

    此外,每个选项中的值( redgreenbluecolor 选项中)可以出现在随机类别中。所以Woman fashion会有类似 Strawberry Red 的颜色和 Tangerine , 而 Cars会有 CarbonBlack metallic .

    此外,将有几种类型的选择:
  • 完全静态(如 size ,可能只有 SM ,但不能同时是两者。无论如何,管理员将无法编写自定义大小,如 Kind of small ;他将能够只需选择它已经在数据库中的内容)。
  • 可以组合在一起的静态(如 colors ,可以是 redgreen ,或者管理员选择的颜色组合)。
  • 自由输入(如 dimensionsweight ,理想情况下,这将是要加入的输入字段和下拉值。例如 [10] | | (mg||kg|tons)[20] (cm|m|km|miles) )。

  • 我可以像这样保存每个选项:
    {
        option: "Color",
        type: "Static with combinations"
        values: [
            {
                value: "Red",
                categories: [
                    "Sunglasses"
                ]
            },
            {
                value: "Green",
                categories: [
                    "Sunglasses",
                    "T-Shirts"
                ]
            },
            {
                value: "Black metallic",
                categories: [
                    "Cars"
                ]
            }
        ],
        categories: [
            "Woman fashion", //<-- only the ID of this group
            "Cars" //<-- only the ID of this group
        ]
    }
    

    但是我担心单个选项会变成多大,当有 30 个类别并且选项的每个值都设置为出现在随机类别中时。
    另外我只是觉得它不够干净,但也许这只是我。

    无论如何,与前一点一样,请随时提出任何可以提出的建议,我将不胜感激您可以给我的任何反馈。

    最佳答案

    我也在经营一个电子商务网站。这是我关于如何实现您提到的功能的建议。希望能帮助到你。

  • 分类

  • 我将它们组织成一个扁平的结构,在你的情况下是:
        {_id: 1, name: "Electronics", parentId: 0, idPath: "/0/1/" ...}
        {_id: 2, name: "Computers", parentId: 1, idPath: "/0/1/2/", ...}
        {_id: 3, name: "Graphic Cards", parentId: 2, idPath: "/0/1/2/3/", ...}
    

    并且产品现在只需要在叶子类别中。在你的情况下:
        {
            _id: asdasfwetrw34tw34t245y45y,
            name: "NVIDIA GTX670",
            price: 99.50,
            ...
            ...
            categoryIds: [3]
        }
    

    产品当然可以是多个类别,所以categoryIds仍然是一个数组。
    这是棘手的部分。当您列出 Electronics类别,您可以通过以下方式找到其所有子类别:
        db.categories.find({idPath: /^\/0\/1/})
    
    idPath索引在这里工作,所以它会很快。当您找到所有子类别时,您可以轻松找到其中的所有产品(在 categoryIds 集合的 Product 上建立索引)。

    或者,您可以将所有类别读入内存并使用 key->categoryId, value->[all the subcategories] 构建哈希表。您的类别通常不会经常更改,并且您不会有很多类别。这样就没事了。
  • 标签/选项

  • 首先,我认为您的类别有问题。 Women fashion是通用的,你应该把你的产品放在更具体的东西上,选项也应该在那里。例如,可能有一个类别 coat其中有 size & color , 除了 women fashion .虽然可能还有color women fashion 中的选项因为它是所有子类别的共同特征。
    如果您考虑一下,为什么所有子类别都组织在一个父类别中?因为他们有共同点。该公共(public)部分应该是父类别的公共(public)选项。也就是说,所有的父类和子类之间应该有继承关系。例如:

    women fashion: color
    |-coat: size
    |-sun glasses: shape



    然后coat最终会有 2 个选项 color & size . sun glasses :color & shape .当您查看时 women fashion ,只有 1 个选项 color .它也过滤子类别,因为它们继承自 women fashion .
    至于颜色的值,我的想法是只使用标准颜色Strawberry Red实际上是 red , Tangerine实际上是 orange .当您过滤产品时,您真的不希望它们出现。否则选项太多,绝对不利于用户体验。
    然而,除了color从类别中选择,我的网站也有一个叫做 customizable options 的东西.这些选项仅在产品上定义。当您查看类别时,它们永远不会出现。在这里您可以拥有 Strawberry Red & Tangerine .在我看来,这些不是产品的“天然”特性。它们仅用于使用户在查看产品时感觉更舒适。因此,您也可以选择此类选项,例如 Tangerine with figure等等。
    关于选项的另一件事。您可能想要标记哪些选项应该用于过滤产品。例如 color绝对是其中之一。虽然 dimension也许不吧。

    关于选项类型。如果它对你来说足够了,你的就可以了。我有更多类型,例如 Number , String , Single Choice , Multiple Choices .我还计划实现 Unit . Unit的棘手部分是例如
    1GB = 1024MB = 1024*1024B
    

    所以当你拿到1GB和1TB的硬盘时,你可能要在过滤产品之前做一个转换。这是题外话,我会回到你的问题。

    请注意,虽然不同类别的选项具有相同的名称。它们不太可能是同一回事。 MaterialCoatFurniture是2种不同的东西。所以我倾向于为不同的类别定义不同的选项。因此可能有 colortoys , 和 colorwomen fashion .这与上面提到的继承并不冲突,因为从某个层面来看,子类别开始共享相同的选项。这与您如何组织类别结构完全相关。如果你想改变品类结构或移动产品一段时间,那将是痛苦的。所以在定义类别时要小心。

    这就是我脑海中浮现的全部内容。恐怕我的母语不是英语,因此您可能会发现我的答案的某些部分难以理解。随时让我知道。

    关于php - 保存、组织和查询产品、选项/标签和类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28269467/

    有关php - 保存、组织和查询产品、选项/标签和类别的更多相关文章

    1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

      我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

    2. ruby - 在院子里用@param 标签警告 - 2

      我试图使用yard记录一些Ruby代码,尽管我所做的正是所描述的here或here#@param[Integer]thenumberoftrials(>=0)#@param[Float]successprobabilityineachtrialdefinitialize(n,p)#initialize...end虽然我仍然得到这个奇怪的错误@paramtaghasunknownparametername:the@paramtaghasunknownparametername:success然后生成的html看起来很奇怪。我称yard为:$yarddoc-mmarkdown我做错了什么?

    3. ruby - 默认情况下使选项为 false - 2

      这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

    4. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

      我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

    5. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

      我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

    6. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

      我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

    7. css - 用 watir 检查标签类? - 2

      我有一个div,它根据表单是否正确提交而改变。我想知道是否可以检查类的特定元素?开始元素看起来像这样。如果输入不正确,添加错误类。 最佳答案 试试这个:browser.div(:id=>"myerrortest").class_name更多信息:http://watir.github.com/watir-webdriver/doc/Watir/HTMLElement.html#class_name-instance_method另一种选择是只查看具有您期望的类的div是否存在browser.div((:id=>"myerrortes

    8. 神州数码无线产品(AC+AP)配置 - 2

      注意:本文主要掌握DCN自研无线产品的基本配置方法和注意事项,能够进行一般的项目实施、调试与运维AP基本配置命令AP登录用户名和密码均为:adminAP默认IP地址为:192.168.1.10AP默认情况下DHCP开启AP静态地址配置:setmanagementstatic-ip192.168.10.1AP开启/关闭DHCP功能:setmanagementdhcp-statusup/downAP设置默认网关:setstatic-ip-routegeteway192.168.10.254查看AP基本信息:getsystemgetmanagementgetmanaged-apgetrouteAP配

    9. 阿里云RDS——产品系列概述 - 2

      基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于

    10. sql - 查询忽略时间戳日期的时间范围 - 2

      我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时

    随机推荐