繁体   English   中英

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

[英]Query in Room SQLite (Insensitive casing) ignoring accents

在我的 Android 应用程序的一部分中,您可以按姓名搜索人员。 但我需要即使名字或姓氏写错(例如没有重音),也会显示结果:

例子:

数据库中:Pérez Juan、Cooper Sheldon、Pérez Adrian

搜索: perez

演出:佩雷斯·胡安、佩雷斯·阿德里安(来自数据库)

我正在使用 LIKE 执行查询,它可以覆盖不敏感的大小写,但它不适用于重音,因为我必须写完全相同的字母(有或没有重音),这是我的工作代码:

所以我得到了 searchPerson 中使用的变量

String name = searchEditText.getText().toString();
            if (!name.equals("")){
                name = "%" + name + "%";
            }

人道

@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 上找到可能的解决方案


为了解决口音的问题,我找到了我试图实施但没有成功的答案

所以我得到了 searchPerson 中使用的变量

String name = searchEditText.getText().toString();
            name = addTildeOptions(name);

addTildeOptions function

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("?", "[?]");
}

人道

@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 function 答案显示但没有这样做,尝试了其他一些不相关的事情,但从未得到结果.

我的代码有什么问题?

您的较新查询失败的原因是您将lower字符串传递给 WHERE 子句,并且没有行与这些小写字符串匹配。 例如,您的表包含“Pérez Juan”,而不是“pérez juan”

addTildeOptions function 在正确的轨道上,但您需要更改它以用“? 字符,以便查询可以使用 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”记录。

使用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úùüû]");
}

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

对于那些在 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 || '*' ")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM