使用 Amazon Neptune 绘制图形关系

简介

在本教程中,将为餐厅评级应用程序构建欺诈检测服务。当用户在应用程序中输入评级时,将数据添加到欺诈检测服务中。然后分析评级,查看是应将其标记为手动评论还是删除。该服务使用 Amazon Neptune(一个全托管图形数据库)作为数据存储。

您将通过本教程学习如何在应用程序中使用全托管 Neptune 数据库。首先,您将了解为什么需要使用诸如 Neptune 之类的图形数据库。然后,您将逐步完成以下操作步骤:创建 Neptune 数据库、设计数据模型、在应用程序中使用该数据库。在本教程结束时,您应当能够在应用程序中自如使用 Neptune。

完成时间:30–45 分钟

专用数据库 - Neptune (22 分 20 秒)
为什么使用 Neptune?

Neptune 是 AWS 提供的一个全托管图形数据库。图形数据库适用于具有各种关系且关联紧密的数据。许多公司将图形数据库用于以下使用场景:

  • 推荐引擎:可以使用图形数据库在社交网络中将用户与关注者相关联,或者在电子商务应用程序中将客户与购买的商品相关联。通过分析相似用户或客户之间的联系,可以提供准确的好友关注推荐或其他购买商品推荐。
  • 欺诈检测:支付公司使用图形数据库识别欺诈的关联网络。通过分析电子邮件地址、IP 地址和其他共享信息之间的关系,可以更容易地标记可疑活动。
  • 知识图:可以使用图形数据库关联相关信息片段,显示人物、地点和概念之间的联系。这可以为您的店面或知识中心中的实体提供丰富的背景信息。

使用 Neptune,您可以获得全托管图形数据库体验。也就是说,您不必关注实例故障转移、数据库备份和恢复或软件升级。而是专注于构建应用程序并为客户提供价值。

课程内容

