如何为搜索后过滤构建数据库模式

时间:2014-09-01 15:30:29

标签: database database-design data-structures database-schema

我想将搜索后过滤添加到电子商务搜索功能中。目前数据存在如下:

产品(带BrandID) 品牌(产品表中BrandID的外键) ProductDietType(产品和饮食类型的联结表) DietTypes(各种产品饮食类型) 产品部门(产品和部门的联结表) 部门

我想添加搜索后过滤器,用户可以选择多个品牌,部门,饮食类型来缩小结果集。

我能想到的就是像这样编码:

if(none)...... 如果(品牌)...... 如果(部门)...... 如果(饮食类型)...... 如果(品牌和部门)...... if(品牌和饮食类型)...... if(部门和饮食类型)...... 如果(品牌和部门和饮食类型)......

我知道这是错的。因为它不是非常可扩展的:每次添加新的过滤器时,你都会增加一倍的代码分支数。

如何整齐且可扩展地编码 - 如果我想添加另一个过滤器 - 例如原产国 - 我可以相对无痛地这样做。

我在C#中编码并使用SQL Server 2008。

任何帮助都非常感激。

乔恩

1 个答案:

答案 0 :(得分:1)

您可以对产品属性使用通用方法。所有可能的过滤条件都称为属性(例如"部门#1和#34;),按属性类型分组(例如"部门")。

这样的模型有利有弊。例如:当品牌只是其中一个属性时,如何保证产品属于一个品牌?这是该模型的消极方面。最积极的方面是:无论你谈论的是产品的品牌,饮食类型,部门或其他什么,它们同样只是产品而且无关紧要。您可以过滤的属性。添加更多属性很容易,无需更改过滤器代码。

表attribute_type

id | text
1  | 'Brand'
2  | 'Diet type'
3  | 'Department'

表格属性

id | id_attribute_type | text
1  | 1                 | 'The Salad Makers'
2  | 1                 | 'Gorgeous Food'
3  | 1                 | 'Great Meals'
4  | 2                 | 'No fat'
5  | 2                 | 'Low carb'
6  | 2                 | 'No lactose'
7  | 3                 | 'Department 1'
8  | 4                 | 'Department 2'

表product_attribute

id_product | id_attribute
1          | 1
1          | 4
1          | 5
1          | 7
2          | 2
2          | 4
2          | 6
2          | 7

假设您选择标题中带有绿色字样的所有产品:

select * from products where upper(name) like '%GREEN%';

此外,您需要与所选产品相关联的所有过滤器:

select at.id as at_id, at.text as at_text, a.id as a_id, a.text as a_text
from product_attribute pa
join attribute a on a.id = pa.id_attribute
join attribute_type at on at.id = a.id_attribute_type
where pa.id_product in (select id from products where upper(name) like '%GREEN%');

如果' GREEN'产品恰好是产品1和产品2然后得到:

  • '品牌' (1)
    • '沙拉制造商' (1)
    • '华丽的食物' (2)
  • '饮食类型' (2)
    • '没有脂肪' (4)
    • '低碳酸盐' (5)
    • '没有乳糖' (6)
  • '部' (3)
    • '部门1' (7)

现在用户选择Brand =' The Salad Makers'和'饮食类型' ='没有脂肪'或者'没有乳糖'。这使得:

select * 
from products
where upper(name) like '%GREEN%'
and id in 
(
  select id_product
  from product_attribute
  group by id_product
  having sum(case when id_attribute in (1) then 1 end) > 0 criteria for Brand
  and sum(case when id_attribute in (4,6) then 1 end) > 0 -- criteria for Diet type
);

您只需在每个使用的属性类型(此处为1个品牌和2个饮食类型)中添加一个条件行,并使用包含所选属性的IN子句来创建此类查询。

这样的模型可以变得更加复杂。例如,可能会有一些与OR相关的过滤器(品牌x y的所有产品)和其他带AND的过滤器(所有产品都是甜的酸)。

嗯,你明白了。我不知道你是否认为这适合你正在做的事情。这只是一个想法。如上所述,它有优点,但它也有缺点。

您可能还会决定混合概念(例如:品牌等主要属性保留实际列,而其他属性则转到属性表)。