Oracle中的模糊文本搜索

Ufu*_*ici 10 sql oracle fuzzy-search

我有一个大型Oracle数据库表,其中包含整个国家/地区的街道名称,其中包含600000多行.在我的应用程序中,我将地址字符串作为输入,并想检查此地址字符串的特定子字符串是否与表中的一个或多个街道名称匹配,以便我可以将该地址子字符串标记为街道的名称.

显然,这应该是一个模糊的文本匹配问题,我查询的子字符串与DB表中的街道名称完全匹配的可能性很小.所以应该有某种模糊文本匹配方法.我正在尝试阅读http://docs.oracle.com/cd/B28359_01/text.111/b28303/query.htm中的Oracle文档,其中解释了CONTAINS和CATSEARCH搜索运算符.但这些似乎用于更复杂的任务,例如在文档中搜索给定字符串的匹配项.我只是想为表的一列做这件事.

在这种情况下,您对我的建议是什么,Oracle是否支持这种模糊文本匹配查询?

Jon*_*ler 8

UTL_MATCH包含匹配字符串和比较字符串相似性的方法.编辑距离,也称为Levenshtein距离,可能是一个很好的起点.由于一个字符串是子字符串,因此可以帮助比较编辑距离相对于字符串的大小.

--Addresses that are most similar to each substring.
select substring, address, edit_ratio
from
(
    --Rank edit ratios.
    select substring, address, edit_ratio
        ,dense_rank() over (partition by substring order by edit_ratio desc) edit_ratio_rank
    from
    (
        --Calculate edit ratio - edit distance relative to string sizes.
        select
            substring,
            address,
            (length(address) - UTL_MATCH.EDIT_DISTANCE(substring, address))/length(substring) edit_ratio
        from
        (
            --Fake addreses (from http://names.igopaygo.com/street/north_american_address)
            select '526 Burning Hill Big Beaver District of Columbia 20041'   address from dual union all
            select '5206 Hidden Rise Whitebead Michigan 48426'                address from dual union all
            select '2714 Noble Drive Milk River Michigan 48770'               address from dual union all
            select '8325 Grand Wagon Private Sleeping Buffalo Arkansas 72265' address from dual union all
            select '968 Iron Corner Wacker Arkansas 72793'                    address from dual
        ) addresses
        cross join
        (
            --Address substrings.
            select 'Michigan'           substring from dual union all
            select 'Not-So-Hidden Rise' substring from dual union all
            select '123 Fake Street'    substring from dual
        )
        order by substring, edit_ratio desc
    )
)
where edit_ratio_rank = 1
order by substring, address;
Run Code Online (Sandbox Code Playgroud)

这些结果并不好,但希望这至少是一个很好的起点.它应该适用于任何语言.但是你仍然可能希望将它与某些语言或特定于语言环境的比较规则结合起来.

SUBSTRING          ADDRESS                                                  EDIT_RATIO
---------          -------                                                  ----------
123 Fake Street    526 Burning Hill Big Beaver District of Columbia 20041   0.5333
Michigan           2714 Noble Drive Milk River Michigan 48770               1
Michigan           5206 Hidden Rise Whitebead Michigan 48426                1
Not-So-Hidden Rise 5206 Hidden Rise Whitebead Michigan 48426                0.5
Run Code Online (Sandbox Code Playgroud)


Axe*_*per 5

您可以利用Oracle数据库中提供的SOUNDEX函数。计算文本字符串的数字签名。这可用于查找听起来相似的字符串,从而减少字符串比较的次数。SOUNDEX

编辑: 如果SOUNDEX不适合您的本地语言,您可以向Google索取效果更好的拼音签名或拼音匹配功能。该函数必须针对每个新表条目评估一次,并且针对每个查询评估一次。因此,它不需要驻留在Oracle中。

示例:此处推广土耳其语 SOUNDEX 。

为了提高匹配质量,第一步应该统一街道名称拼写。这可以通过应用一组规则来完成:

简化示例规则:

  1. 将所有字符转换为小写
  2. 删除“str”。在名字的末尾
  3. 删除“驱动”。在名字的末尾
  4. 删除名称末尾的“地点”
  5. 删除“大道”。在名字的末尾
  6. 按字母顺序对包含多个单词的名称进行排序
  7. 删除辅助词,如“of”、“and”、“the”……