在本教程中,您将学习如何构建使用 Neptune 作为数据存储的欺诈检测服务。本教程分为五个步骤。

  • 在本模块中,您将创建和准备 AWS Cloud9 环境。AWS Cloud9 是基于云的集成开发环境 (IDE)。可以为您快速搭建一致的开发环境,让您在其中快速构建 AWS 应用程序。


    首先,请前往 AWS Cloud9 控制台。点击 Create environment(创建环境),启动 AWS Cloud9 环境创建向导。

    (点击放大)

    在向导的第一页,为您的环境命名和提供描述。然后点击 Next step(下一步)。

    (点击放大)

    在下一步中,您可以配置环境设置(如环境中的实例类型、平台和网络设置)。

    在本教程中保留默认设置,因此滚动到底部并点击 Next step(下一步)。

    (点击放大)

    最后一步显示您的设置以供检查。滚动到底部并点击 Create environment(创建环境)。

    (点击放大)

    AWS Cloud9 环境需要几分钟才能完成预配。如果系统正在创建环境,则会显示以下界面。

    (点击放大)

    几分钟后,您应当会看到 AWS Cloud9 环境。如以下屏幕截图所示,AWS Cloud9 控制台有三块区域需要了解:

    • 文件资源管理器:文件资源管理器位于 IDE 的左侧区域,会显示您目录中的文件列表。
    • 文件编辑器:文件编辑器位于 IDE 的右上区域,您可以在其中查看和编辑在文件资源管理器中选择的文件。
    • 终端:终端位于 IDE 的右下区域,您可以在其中运行用来执行代码示例的命令。
    (点击放大)

    在本教程中,您将使用 Python 与 Neptune 数据库进行交互。在 AWS Cloud9 终端运行以下命令,下载并解压缩模块代码。

    cd ~/environment
    curl -sL https://s3.amazonaws.com/aws-data-labs/fraud-detection.tar | tar -xv

    在 AWS Cloud9 终端运行以下命令,查看您的目录内容。

    ls

    在 AWS Cloud9 终端,您应当会看到两个目录:

    • scripts/:scripts 目录包含配置和准备您的数据库所需的文件。使用此目录测试数据库连接并将示例数据加载到数据库中。
    • application/:application 目录包含与应用程序中的文件相似的文件。这些文件会展示如何查询图形数据库以满足数据访问模式。

    在终端运行以下命令,安装应用程序的依赖项。

    sudo pip install -r requirements.txt

    pip install gremlinpython


    在本模块中,您配置了一个用于开发的 AWS Cloud9 实例。在下一个模块中,将创建一个 Neptune 数据库。

  • 在本模块中,我们将创建一个 Neptune 数据库。此数据库用于为应用程序中的欺诈检测服务提供支持。


    首先,前往 Neptune 控制台。点击 Create database(创建数据库),启动数据库创建向导。

    (点击放大)

     Engine options(引擎选项)部分中,使用默认 Neptune 版本。然后在 Settings(设置)部分中,为数据库提供标识符,例如 fraud-detection

    (点击放大)

    数据库创建向导包括一些模板,简化了创建过程。在本模块中,点击 Development and Testing(开发和测试)模板,以选择适用于本教程的默认值。

    (点击放大)

    在 DB instance size(数据库实例大小)部分中,保留默认值,即 db.t3.medium 实例。

    在 Availability & durability(可用性与持久性)部分中,保留默认值,即不使用 Multi-AZ deployment(多可用区部署)。在部署至生产环境时,建议您使用多可用区部署,以便在发生故障时提高可用性。

    (点击放大)

    在 Connectivity(连接)部分的 Additional connectivity configuration(其他连接配置)子部分中,对于 VPC security group(VPC 安全组),点击 Create new(新建)以创建一个新组。然后输入新的安全组名称 fraud-detection

    (点击放大)

    您可以配置标签或更新其他配置选项,但在本教程中保留默认值即可。

    点击 Create database(创建数据库),创建 Neptune 数据库。

    (点击放大)

    AWS 开始预配您的 Neptune 数据库。数据库正在进行预配时,其 Status(状态)显示为 Creating(正在创建)。

    数据库准备就绪时,其 Status(状态)显示为 Available(可用)。

    (点击放大)
    (点击放大)

    创建数据库后,您需要为其配置安全组,以允许从 AWS Cloud9 环境进行访问。

    为此,请前往 Amazon EC2 控制台上的 Security Groups(安全组)页面。您应该会看到 AWS Cloud9 环境和 Neptune 数据库的安全组。

    点击 Neptune 数据库对应的 Security group ID(安全组 ID)。

    (点击放大)

    随后的页面显示安全组的详细信息和网络规则。点击 Edit inbound rules(编辑入站规则),编辑安全组的入站网络规则。

    (点击放大)

    应该有一个现有的规则,允许从用于创建 Neptune 数据库的 IP 地址通过端口 8182 传输的 TCP 流量。编辑 Source(源)值,使其使用 AWS Cloud9 安全组。

    然后点击 Save rules(保存规则),保存您的入站规则。

    (点击放大)

    最后,应进行检查,确保正确配置了所有设置,并且可以从 AWS Cloud9 环境连接到 Neptune 数据库。

    返回 Neptune 控制台,找到您的 Neptune 数据库。点击 Role(角色)为 Cluster(集群)的 DB identifier(数据库标识符),查看有关集群的详细信息。

    (点击放大)

    在集群详细信息页面上,有一个 Cluster endpoint(集群端点)值。复制此值。

    (点击放大)

    在 AWS Cloud9 环境的终端运行以下命令,将集群端点设置为环境变量。

    export NEPTUNE_ENDPOINT=<yourClusterEndpoint>

    在运行该命令之前,请务必将 <yourClusterEndpoint> 替换为从 Neptune 控制台复制的值。

    在 scripts/ 目录中,有一个名为 test_connection.py 的文件。在文件编辑器中打开此文件。其内容应当如下所示。

    import os
    
    from gremlin_python.process.anonymous_traversal import traversal
    from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
    
    endpoint = os.environ["NEPTUNE_ENDPOINT"]
    
    g = traversal().withRemote(
        DriverRemoteConnection(f"wss://{endpoint}:8182/gremlin", "g")
    )
    
    results = g.V().count().next()
    
    print(f"Connected to Neptune! There are {results} vertices in the database")
    

    此脚本会尝试连接到 Neptune 以确保您的配置正确。首先,该脚本从 gremlinpython 库导入所需的库。Gremlin 是一种流行的图形遍历语言,可以通过 Apache TinkerPop 项目在应用程序中加以使用。

    导入库后,该脚本将使用您在环境中设置的 Neptune 端点创建一个 Gremlin 图形对象。最后,该脚本运行一个简单的 count 运算,测试连接。

    在终端运行以下命令,测试与 Neptune 数据库的连接。

    python scripts/test_connection.py

    您应该会看到一条消息,表明您能够连接到 Neptune 数据库,并且数据库中没有顶点。


    在本模块中,您使用 Neptune 创建了一个图形数据库。Neptune 提供全托管图形数据库,且与 Gremlin 等开源图形语言兼容。创建数据库后,您配置了安全组,允许来自 AWS Cloud9 环境的入站流量。最后,您了解了如何与 Neptune 进行连接,以及如何通过运行脚本来测试连接情况。

    在下一个模块中,您将为欺诈检测服务设计数据模型,并在表中加载示例数据。

  • 在本模块中,您将学习有关使用图形数据库进行数据建模的基础知识。然后,您将为欺诈检测服务设计数据模型,并在数据库中加载示例数据。


    图数据库可能与您过去使用的数据库(如关系数据库)有所区别。关于图形数据库,有几个关键术语需要了解:

    • Graph(图形):指的是整个数据库。类似于其他数据库中的表。
    • Vertex(顶点):顶点(也称为节点)表示图形中的项目。通常用于表示名词或概念,例如人物、地点和术语。vertex(顶点)的复数形式是 vertices(顶点),本教程中将使用该术语。
    • Edge(边):连接两个顶点。边通常表示实体之间的关系。例如,一起工作的两个人可能通过 WorksWith 边相连接。
    • Label(标签):可用于指示要添加的顶点或边的类型。例如,一些顶点可能具有标签 User,用于指示应用程序中的用户,一些顶点可能具有标签 Interest,用于指示人们可以关注的兴趣。
    • Property(属性):可以为顶点和边添加键值对。这些称为属性。例如,用户顶点具有 username 属性。

    查询图形时,通常从一个顶点开始,遍历各个边,查找与该原始顶点的关系。在欺诈检测使用场景中,可以从一个 User 顶点开始,遍历 Reviewed 边,找到该用户已进行评论的 Restaurant 顶点。

    构建图形数据模型时,应该考虑应用程序中的实体及其之间的关系。在图形数据库中建模的信息可能不同于主数据存储中存储的信息。

    例如,主数据库可能包含每个用户的出生日期信息。虽然您可能会在主数据库中使用该信息,例如在用户生日时发送特别优惠,但这对于欺诈检测服务来说可能并不重要。由于出生日期不太可能影响欺诈行为,因此可以将其完全从图形数据库中删除。

    相反,可能有一些信息没有存储在主数据库中,但在图数据库中却很有用。当用户对餐厅留下评论时,您可能不需要存储留下评论时使用的 IP 地址。然而,当您查找使用相同 IP 地址的机器人执行的一连串欺诈活动时,IP 地址在欺诈检测服务中可能非常有用。

    了解这些内容后,下图中展示了一个粗略的欺诈检测服务数据模型示例。

    (点击放大)

    在上面的数据模型中,顶点显示为椭圆形。此示例中有四个顶点,三种不同的类型:

    • User:表示应用程序中的用户。User 顶点具有 User 标签和 username 属性。
    • Restaurant:表示应用程序中的餐厅。Restaurant 顶点具有 Restaurant 标签和 name 属性。
    • IPAddress:表示 User 在对 Restaurant 评论时使用的 IP 地址。IPAddress 顶点具有 IPAddress 标签和 address 属性。

    此外,此图中还有两种类型的三条边:

    • Reviewed:表示 User 针对 Restaurant 提交的评论。Reviewed 边具有 Reviewed 标签和 rating 属性。
    • Used:表示 User 提交评论时使用的 IPAddressUsed 边具有 Used 标签。

    现在,将一些示例数据加载到图形数据库中,测试访问模式。

    在 scripts/ 目录中,有一个名为 bulk_load_database.py 的文件。在文件编辑器中打开此文件。您应当会看到以下内容。

    import json
    import os
    
    from gremlin_python.process.anonymous_traversal import traversal
    from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
    
    endpoint = os.environ["NEPTUNE_ENDPOINT"]
    
    g = traversal().withRemote(
        DriverRemoteConnection(f"wss://{endpoint}:8182/gremlin", "g")
    )
    
    with open("scripts/vertices.json", "r") as f:
        for row in f:
            data = json.loads(row)
            if data["label"] == "User":
                g.addV("User").property("username", data["username"]).next()
            elif data["label"] == "Restaurant":
                g.addV("Restaurant").property("name", data["name"]).next()
            elif data["label"] == "IPAddress":
                g.addV("IPAddress").property("address", data["address"]).next()
    
    with open("scripts/edges.json", "r") as f:
        for row in f:
            data = json.loads(row)
            if data["label"] == "Used":
                g.V().has("User", "username", data["username"]).as_("user").V().has(
                    "IPAddress", "address", data["ip_address"]
                ).as_("ip_address").addE("Used").from_("user").to("ip_address").next()
            elif data["label"] == "Reviewed":
                g.V().has("User", "username", data["username"]).as_("user").V().has(
                    "Restaurant", "name", data["restaurant"]
                ).as_("restaurant").addE("Reviewed").from_("user").to(
                    "restaurant"
                ).property(
                    "rating", data["rating"]
                ).property(
                    "username", data["username"]
                ).property(
                    "restaurant", data["restaurant"]
                ).next()
    
    print("Loaded data successfully!")

    该文件从两个文件(scripts/vertices.json 和 scripts/edges.json)加载数据,并将数据插入到 Neptune 数据库。查看代码,了解如何在应用程序代码中创建顶点和边。您将使用 Gremlin 软件包中的 addV() 和 addE() 方法在代码中添加顶点和边。

    要执行批量加载脚本并将记录插入到数据库,请在终端运行以下命令。

    python scripts/bulk_load_database.py

    加载所有记录需要一些时间。您应该会看到指示数据已成功加载的输出。

    再次执行 scripts/test_connection.py 脚本,查看加载后表中的顶点数。

    $ python scripts/test_connection.py
    Connected to Neptune! There are 118 vertices in the database

    成功了!您将项目加载到了 Neptune 数据库中。


    在本模块中,您学习了使用图形数据库的基本术语。然后,为欺诈检测服务设计了数据模型。最后,将一些示例数据加载到了数据库中。

    在下一个模块中,您将对图形数据库运行一些查询,以帮助识别欺诈活动。

  • 在本模块中,您将学习如何在应用程序中使用图形数据库。您将执行一些 Gremlin 图形遍历查询,以识别餐厅评论应用程序中潜在的一连串欺诈活动。


    图形数据库在遍历整个应用程序中的关系方面非常高效。它们可用于查找实体之间的联系,而使用其他数据库却很难发现。因此,它们常常用于欺诈检测和社交网络应用程序。

    我们先来看看第一个使用场景。假设您遇到了自动机器人给餐厅刷了大量一星评级的问题。餐厅老板对您的服务感到不满,因为用户大量留下低分评级,损害了餐厅的声誉。您希望找出来自机器人的流量并删除这些恶意评级。

    假设有一个 IP 地址已标记为可疑。您想查明哪些用户使用过该 IP 地址,以及这些用户是否给出了大量一星评论。

    在 applications/ 目录中,有一个名为 find_users_of_suspicious_ip_addresses.py 的文件。在文件编辑器中打开此文件。其内容应当如下所示。

    import os
    
    from gremlin_python.process.anonymous_traversal import traversal
    from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
    from gremlin_python import statics
    
    statics.load_statics(globals())
    
    
    endpoint = os.environ["NEPTUNE_ENDPOINT"]
    
    g = traversal().withRemote(
        DriverRemoteConnection(f"wss://{endpoint}:8182/gremlin", "g")
    )
    
    
    def find_users_of_suspicious_ip_addresses(ip_address):
        results = (
            g.V()
            .has("IPAddress", "address", ip_address)
            .as_("ip_address")
            .in_("Used")
            .aggregate("ip_address_users")
            .outE("Reviewed")
            .has("rating", 1)
            .values("username")
            .groupCount()
            .order(local)
            .by(values, desc)
            .limit(local, 10)
            .toList()
        )
    
        return [
            {"username": k, "1-star reviews": v}
            for result in results
            for k, v in result.items()
        ]
    
    
    suspicious_users = find_users_of_suspicious_ip_addresses("173.153.51.29")
    
    for user in suspicious_users:
        print(
            f"User {user['username']} has written {user['1-star reviews']} one-star reviews."
        )

    当库导入数据库连接逻辑后,有一个名为 find_users_of_suspicious_ip_adddresses 的函数。该函数获取一个 IP 地址,并根据用户留下的一星评论数量返回使用该地址的前 10 名用户列表。这类似于欺诈检测服务中的函数。

    查看用于查询 Neptune 数据库的查询。该查询从图形对象开始,并使用 V().has() 语法查找表示给定 IP 地址的顶点,从而找到有问题的 IP 地址。接着,遍历连接 IP 地址顶点的边,以找到使用过该 IP 地址的用户。然后,查看连接这些用户的已评论边,以查找评级为 1 的用户。最后,根据一星评级的数量对用户进行分组,并返回找到的前 10 名用户。

    在本模块的底部提供了一个示例,说明了如何使用给定 IP 地址调用函数。调用后将输出相应的结果。

    要测试该函数,请在终端运行以下命令。

    python application/find_users_of_suspicious_ip_addresses.py

    您应当会在终端看到以下结果。

    $ python application/find_users_of_suspicious_ip_addresses.py
    User clester has written 10 one-star reviews.
    User hhouston has written 5 one-star reviews.

    太棒了!您发现了两个可能存在欺诈行为的用户。

    尽管这种方法可以发现使用相同 IP 地址的机器人用户,但您的对手可能会变得更狡猾,改为利用多个 IP 地址采取行动。您也可以使用图形数据库发现一连串遭到泄露的 IP 地址。

    在 application/ 目录中,有一个名为 find_related_suspicious_ip_addresses.py 的文件。在文件编辑器中打开此文件。其内容应当如下所示。

    import os
    
    from gremlin_python.process.anonymous_traversal import traversal
    from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
    from gremlin_python import statics
    
    statics.load_statics(globals())
    
    
    endpoint = os.environ["NEPTUNE_ENDPOINT"]
    
    g = traversal().withRemote(
        DriverRemoteConnection(f"wss://{endpoint}:8182/gremlin", "g")
    )
    
    
    def find_related_suspicious_ip_addresses(ip_address):
        results = (
            g.V()
            .has("IPAddress", "address", ip_address)
            .as_("ip_address")
            .in_("Used")
            .aggregate("ip_address_users")
            .out("Used")
            .where(neq("ip_address"))
            .values("address")
            .groupCount()
            .order(local)
            .by(values, desc)
            .limit(local, 10)
            .toList()
        )
    
        return [
            {"ip_address": k, "user_overlap": v}
            for result in results
            for k, v in result.items()
        ]
    
    
    suspicious_ip_addresses = find_related_suspicious_ip_addresses("173.153.51.29")
    
    for user in suspicious_ip_addresses:
        print(
            f"IP address {user['ip_address']} has {user['user_overlap']} overlapping users."
        )

    此文件的内容与前一个文件类似。有一个名为 find_related_suspicious_ip_addresses 的函数,该函数与您的服务中的函数类似。该函数获取一个 IP 地址,并返回使用该可疑 IP 地址的用户使用过的所有 IP 地址。这可以用来识别一连串的不良行为用户。

    在此文件的底部,有一条语句使用可疑 IP 地址执行该函数。在终端运行以下命令,测试该脚本。

    python application/find_related_suspicious_ip_addresses.py

    您应当会在终端看到以下输出结果。

    $ python application/find_related_suspicious_ip_addresses.py
    IP address 174.70.217.249 has 1 overlapping user.

    成功了!您发现了另一个可疑的 IP 地址。您可以在前面的函数中使用此 IP 地址,查看是否也有使用该 IP 地址的可疑用户。


    在本模块中,您了解了如何在应用程序中使用图形数据库。您使用 Gremlin 查询语言遍历了图形以查找相关实体并识别欺诈活动。

    在下一个模块中,您将清除在本教程中创建的资源。

  • 在本教程中,您使用 Neptune 创建了一个图形数据库,用于欺诈检测服务。图形数据库非常适合遍历关联紧密的数据,以发现应用程序中实体之间隐藏的关系。使用 Neptune,您可以获得全托管图形数据库,从而您能够专注于构建令用户满意的功能。

    在本模块中,您将清除在本教程中创建的资源,以免产生额外费用。


    首先,删除您的 Neptune 数据库。为此,请前往 Neptune 控制台。选择所创建数据库的 Writer(写入器)实例,然后在 Actions(操作)下拉菜单中点击 Delete (删除)。

    (点击放大)

    在删除数据库之前会显示一个确认页面。在本教程中,您可以选择不保留数据库的最终快照。点击 Delete(删除)以确认删除。

    (点击放大)

    Neptune 页面显示正在删除 Writer(写入器)实例。

    (点击放大)

    删除 Writer(写入器)实例后,Neptune 也会删除 Cluster(集群)实例。

    (点击放大)

    此外,您还需要删除 AWS Cloud9 开发环境。

    为此,请前往 AWS Cloud9 控制台。选择您为本教程创建的环境,然后点击 Delete(删除)。

    (点击放大)

    在本模块中,您学习了如何清除在本教程中创建的 Neptune 数据库和 AWS Cloud9 环境。

在本教程中,您学习了如何在应用程序中创建和使用 Neptune 数据库。首先,您创建了一个 Neptune 数据库,并配置了网络访问权限,以便与数据库进行连接。然后,您学习了使用图形数据库进行数据建模,并在数据库中加载示例数据。最后,您了解了如何在应用程序中查询图形数据库以遍历数据中的关系。当您使用 Neptune 构建应用程序时,可以使用这些模式。

此页内容对您是否有帮助?