MongoDB通过其graphLookup阶段提供图形能力。在MongoDB Atlas中创建一个免费集群,尝试使用graphLookup。

图形数据库满足了传统数据库未能满足的需求:它们优先考虑实体之间的关系。这使得图形数据库在寻找模式、进行预测和寻找解决方案方面非常高效。

虽然 MongoDB 是一个通用文档数据库,但它通过聚合管道中的 $graphLookup 阶段提供了图形和树遍历功能。对于需要更高级图形功能或经常使用图形功能的应用程序,MongoDB 也可以与专用图形数据库配合使用。

1.什么是图形数据库?

图形数据库是一种将数据存储在节点和边缘中的数据库——节点用于存储有关实体的信息,而边缘用于存储有关节点之间关系或操作的信息。这种数据模型使得图形数据库能够优先处理数据之间的关系,从而比传统数据库更容易搜索连接和模式。

图形数据库使用以下关键术语:

Nodes (or vertices)      :节点(或顶点)。您可以将节点视为数据库中的名词;它们存储有关人、地点和物品的信息。
Edges (or relationships) :边缘(或关系)。您可以将边缘视为数据库中的动词;它们存储有关在节点之间执行的操作的信息。
Properties               :属性。属性是存储有关特定节点或边缘信息的键值对。
Labels                   :标签。标签可选择用于标记一组相关节点。

下面的部分包含了一个使用节点、边缘、属性和标签在图形数据库中建模数据的示例。

(1).数据如何存储在图形数据库中?

让我们来了解一下图形数据库中数据是如何存储的。假设你想要存储航空旅行信息。

每个机场都将由一个节点表示,并且有关机场的信息将存储在节点的属性中。例如,您可以创建一个代表新西兰奥克兰机场的节点,并在其属性中存储诸如airport_code: AKL和country: New-Zealand等信息。

两个机场之间的航班,也就是两个节点之间的关系,由一条边来表示。这条边的属性包含有关航班的信息。在此示例中,您可以在奥克兰机场和布里斯班机场之间创建一条边。该边可以具有飞机:73H 388 和航空公司:澳洲航空等属性。

MongoDB作为图形数据库_数据

一个节点代表奥克兰机场,列出了它的属性。一条边表示从奥克兰机场到布里斯班机场的航班,具有飞机和航空公司的属性。  

除了用于机场的节点外,您可能还会为其他相关实体创建节点,例如机场餐厅。您可以选择将“Airport”标签应用于机场节点,“Restaurant”标签应用于餐厅节点。下面的图显示了一个带有多个节点、边、属性和标签的图形。

MongoDB作为图形数据库_图形数据库_02

一个代表机场、机场餐厅和航班的图表。

(2).为什么你应该关注图形数据库?

由于图形数据库优先考虑关系,它们允许用户高效地查询节点之间的这些关系以寻找模式并进行预测。在一个越来越重视智能决策和推荐的世界中,图形数据库在关系型数据库难以胜任的领域表现出色。

此外,图形数据库提供了灵活的架构。这使得开发人员可以轻松地根据不断变化和演进的需求对其数据库进行更改。灵活的架构对于构建现代应用程序的敏捷团队非常有价值。

(3).图形数据的常见用例有哪些?

图形数据库适用于各种用例。其中一些最常见的包括检测欺诈、构建推荐引擎、管理IT网络以及在数据之间计算图形算法。

1.Detecting fraud(检测欺诈)。图形数据库通常用于检测洗钱、信用卡欺诈、保险欺诈、税务欺诈和其他犯罪活动。近年来,犯罪分子在其计划中变得越来越复杂。他们不再从单一点或账户工作,而是创建一个更容易被忽视的小型方案的欺诈环。图形数据库允许分析人员查看数据之间的连接以找到欺诈模式。
2.Building recommendation engines(构建推荐引擎)。现代企业希望通过提供智能推荐给客户作为增加收入的战略方式。图形数据库允许应用程序分析先前购买数据以确定客户可能想要购买下一个什么产品。
3.Managing IT networks(管理IT网络)。图形数据库可以帮助IT专家对网络、IT基础设施和物联网设备进行建模和管理。由于这些实体在现实世界中是物理连接的,它们自然地映射到图形上。图形数据库可以使组织轻松执行影响分析并计划停机时间。
4.Computing graph algorithms(计算图算法)。当您需要高效地对数据之间的连接进行计算时,图形数据库是一个很好的选择。它们广泛用于计算最短路径和PageRank等图算法。这些算法用于从找到两个位置之间最便宜的航班到确定社交网络中的影响力等各种应用场景中。
(4).图形数据库的关键考虑因素是什么?

