如何在MariaDB的多列全文索引中搜索包含多个单词前缀的条目?

n9vozmp4  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(107)

我有一个表存储人名

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,并再次尝试,但结果没有改变。

jchrr9hc

jchrr9hc1#

  • innodb_ft_min_token_size更改为2并重建索引。
  • MATCH (first_name, last_name) AGAINST ('+de* +vr*' IN BOOLEAN MODE)--+用于两个“单词”
jhiyze9q

jhiyze9q2#

SELECT *
FROM person
WHERE MATCH (first_name, last_name) AGAINST ('de* +vr*' IN BOOLEAN MODE)
ORDER BY last_name, first_name;

SELECT *
FROM person
WHERE MATCH (first_name, last_name) AGAINST ('de*,+vr*' IN BOOLEAN MODE)
ORDER BY last_name, first_name;

相关问题