我正在寻找为网站构建强大的搜索功能,类似于NewEgg的深入搜索,例如,
http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&N=2010150014%201035507776&name=7200%20RPM
我正在处理各种类似于具有不同标准的产品的对象.任何人都可以推荐一个很好的设计来构建像NewEgg这样的搜索引擎吗?
mjv*_*mjv 22
将数据"垂直地"存储,即以实体 - 属性 - 值(EAV)格式存储,以及对EAV隐含的[meta]数据驱动的模式管理,提供了每个产品的属性彼此"独立"的框架.这又有助于向下钻取的实现(即,查询的引导细化,其中在每个步骤向最终用户提供仍然适用的可能属性的列表,对于每个这样的属性,可能值的列表).
一个小小的警告是,这更适用于较小的目录(比如少于100万个产品),因为EAV模型可能会引入更大数据库的一些性能和/或扩展问题.性能受到关注的实际大小因目录的具体情况而异(每个产品的平均属性数,不同类型的产品之间的属性的共性,"本体"的一般复杂性等),但EAV非常相似如何去寻找更小的目录.除了支持"向下钻取"过滤之外,它还介绍了灵活的数据模式(添加/删除属性和/或产品类型等的能力,无需更改物理(数据库)模式;只有逻辑模式是改变).
编辑:关于EAV的更多细节/资源
不可否认,关于它的维基百科文章有点抽象......
简而言之,该模型确定了以下概念:
例如,用电子产品目录来说明这一点,实体可以是特定的"平面显示器",其类型可以是"显示设备",其属性"大小","分辨率","价格"等.
使用EAV,大部分信息存储在名为Product table和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)
Run Code Online (Sandbox Code Playgroud)
上面的表格构成了大部分数据,并且由存储目录的[逻辑]模式的表格补充,也称为"元数据".这些表格包括:
所有这些看起来有点复杂,与传统的方法相比,逻辑模式在SQL模式中是"硬编码"的,即我们有一个"TVSets"表,每个属性有一组列,然后是一个"VCR"表.它自己的,不同的列/属性集.然而,通过这种方法,应用程序逻辑以某种方式(如果仅通过各种映射中的间接)以表和列名称结束硬编码.
相比之下,EAV模型允许程序发现可能类型的列表,并且对于每种类型,可能的属性列表(要求或可选).此外,由于属性值都存储在同一个表中,因此无论产品的类型(或子类型)如何,都可以对属性进行过滤.例如,要使所有物品的价格低于50美元(在另一种方法中,我们可能不得不查看十几张表格).
返回"向下钻取"功能...
一旦执行了初始搜索(比如搜索名称[全文索引]包含单词"screen"的所有产品),ProductAttributes表可以生成所有不同的不同列表对于满足此第一搜索条件的产品,AttributeID(因此通过在Attributes表中查找属性名称).
在用户选择给定属性(例如"制造商")时,ProductAttributes表可以生成不同的制造商列表(以及每个制造商的产品数量).(或者,可以在最初搜索此类信息而不是懒惰,用户请求它.
然后用户选择给定的制造商(或几个),并运行新的查询以减少初始结果列表.可能的属性列表(以及每个属性中可能值列表)减少,因为一些现在排除了最初选择的产品(实体).
该过程继续进行,为最终用户提供有目标的搜索目录.当然,用户可以回溯等.
为了帮助解释这个冗长的解释(或者可能进一步混淆读者......),下面的代码片段提供了一个更精确的指示,表明这种结构可用于实现搜索.此代码适用于上述说明中使用的表名,可能包含一些拼写错误,但通常提供事物的味道.此外,这是使用公用表表达式(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
Run Code Online (Sandbox Code Playgroud)
很抱歉很长的解释,可能[可能]更好的在线描述,但我还没有找到它...