【问题标题】:Fuzzy text searching in OracleOracle 中的模糊文本搜索
【发布时间】:2014-08-12 07:54:06
【问题描述】:

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

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

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

【问题讨论】:

    标签: sql oracle fuzzy-search


    【解决方案1】:

    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;
    

    这些结果不是很好,但希望这至少是一个好的起点。它应该适用于任何语言。但您可能仍希望将其与一些特定于语言或区域设置的比较规则结合起来。

    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
    

    【讨论】:

    • 我已经发现了这个 EDIT_DISTANCE_SIMILARITY 和 JARO_WINKLER_DISTANCE 相似函数,而且它们似乎完全符合我的要求。感谢您的回答。
    【解决方案2】:

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

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

    示例:提升土耳其语 SOUNDEX here

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

    简化示例规则:

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

    【讨论】:

    • 问题是 SOUNDEX 似乎是为英语构建的。我的数据不是英文的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    • 1970-01-01
    • 2013-02-18
    相关资源
    最近更新 更多