分面搜索(solr)vs通过PHP进行良好的旧过滤?

Adi*_*dil 25 php solr magento faceted-search layered-navigation

我打算在我的电子商务商店中设置过滤系统(优化搜索).你可以在这里看到一个例子:http://www.bettymills.com/shop/product/find/Air+and+HVAC+Filters

PrestaShop,OpenCart和Magento等平台拥有所谓的分层导航.

我的问题是,与使用Solr或Lucene之类的东西进行分面导航相比,Magento或PrestaShop等平台中的分层导航有什么区别.

可以通过php和mysql完成类似的结果吗?

非常感谢详细解释.

net*_*der 51

分层导航==分面搜索.

它们是相同的,但Magento和al使用不同的措辞,可能是吸引人的.据我所知,Magento支持Solr分面搜索或MySQL搜索.主要区别在于性能.

绩效是主要的权衡.

要在MySQL中进行分面搜索,需要连接表,而Solr会自动索引文档构面以进行过滤.在平均硬件上使用Solr(多面搜索查询<100ms)通常可以实现快速响应时间.虽然MySQL对于相同的搜索将花费更长的时间,但可以使用索引对其进行优化以实现类似的响应时间.

Solr的缺点是它需要您在服务器上配置,保护和运行另一项服务.它也可能是CPU和内存密集型,具体取决于您的配置(Tomcat,jetty等).

PHP/MySQL中的分面搜索是可能的,并不像你想象的那么难.

您需要特定的数据库模式,但这是可行的.这是一个简单的例子:

产品

+----+------------+
| id | name       |
+----+------------+
|  1 | blue paint |
|  2 | red paint  |
+----+------------+
Run Code Online (Sandbox Code Playgroud)

分类

+----+----------+
| id | name     |
+----+----------+
|  1 | color    |
|  2 | material |
|  3 | dept     |
+----+----------+
Run Code Online (Sandbox Code Playgroud)

product_classification

+------------+-------------------+-------+
| product_id | classification_id | value |
+------------+-------------------+-------+
|          1 |                 1 | blue  |
|          1 |                 2 | latex |
|          1 |                 3 | paint |
|          1 |                 3 | home  |
|          2 |                 1 | red   |
|          2 |                 2 | latex |
|          2 |                 3 | paint |
|          2 |                 3 | home  |
+------------+-------------------+-------+
Run Code Online (Sandbox Code Playgroud)

所以,有人说搜索paint,你会做类似的事情:

SELECT p.* FROM product p WHERE name LIKE '%paint%';
Run Code Online (Sandbox Code Playgroud)

这将返回product表中的两个条目.

搜索执行完毕后,您可以使用以下查询获取结果的关联方面(过滤器):

SELECT c.id, c.name, pc.value FROM product p
   LEFT JOIN product_classification pc ON pc.product_id = p.id
   LEFT JOIN classification c ON c.id = pc.classification_id
WHERE p.name LIKE '%paint%'
GROUP BY c.id, pc.value
ORDER BY c.id;
Run Code Online (Sandbox Code Playgroud)

这会给你类似的东西:

+------+----------+-------+
| id   | name     | value |
+------+----------+-------+
|    1 | color    | blue  |
|    1 | color    | red   |
|    2 | material | latex |
|    3 | dept     | home  |
|    3 | dept     | paint |
+------+----------+-------+
Run Code Online (Sandbox Code Playgroud)

因此,在您的结果集中,您知道有些产品的颜色是,blue并且red它是唯一的材料latex,并且它可以在部门home和部门中找到paint.

用户选择构面后,只需修改原始搜索查询:

SELECT p.* FROM product p
   LEFT JOIN product_classification pc ON pc.product_id = p.id
WHERE 
   p.name LIKE '%paint%' AND (
      (pc.classification_id = 1 AND pc.value = 'blue') OR
      (pc.classification_id = 3 AND pc.value = 'home')
   )
GROUP BY p.id
HAVING COUNT(p.id) = 2;
Run Code Online (Sandbox Code Playgroud)

因此,这里用户正在搜索关键字paint,并包括两个方面:blue颜色方面和home部门方面.这会给你:

+----+------------+
| id | name       |
+----+------------+
|  1 | blue paint |
+----+------------+
Run Code Online (Sandbox Code Playgroud)

所以,总之.尽管它在Solr中是开箱即用的,但它可以很容易地在SQL中实现它.

  • @RPM:是的.因为你希望MySQL匹配一个方面或另一个方面,然后使用`HAVING`子句检查所有方面是否匹配(你不能告诉MySQL使用`AND`匹配两个方面因为它的关系性质它是不可能的例如:`value`不能同时是`blue`和`red`).所以,如果你有4个方面,你需要三个带有"OR"子句的条件,以及一个"HAVING COUNT()"的"4". (4认同)
  • @RPM:是的,所有方面都在嵌套的`AND`中.模式如下.当使用`OR`子句时,对于匹配的每个方面,MySQL将返回一行或多行,具有相同的`p.id`(item).所以,如果你的项目(`p.id = 1`)匹配`blue`和`paint`你将有两行:`p.id = 1,value = blue`和`p.id = 1,value = paint`.`HAVING`子句确保您确实有两行,每行选择一个.删除`GROUP BY`条款,你会明白我的意思. (2认同)