在 Room SQLite 中查询(不区分大小写)忽略重音
Query in Room SQLite (Insensitive casing) ignoring accents
在我的 Android 应用程序的一部分中,您可以按姓名搜索人员。但我需要即使名字或姓氏写错了(例如没有重音)结果也会显示:
示例:
在数据库中:Pérez Juan、Cooper Sheldon、Pérez Adrian
搜索:佩雷斯
显示:Pérez Juan、Pérez Adrian(来自数据库)
我正在使用 LIKE 执行查询并且它可以覆盖不敏感的大小写,但它不适用于重音,因为我必须写完全相同的字母(有或没有重音),这是我的工作代码:
所以我得到了searchPerson
中使用的变量
String name = searchEditText.getText().toString();
if (!name.equals("")){
name = "%" + name + "%";
}
PersonDao
@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
"FROM Person\n" +
"WHERE FullName LIKE :fn\n" +
"ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);
在 Whosebug 上找到了可能的解决方案
为了解决口音问题,我发现 this answer 我尝试实施但没有成功
所以我得到了searchPerson
中使用的变量
String name = searchEditText.getText().toString();
name = addTildeOptions(name);
addTildeOptions 函数
private String addTildeOptions(String searchText) {
return searchText.toLowerCase()
.replaceAll("\[aáàäâã]\.*", "[aáàäâã]")
.replaceAll("\[eéèëê]\.*", "[eéèëê]")
.replaceAll("\[iíìî]\.*", "[iíìî]")
.replaceAll("\[oóòöôõ]\.*", "[oóòöôõ]")
.replaceAll("\[uúùüû]\.*", "[uúùüû]")
.replace("*", "[*]")
.replace("?", "[?]");
}
PersonDao
@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
"FROM Person\n" +
"WHERE lower(FullName) GLOB :fn\n" +
"ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);
但是这不会return任何结果,即使我输入一个字母它也不会显示任何内容。
我尝试在获取 EditText 的文本时在开头和结尾添加星号,尝试在我的 PersonDao 查询中输入 addTildeOptions 函数,但没有成功,尝试了一些其他不相关的事情却一直没有结果。
我的代码有什么问题?
较新的查询失败的原因是您将 lower
大小写的字符串传递给 WHERE 子句,并且没有行与这些小写字符串匹配。例如,您的 table 包含“Pérez Juan”,而不是“pérez juan”
addTildeOptions
功能运行正常,但您需要对其进行更改,以将所有纯元音字母和带有变音符(波浪号、重音符、元音变音符等)的元音字母替换为“?”字符,以便查询可以使用 LIKE 或 GLOB 查找行:
String globPersonName(String fn) {
return fn.replaceAll("[aáàäâã]", "?")
.replaceAll("[eéèëê]", "?")
.replaceAll("[iíìî]", "?")
.replaceAll("[oóòöôõ]", "?")
.replaceAll("[uúùüû]", "?");
}
然后只需删除 lower
调用并在您的查询中保留 GLOB:
@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
"FROM Person\n" +
"WHERE FullName GLOB :fn\n" +
"ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);
因此搜索名称的所有变体形式如下:personDao.searchPerson(globPersonName(fn));
例如,globPersonName("Perez Juan")
将 return P?r?z J??n
,您的查询应该找到“Pérez Juan”记录。
使用 GLOB
正是我所需要的。但是,我将其稍微更改为多一点“fine-grained”。例如,@zen_of_kermit 的解决方案也将匹配“Poraz Jaen”;但这不会:
String globPersonName(String fn) {
return fn.replaceAll("[aáàäâã]", "[aáàäâã]")
.replaceAll("[eéèëê]", "[eéèëê]")
.replaceAll("[iíìî]", "[iíìî]")
.replaceAll("[oóòöôõ]", "[oóòöôõ]")
.replaceAll("[uúùüû]", "[uúùüû]");
}
这样每个元音都被其各自的正则表达式替换,因此它只匹配每个元音的已知个变体。
在我的 Android 应用程序的一部分中,您可以按姓名搜索人员。但我需要即使名字或姓氏写错了(例如没有重音)结果也会显示:
示例:
在数据库中:Pérez Juan、Cooper Sheldon、Pérez Adrian
搜索:佩雷斯
显示:Pérez Juan、Pérez Adrian(来自数据库)
我正在使用 LIKE 执行查询并且它可以覆盖不敏感的大小写,但它不适用于重音,因为我必须写完全相同的字母(有或没有重音),这是我的工作代码:
所以我得到了searchPerson
中使用的变量String name = searchEditText.getText().toString();
if (!name.equals("")){
name = "%" + name + "%";
}
PersonDao
@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
"FROM Person\n" +
"WHERE FullName LIKE :fn\n" +
"ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);
在 Whosebug 上找到了可能的解决方案
为了解决口音问题,我发现 this answer 我尝试实施但没有成功
所以我得到了searchPerson
中使用的变量String name = searchEditText.getText().toString();
name = addTildeOptions(name);
addTildeOptions 函数
private String addTildeOptions(String searchText) {
return searchText.toLowerCase()
.replaceAll("\[aáàäâã]\.*", "[aáàäâã]")
.replaceAll("\[eéèëê]\.*", "[eéèëê]")
.replaceAll("\[iíìî]\.*", "[iíìî]")
.replaceAll("\[oóòöôõ]\.*", "[oóòöôõ]")
.replaceAll("\[uúùüû]\.*", "[uúùüû]")
.replace("*", "[*]")
.replace("?", "[?]");
}
PersonDao
@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
"FROM Person\n" +
"WHERE lower(FullName) GLOB :fn\n" +
"ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);
但是这不会return任何结果,即使我输入一个字母它也不会显示任何内容。
我尝试在获取 EditText 的文本时在开头和结尾添加星号,尝试在我的 PersonDao 查询中输入 addTildeOptions 函数,但没有成功,尝试了一些其他不相关的事情却一直没有结果。
我的代码有什么问题?
较新的查询失败的原因是您将 lower
大小写的字符串传递给 WHERE 子句,并且没有行与这些小写字符串匹配。例如,您的 table 包含“Pérez Juan”,而不是“pérez juan”
addTildeOptions
功能运行正常,但您需要对其进行更改,以将所有纯元音字母和带有变音符(波浪号、重音符、元音变音符等)的元音字母替换为“?”字符,以便查询可以使用 LIKE 或 GLOB 查找行:
String globPersonName(String fn) {
return fn.replaceAll("[aáàäâã]", "?")
.replaceAll("[eéèëê]", "?")
.replaceAll("[iíìî]", "?")
.replaceAll("[oóòöôõ]", "?")
.replaceAll("[uúùüû]", "?");
}
然后只需删除 lower
调用并在您的查询中保留 GLOB:
@Query("SELECT *, lastName || ' ' || name AS FullName\n" +
"FROM Person\n" +
"WHERE FullName GLOB :fn\n" +
"ORDER BY FullName")
LiveData<List<Person>> searchPerson(String fn);
因此搜索名称的所有变体形式如下:personDao.searchPerson(globPersonName(fn));
例如,globPersonName("Perez Juan")
将 return P?r?z J??n
,您的查询应该找到“Pérez Juan”记录。
使用 GLOB
正是我所需要的。但是,我将其稍微更改为多一点“fine-grained”。例如,@zen_of_kermit 的解决方案也将匹配“Poraz Jaen”;但这不会:
String globPersonName(String fn) {
return fn.replaceAll("[aáàäâã]", "[aáàäâã]")
.replaceAll("[eéèëê]", "[eéèëê]")
.replaceAll("[iíìî]", "[iíìî]")
.replaceAll("[oóòöôõ]", "[oóòöôõ]")
.replaceAll("[uúùüû]", "[uúùüû]");
}
这样每个元音都被其各自的正则表达式替换,因此它只匹配每个元音的已知个变体。