如何使精确的 unicode 字符优先于 ASCII 版本?

Posted

技术标签:

【中文标题】如何使精确的 unicode 字符优先于 ASCII 版本?【英文标题】:How to make exact unicode characters take priority over ASCII versions? 【发布时间】:2021-11-15 16:19:33 【问题描述】:

我有一个包含德国城镇名称的数据库,例如慕尼黑和明斯特。

如果我这样查询:

SELECT name,
       MATCH(name) AGAINST('+mün*' IN BOOLEAN MODE) AS relevance
FROM place_names
ORDER BY relevance DESC

对于包含munmün 或任何其他在不考虑变音符号时扁平为mun 的文本的所有地点,我得到相同的相关性值。换句话说,搜索munmün 会得到完全相同的结果。

如何配置我的数据库,以便搜索 mün 将与实际包含字母 ü 的单词提供更高的相关性,但仍将 u 视为匹配项?

【问题讨论】:

不行。相同的相关性或其中之一不匹配。这取决于排序规则。您可以使用将两者都视为匹配的排序规则,并使用敏感排序规则使用额外的匹配,这将严格匹配。 那么我如何为同一个数据库(/表?)设置两个不同的排序规则并在同一个查询中使用它们?例如,取两者中的GREATEST() 【参考方案1】:
CREATE TABLE place_names (id SERIAL PRIMARY KEY, name VARCHAR(255));
CREATE FULLTEXT INDEX idx ON place_names (name);
INSERT INTO place_names (name) VALUES ('Munich'), ('Münster');
SELECT * FROM place_names;
id name
1 Munich
2 Münster
SELECT name,
       MATCH(name) AGAINST('+mün*' IN BOOLEAN MODE) AS relevance
FROM place_names
ORDER BY relevance DESC;
name relevance
Munich 0.000000001885928302414186
Münster 0.000000001885928302414186
ALTER TABLE place_names ADD COLUMN name2 VARCHAR(255) COLLATE utf8mb4_0900_bin AS (name) STORED;
CREATE FULLTEXT INDEX idx2 ON place_names (name2);
SELECT name,
       MATCH(name) AGAINST('+mün*' IN BOOLEAN MODE) AS relevance,
       MATCH(name2) AGAINST('+mün*' IN BOOLEAN MODE) AS relevance2
FROM place_names
ORDER BY relevance DESC;
name relevance relevance2
Munich 0.000000001885928302414186 0
Münster 0.000000001885928302414186 0.0906190574169159

db小提琴here

因此

SELECT name,
       MATCH(name) AGAINST('+mün*' IN BOOLEAN MODE) AS relevance
FROM place_names
ORDER BY MATCH(name2) AGAINST('+mün*' IN BOOLEAN MODE) DESC;

【讨论】:

谢谢。但是制作一个单独的列来保存具有不同排序规则的相同数据将需要我复制大量数据。真的没有办法在查询时“解释”具有两种不同排序规则的列吗? @theberzi FTI 使用明确的排序规则,MATCH .. AGAINST 不能使用除列的排序规则之外的排序规则。通过所示方式,您的任务需要两个单独的排序规则 - 所以您需要 2 个单独的 FTI。 FTI 使用列的排序规则 - 因此您需要 2 个单独的列。 FTI 不能由虚拟生成的列创建 - 因此您需要两倍的磁盘空间。也许还有其他解决方案,但我现在找不到。除了按非 FTS 表达式(LIKE 或 REGEX)排序。【参考方案2】:

一种方法可能是:

WHERE MATCH(name) AGAINST ('+mün*' IN BOOLEAN MODE) AS relevance
ORDER BY name LIKE '%Mün%' COLLATE utf8mb4_bin DESC, relevance DESC

另外需要注意的是在 mysql 8.0 中存在排序规则 utf8mb4_0900_as_ci -- “Accent Sensitive and Case Insensitive”。 (但是,这根本不匹配“Mun”。)

【讨论】:

以上是关于如何使精确的 unicode 字符优先于 ASCII 版本?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中仅匹配 Unicode 字符串中的完全组合字符?

15接口优先于反射机制

如何让 CSS 类优先于 id?

如何解决“允许属性将优先于allowfullscreen”警告?

如何确定两个优先于重载解析的隐式转换序列?

为什么在密码问题上char[]优先于String?(转载自ImportNew)