我有一个表存储人名
CREATE TABLE `person` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `first_name_last_name` (`first_name`,`last_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `person` (`first_name`, `last_name`) VALUES
('Aristide', 'Romano'),
('Jérôme', 'Nadeau'),
('Madeleine', 'Roger'),
('Daniel', 'De Jong'),
('Alban', 'Hervé'),
('Camille', 'Evrard'),
('Delphine', 'Vriaud'),
('Pavel', 'Lelièvre'),
('Albert', 'De Vries'),
('Luc', 'Robin'),
('Vanessa', 'Olivier'),
('Georges', 'De Vries'),
('Delphine', 'Bernard');
- 注意:这些是随机生成的名字,而不是实际的人。
当用户搜索“de vr”时,我想返回所有包含以“de”开头的单词和以“vr”开头的单词的行:
*DelphineVriaud
- 阿尔伯特·德·弗里斯
- 乔治·德·弗里斯
当然,真实的表要大得多(大约10,000行),而且查询会经常使用,这就是为什么我尝试使用FULLTEXT搜索而不是繁重的column LIKE "{search}%"
我不能在全文搜索中使用默认的“orderbyrelevance”,因为自定义ORDERBY子句总是根据用户输入应用。我需要查询返回那些行only,因为如果它们被部分匹配所稀释,我不能期望好的结果出现在顶部。
根据MariaDB文档中的操作符描述,我认为正确的方法是:
SELECT * FROM person
WHERE MATCH (first_name, last_name) AGAINST ('+de*, +vr*' IN BOOLEAN MODE)
ORDER BY last_name, first_name;
*
表示“我接受这个词或这样开始的词...”,“+”表示“所有结果必须匹配这个词”。
但是这个查询只返回“Delphine Vriaud”。看来匹配必须在不同的列,防止姓氏“德弗里斯”匹配。
如果我从查询中删除+
符号:
SELECT * FROM person
WHERE MATCH (first_name, last_name) AGAINST ('de*, vr*' IN BOOLEAN MODE)
ORDER BY last_name, first_name;
我得到了所有包含“de*”或“vr*"的行,正如预期的那样,其中包括3行我想要的和“Delphine Bernard”我不想要的。
你可以试试这个小提琴上的查询。
我想实现的是FULLTEXT搜索吗?
编辑:后来我发现了InnoDB变量innodb_ft_min_token_size,它定义了一个单词必须包含在FULLTEXT索引中的最小长度。此变量的默认值为3,这意味着来自“De弗里斯”或“De Jong”的单词“De”不在索引中,可以解释结果。
我在本地MariaDb服务器上将值更改为2,并再次尝试,但结果没有改变。
2条答案
按热度按时间jchrr9hc1#
innodb_ft_min_token_size
更改为2并重建索引。MATCH (first_name, last_name) AGAINST ('+de* +vr*' IN BOOLEAN MODE)
--+
用于两个“单词”jhiyze9q2#
或