如上所述,图形数据库是在需要分析实体之间的关系以寻找模式、生成智能推荐、建模网络或计算图形算法时的绝佳选择。

对于非遍历查询,图形数据库往往性能较差。大多数应用程序都需要这样的查询,因此它们需要一个通用数据库。对于那些既可以从图形数据库中受益又可以从通用数据库中受益的应用程序,开发人员有两个选择:

1.将通用数据库(如文档或关系型数据库)与图形数据库配对使用。
2.使用具有图形能力的通用数据库(如MongoDB)。

2.MongoDB 如何与图形数据集成?

MongoDB是一种通用的文档数据库。如下图所示,文档模型是其他数据处理方式(包括键值对、关系型、对象、图形和地理空间)的超集。

MongoDB作为图形数据库_数据库_03

文档是所有其他数据模型的超集。 

MongoDB具有graphLookup聚合管道阶段,用于查询图形。 graphLookup非常适合遍历图形、树和分层数据。请注意,graphLookup可能不如独立的图形数据库性能好或提供完整的图形算法功能。

如果您的应用程序将频繁运行图形查询,请考虑将MongoDB数据库与图形数据库耦合使用。请注意,耦合数据库会在架构中引入重大复杂性,需要您在两个不同系统之间保持数据同步,并使用不同语言进行查询。因此,如果内置于MongoDB中的功能可以满足您对图表查询的要求,则最好将所有内容放在一起并使用单个API与数据交互。

如何在 MongoDB 中执行一个图查询?

MongoDB有一个graphLookup聚合管道阶段,可以执行递归搜索。 graphLookup可用于遍历文档之间的连接。

让我们看一下MongoDB Atlas示例数据集中包含的路线集合中的一个示例。 路由集合包含有关机场之间航空公司路线的信息。 下面是来自路线集合的样本文档。

{
   _id:"56e9b39c732b6122f878b0cc",
   airline: {
     id: 4089, 
     name: 'Qantas', 
     alias: 'QF', 
     iata: 'QFA' 
   },
   src_airport: 'AKL',
   dst_airport: 'BNE',
   airplane: '73H 388'
 }

上述文件存储了有关从奥克兰机场(AKL)到布里斯班机场(BNE)的路线信息。该文件指出,分配给此路线的飞机是波音737-800(73H)和空客A380-800(388)。该文件还指出,经营此航线的航空公司是澳洲航空公司。

让我们查询可以通过直达或中转航班从奥克兰机场到达的所有可能目的地。我们可以使用MongoDB聚合管道来构建查询。我们可以以match阶段开始聚合管道,以匹配src_airport为AKL的文档。然后,我们可以使用graphLookup阶段递归搜索src_airport与当前文档dst_airport相匹配的文档。以下是在MongoDB shell中运行完整聚合命令。请注意,由于它会搜索所有可能路径,因此这个查询可能需要几分钟才能运行完成.

db.routes.aggregate(
[
  {
    $match: {
        src_airport: 'AKL'
    }
  }, 
  {
    $graphLookup: {
        from: 'routes',
        startWith: '$dst_airport',
        connectFromField: 'dst_airport',
        connectToField: 'src_airport',
        as: 'routesThatCanBeReached',
        depthField: 'numberOfAdditionalStops'
    }
 }
])

结果是一组文档。结果中的每个文档都是从AKL起始的路线。每个文档还包含一个名为routesThatCanBeReached的数组,其中列出了可以直接或间接到达该路线的所有路线。numberOfAdditionalStops字段指示乘客在完成此路线后需要多少个额外停靠站点。以下是运行上述聚合命令时输出的部分内容。

