房间SQLite中的查询(不区分大小写)忽略重音

50few1ms  于 2022-11-15  发布在  SQLite
关注(0)|答案(3)|浏览(168)

在我的Android应用程序的一部分中,你可以按名字搜索人。但我需要的是,即使名字或姓氏写错了(例如没有重音),结果也会显示出来:
示例:
数据库中:佩雷斯·胡安,库珀·谢尔顿,佩雷斯·禤浩焯
搜索:佩雷斯
节目:佩雷斯·胡安,佩雷斯·禤浩焯(来自数据库)
我使用LIKE执行查询,它覆盖了不敏感的大小写,但它不适用于重音,因为我必须写完全相同的字母(带或不带重音),以下是我的工作代码:

所以我得到了在搜索Person中使用的变量

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);

StackOverflow找到可能的解决方案

为了解决我找到的this answer口音问题,我正在尝试实现该口音,但没有成功

所以我得到了在搜索Person中使用的变量

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);

但是,这不会返回任何结果,即使我输入一个字母,它也不会显示任何内容。
在获取EditText的文本时,我尝试在开始和结束处添加星号,尝试在PersonDao查询中输入addTildeOptions函数,如答案所示,但失败了,尝试了其他一些不相关的事情,但从未得到结果。
我的代码中有什么错误?

vddsk6oq

vddsk6oq1#

较新的查询失败的原因是,您将一个大小写为lower的字符串传递给WHERE子句,而没有任何行与这些小写字符串匹配。例如,您的表包含“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")将返回P?r?z J??n,您的查询应该找到“Pérez Juan”记录。

pokxtpni

pokxtpni2#

使用GLOB正是我所需要的。然而,我对其进行了一点修改,使其更加“细粒度”。例如,@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úùüû]");
}

这样,每个元音都被其各自的正则表达式替换,因此它只匹配每个元音的已知变体。

cgyqldqp

cgyqldqp3#

对于那些在Kotlin工作的人:

fun replaceVowels(searchText: String): String {
  return searchText.lowercase(Locale.getDefault())
      .replace(Regex("[aáàâã]"), "?")
      .replace(Regex("[eéèëê]"), "?")
      .replace(Regex("[iíìî]"), "?")
      .replace(Regex("[oóòôõ]"), "?")
      .replace(Regex("[uúùüû]"), "?")
}

并将SQL查询更改为:

@Query("SELECT * FROM your_table WHERE your_column GLOB :query || '*' ")

相关问题