gpt4 book ai didi

php - 向下钻取/过滤搜索的设计模式

转载 作者:行者123 更新时间:2023-12-03 15:11:48 25 4
gpt4 key购买 nike

我希望为网站构建一个强大的搜索功能,类似于 NewEgg 的下钻搜索,例如,

http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&N=2010150014%201035507776&name=7200%20RPM

我正在处理各种类似于具有不同标准的产品的对象。任何人都可以推荐一个好的设计来构建像 NewEgg 这样的搜索引擎吗?

最佳答案

“垂直”存储数据,即在 Entity-Attribute-Value 中(EAV) 格式以及 EAV 隐含的 [元] 数据驱动模式管理,提供了一个框架,其中每个产品的属性彼此“独立”。这反过来又促进了下钻的实现(即查询的引导式细化,其中在每个步骤中,最终用户都被提供了仍然适用的可能属性列表,对于每个这样的属性,可能值的列表)。

一个小小的警告是,这更适用于较小的目录(比如少于 100 万个产品),因为 EAV 模型可能会在较大的数据库中引入一些性能和/或扩展问题。性能受到关注的实际大小因目录的具体情况而异(每个产品的平均属性数、不同类型产品之间属性的共性、“本体”的一般复杂性等),但 EAV 是相当小目录的方法。除了对“向下钻取”过滤的支持外,它还介绍了灵活的数据模式(添加/删除属性和/或产品类型等的能力,无需更改物理(数据库)模式;只有逻辑模式是改变)。

编辑 :有关 EAV 的更多详细信息/资源
诚然,维基百科关于它的文章有点抽象......
简而言之,该模型确定了以下概念:

  • 实体(又名产品或物品)= 传统关系术语中的“记录”
  • 属性 = RDBMS 术语中的“列”(又名“字段”)
  • 值 = 给定记录的给定列的数字(或字符串或其他)值。
  • 类型(又名类别)= [松散地] RDBMS 中的“表”,即一组通常共享相同属性集的记录。

  • 为了说明这一点,例如,电子产品目录,实体可以是特定的“平板显示器”,其类型可以是“显示设备”,其属性可以是“尺寸”、“分辨率”、“价格”等。

    使用 EAV,大部分信息存储在两个表中,称为 Product 表和 ProductAttributes 表:
    Product table  
    "ProductID" (primary key, the "EntityId")
    "TypeId"
    optionally, some common attributes found in all/most other Products, say...
    price
    ManufacturerId
    Photo

    ProductAttributes table
    "ProductID" (Foreign Key to Product table)
    "AttributeID" (FK to Attribute table)
    "Value" (actual value; note: sometimes we can have several SQL fields for
    this say IntValue, StringValue, DateValue, allowing to store
    values in their natural format)

    上面的表构成了大部分数据,并辅以存储目录的 [逻辑] 模式的表,也称为“元数据”。这些表包括:
  • 定义属性的属性表:名称、数据类型、isRequired 等。
  • 定义类型(类别)的类型表:名称,在分层本体的情况下可能是父类型。
  • Type_Attributes,其中列出了给定类型的可能属性(例如:“电视机”具有属性“ channel 数”、“屏幕尺寸”等,而“VCR”具有属性“磁头数”、“支持的格式” 、“体色”等

  • 与逻辑模式在 SQL 模式中“硬编码”的传统方法相比,所有这些似乎都有些复杂,即我们有一个“TVSets”表,每个属性都有一个列集,然后是一个“VCR”表它自己的不同的列/属性集。然而,使用这种方法,应用程序逻辑最终会以某种方式(如果只是通过排序映射中的间接)对表名和列名进行硬编码。
    相比之下,EAV 模型允许程序发现可能类型的列表,以及对于每种类型的可能属性列表(必需的或可选的)。此外,由于属性值都存储在同一个表中,因此可以过滤属性而不考虑产品的类型(或子类型)。例如,要让所有商品都低于 50 美元(在另一种方法中,我们可能不得不查看几十张 table )。

    回到“向下钻取”功能...
    一旦执行初始搜索(例如搜索名称 [全文索引] 包含单词“屏幕”的所有产品),ProductAttributes 表可以生成所有不同 AttributeID 的不同列表(因此通过在 Attributes 表中查找属性名称)满足第一个搜索条件的产品。
    在用户选择给定属性(比如“制造商”)后,ProductAttributes 表可以生成不同的制造商列表(以及每个制造商的产品数量)。(或者,可以最初而不是懒惰地搜索此类信息,当用户要求)。
    然后用户选择一个给定的制造商(或几个),并运行一个新的查询以减少初始结果列表。可能的属性列表(以及每个属性内的可能值列表)减少了,因为最初选择的一些产品(实体)现在被排除在外。
    该过程继续进行,为最终用户提供对目录的引导搜索。当然,用户可以回溯等。

    为了可能有助于这个冗长的解释(或者可能进一步混淆读者......),以下代码段提供了更准确的指示,可以使用这种结构来实现搜索。此代码适用于上述解释中使用的表名,可能包含一些拼写错误,但通常提供事物的 flavor 。此外,这是用公共(public)表表达式 (CTE) 编写的,但也可以编写为子查询。也不是我们不连接逻辑模式(元数据)表,但也可以这样做,以直接在结果集中获取属性名称、类型名称等。
    正如前面所暗示的,支持这种架构的查询和逻辑更复杂,但也更通用,更能容忍存储的项目类型及其属性的变化。当然,这种类型的查询是根据最终用户提供的当前搜索条件列表动态生成的。
    WITH SearchQry AS (
    SELECT ROW_NUMBER() OVER (ORDER BY P.EntityId ASC) AS RowNum,
    P.EntityId AS EId
    FROM Products P
    INNER JOIN ProductAttributes PA1 ON P.EntitityId = PA1.EntityId and PA1.AttributeID = <some attribute id, say for Manufacturer>
    INNER JOIN ProductAttributes PA2 ON P.EntitityId = PA2.EntityId and PA2.AttributeID = <some other attribute id, say for Color>
    -- here for additional PAn JOINs as more criteria is added
    WHERE P.ProductType IN (ProdId_x, ProdId_y, ProdId_z) -- for example where these x,y,z Ids correspond to say "TV Sets", "LapTop Computers" and "PDAs" respectively
    AND PA1.Value = 'SAMSUNG' -- for example
    AND PA2.Value = 'YELLOW' -- for example
    GROUP BY P.EntityId
    )

    SELECT P.EntityId, PA.AttributeId, PA.Value -- PA.IntValue (if so structured)
    FROM (SELECT * FROM SearchQry WHERE RowNum BETWEEN 1 AND 15) AS S
    JOIN ProductAttributes PA ON PA.EntityId = S.EId
    INNER JOIN Products P on P.EntityID = PA.EntityId
    ORDER BY P.EntityId, P.AttributeId -- or some other sort order

    抱歉,解释太长了,网上可能[可能]对此有更好的描述,但我还没有找到......

    关于php - 向下钻取/过滤搜索的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2350506/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com