我有一个用户在他们的购物篮中有一个项目,例如:Gears Of War 2限量版 - 我希望能够显示其他项目但不相似,更像是不同的版本,例如:战争的2个年度版本的游戏
所以我基本上想要做的事情,如果不可能的话,如果没有出现的话,用一个较少的单词进行搜索,然后再做一次,直到我得到所需的结果数,或最终没有单词。
所以,如果一个用户只是简单的“战争的齿轮”那么这很容易,因为有很多比赛,例如战争2的战争,战争的齿轮3等,当它是一个很大的独特标题时。
可行吗?这是最好的方法吗?
答案 0 :(得分:1)
这样做的方法是首先选择名称与当前产品使用相同字词的产品,然后按照匹配的字数对其进行排序
我做了一个测试并使用了这个结构/内容的表:http://i.imgur.com/bwnNd.png
假设当前产品是id为1且标题为“Lorem ipsum dolor sit amet”的产品我将标题拆分为单词,选择标题中至少有一个单词的产品,订购列表按匹配的单词数量,只得到前几个(示例中为4)
在此之后,为了确保您获得更好的结果,不仅仅是匹配最大字数的那些,您可以使用字符串比较算法,如levenshtein距离。我使用了这个算法,因为php核心http://php.net/manual/en/function.levenshtein.php
中有一个函数这个函数基本上告诉你需要在字符串上应用到另一个的转换数量(通过转换可以理解:删除一个字符,添加一个或更改一个字符的值)
因此,通过获得初始标题与每个结果的标题之间的levenshtein距离,您将知道更接近的标题
执行此操作时,您可以找到最小值(最好的,因为它告诉您需要最小的转换次数)并显示您找到此距离的产品
我在这里添加了一个示例脚本:http://codepad.org/FKDgo7ph
作为免责声明:您需要注意此脚本的安全性,这只是一个示例,并且还将其集成到您的系统中(此处产品的product_id和product_name是静态变量)
另外:通过添加一些改进可以获得更好的结果:
答案 1 :(得分:0)
如果你想只用一次MySQL调用就可以做到这一点。然后用一个简单的循环创建一个存储过程。
在每次迭代中将其抛入一个循环和一个单词
var_similar_title = 'Gears of War 2 Limited Edition'
....
SELECT
product_name
FROM
product
WHERE
product_name LIKE CONCAT(var_similar_title,'%')
....
单词的简单方法是使用REVERSE(),LOCATE()和SUBSTRING()函数的组合。
或
类似的东西:
SET numWords = (length('gears of war')-length(REPLACE('gears of war', ' ', '')))/length(' ')
获取字符串中的单词计数(或者如果您愿意,可以从php程序中传递),然后使用
SUBSTRING_INDEX('gears_of_war', i)
其中i最初为numWords,然后每次递减1次。
编辑:如果您需要更详细的示例,我会添加它:
DELIMITER $$
DROP PROCEDURE IF EXISTS findSimilarTitles$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `findSimilarTitles`( title VARCHAR(255), minMatches INT)
BEGIN
DECLARE i INT;
DECLARE var_similar_title VARCHAR(255);
DECLARE var_number_of_matches INT;
SET i = 1;
SET i = (length(title)-length(REPLACE(title, ' ', '')))/length(' ');
WHILE i > 0 DO
SET title = SUBSTRING_INDEX(title, ' ', i);
SET var_number_of_matches = (SELECT COUNT(*) FROM products WHERE product_name LIKE CONCAT(title,'%'));
IF var_number_of_matches >= minMatches THEN
SET i = -99;
ELSE
SET i = i - 1;
END IF;
END WHILE;
IF i = -99 THEN
SELECT product_name FROM products WHERE product_name LIKE CONCAT(title,'%');
ELSE
SELECT 'No Matching Products';
END IF;
END$$