[
 {
   _id: "56e9b39c732b6122f878b0cc",
   airline: { id: 4089, name: "Qantas", alias: "QF", iata: "QFA" },
   src_airport: "AKL",
   dst_airport: "BNE",
   airplane: "73H 388",
   routesThatCanBeReached: [
     {
       _id: "56e9b39c732b6122f8787a6d",
       airline: { id: 2822, name: "Iberia Airlines", alias: "IB", iata: "IBE" },
       src_airport: "ORY",
       dst_airport: "IBZ",
       airplane: "320",
       numberOfAdditionalStops: 3
     },
     {
       _id: "56e9b39c732b6122f87882a1",
       airline: { id: 3052, name: "Jetstar Airways", alias: "JQ", iata: "JST" },
       src_airport: "BNE",
       dst_airport: "LST",
       airplane: "320",
       numberOfAdditionalStops: 0
     }
     ...
   ]
 },
 {
   _id: "56e9b39c732b6122f878b0cd",
   airline: { id: 4089, name: "Qantas", alias: "QF", iata: "QFA" },
   src_airport: "AKL",
   dst_airport: "MEL",
   airplane: "73H",
   routesThatCanBeReached: [
     ...    
   ]
 },
 ...
]

假设我们想进一步细化这个查询。我们希望将结果限制为最多只有一个停靠点的旅行。为此,我们可以将maxDepth设置为0,以指示查询应使用最大递归深度为0。我们还可以选择仅搜索特定航空公司的航班,方法是使用restrictSearchWithMatch属性。以下是在MongoDB shell中运行的完整聚合命令:

db.routes.aggregate([
    {
        '$match': {
            'src_airport': 'AKL', 
            'airline.name': 'Qantas'
        }
    }, {
        '$graphLookup': {
            'from': 'routes', 
            'startWith': '$dst_airport', 
            'connectFromField': 'dst_airport', 
            'connectToField': 'src_airport', 
            'as': 'airportsThatCanBeReachedWithOnlyOneStop', 
            'maxDepth': 0, 
            'restrictSearchWithMatch': {
                'airline.name': 'Qantas'
            }
        }
    }
  ]
)

就像我们之前运行的命令一样,结果是一组文档。每个文档都包含一个名为airportsThatCanBeReachedWithOnlyOneStop的数组,其中包含从连接点开始并由澳洲航空公司操作的路线信息。以下是运行上述聚合命令时输出的部分内容。

[
  {
    _id: ObjectId("56e9b39c732b6122f878b0cc"),
    airline: { id: 4089, name: 'Qantas', alias: 'QF', iata: 'QFA' },
    src_airport: 'AKL',
    dst_airport: 'BNE',
    airplane: '73H 388',
    airportsThatCanBeReachedWithOnlyOneStop: [
      {
        _id: ObjectId("56e9b39c732b6122f878b104"),
        airline: { id: 4089, name: 'Qantas', alias: 'QF', iata: 'QFA' },
        src_airport: 'BNE',
        dst_airport: 'LDH',
        airplane: 'DH8'
      },
      {
        _id: ObjectId("56e9b39c732b6122f878b0f8"),
        airline: { id: 4089, name: 'Qantas', alias: 'QF', iata: 'QFA' },
        src_airport: 'BNE',
        dst_airport: 'CBR',
        airplane: '717 73H'
      },
…
 {
    _id: ObjectId("56e9b39c732b6122f878b0cd"),
    airline: { id: 4089, name: 'Qantas', alias: 'QF', iata: 'QFA' },
    src_airport: 'AKL',
    dst_airport: 'MEL',
    airplane: '73H',
    airportsThatCanBeReachedWithOnlyOneStop: [
      {
        _id: ObjectId("56e9b39c732b6122f878b1bd"),
        airline: { id: 4089, name: 'Qantas', alias: 'QF', iata: 'QFA' },
        src_airport: 'MEL',
        dst_airport: 'HBA',
        airplane: '73H'
      },
    …
    ]
}
…
]

这里就是mongodb中对图形数据的操作。