-4

我有一个包含 20000 个域名的数据库,包括顶级域、二级和低级域。例如

.biz stackoverflow.com ru.wikipedia.com

我想执行快速查找以查看输入 URL 是否与这 20000 个中的任何一个匹配。我可以使用 Dictionary 键或 HashSet.Contains,但它仅适用于完全匹配。由于数据库还包含 TLD 名称,因此我希望 acmeycompany.biz 也因为 .biz TLD 而返回匹配项。另一方面,fr.wikipedia.com 不应该匹配,因为子域不同。

简单地遍历列表并进行基于字符串的比较也不是一种选择。如果我有 1000 个 URL 进行比较,那就太慢了。所以它必须是基于键的索引查找。

我正在考虑构建一个如下所示的树结构,然后进行基于键的查找,例如:

.com .wikipedia .ru .stackoverflow .biz

然后我可以将输入 Url (sampledomain.com) 拆分为多个部分并像 .com -> .sampledomain 这样进行查找

任何人都可以指点我一个样本怎么做吗?或者还有什么其他选择?任何样品表示赞赏。

谢谢!

这就是我开始的方式......这是 vb.net 代码,但你明白了。

 Public Class TreeNode

    Sub New()
        ChildNodes = New Dictionary(Of String, TreeNode)
    End Sub

    Public Property Key As String
    Public Property ChildNodes As Dictionary(Of String, TreeNode)

End Class

Private Tree As New Dictionary(Of String, TreeNode)

Sub BuildTree()

    For Each Link In Links

        If Uri.IsWellFormedUriString(Link, UriKind.Absolute) Then

            Dim Url As New Uri(Link)
            Dim Domain As String

            If Url.HostNameType = UriHostNameType.Dns Then

                Domain = Url.Host.ToLower.Replace("www.", "")

                Dim DomainParts() As String = Domain.Split(CChar("."))

                'lets start from TLD
                For Each Key In DomainParts.Reverse

                    'dont konw how to populate tree

                Next

            End If

        End If

    Next

End Sub

Function TreeLookup(Link As String) As Boolean

    Dim Url As New Uri(Link)
    Dim Domain As String
    Dim IsMatch As Boolean = False

    If Url.HostNameType = UriHostNameType.Dns Then

        Domain = Url.Host.ToLower.Replace("www.", "")

        Dim DomainParts() As String = Domain.Split(CChar("."))
        Dim DomainPartsCount As Integer = DomainParts.Length
        Dim Index As Integer = 0


        For Each Key In DomainParts

            Index += 1

            'use recursive loop to see if 

            'returns true if directory contains key and we have reached to the last part of the domain name
            If Index = DomainPartsCount Then

                IsMatch = True
                Exit For

            End If

        Next

    End If

    Return IsMatch

End Function
4

2 回答 2

0

您可能想要创建哈希图字典的字典。第一个字典可以包含与所有具有该 TLD 的二级域的字典配对的所有 TLD 条目。然后每个二级域可以包含它所包含的所有低级域的哈希图。每个条目还将有一个标志来指示该条目是否实际在数据库中,或者只是较低级别条目的占位符。与您使用的短列表一样,.com它实际上不在列表中,但仍将是 TLD 中的条目,因此可以访问stackoverflow.comand wikipedia.com(它本身将是 的占位符ru.wikipedia.com)。然后,查找将从 URL TLD 开始,然后是第二层,如果需要深入,则最后是更低的级别。

我希望我能正确理解你的困境并充分解释我的想法。

编辑:最低级别只需要一个哈希图。


您需要在树节点中添加一个指示器,以指示该节点是匹配键还是只是进入二级/低级域的垫脚石。

要添加域,您可以执行以下操作(如果您愿意,可以将其设为递归,但只有三个级别没什么大不了的):

// TLD, SLD and LLD are the three levels of the current domain you are adding into the tree
if Tree does not contain the TLD
    Add TLD to the Tree with a new TreeNode

if SLD does not exist for the current domain
    Mark the Tree at TLD as a match
else   
    if Tree[TLD] does not contain the SLD
        Add SLD to the Tree[TLD] Node

    if LLD does not exist for the current domain
        Mark the Tree[TLD] at SLD as a match
    else   
        if Tree[TLD][SLD] does not contain the LLD
            Add LLD to the Tree[TLD][SLD] Node
            // Don't really need to mark the node
            // as every LLD would be a match
            // Probably would need to mark if made recursive

查找域(同样,可以递归):

// TLD, SLD and LLD are for the domain you looking for
if Tree does not contain TLD
    you are done, no match
else
    if Tree[TLD] is marked
        done, match
    else
        if Tree[TLD] does not contain SLD
            done, no match
        else
            if Tree[TLD][SLD] is marked
                done, match
            else
                if Tree[TLD][SLD] contains LLD
                    done, match
                    // would need to check if the node
                    // is marked if made recursive
于 2013-08-14T18:36:06.100 回答
-1

当您在数据库中存储项目时,请让 URL 的每个部分都有自己的列。因此,TLD、域和子域都将是它们自己的列。

create table MyList
(
    [TLD] nvarchar(10) not null,
    [Domain] nvarchar(50) not null,
    [Subdomain] nvarchar(50) not null,

    unique ([TLD], [Domain], [Subdomain]) 
    --this means that you can't add the same data twice
)

现在使用 SQL 来获取您想要的数据。

select *
from MyList
where [TDL] = '.com'

这是解决您的问题的最有效方法,因为数据在被过滤之前永远不会离开您的数据库。

至于表的原因,请阅读Database Normalization

如果您只将 url 存储在单个列中,则必须进行一些数据转换。

于 2013-08-14T18:46:34.913 回答