图数据库满足了传统数据库未能满足的需求:它们优先考虑实体之间的关系。这使得图数据库在查找模式、进行预测和找到解决方案方面非常高效。
尽管它是一个通用目的的 文档数据库,但 MongoDB 通过聚合管道中的 $graphLookup 阶段提供图形和树遍历功能。对于需要更高级图形功能或频繁使用图形功能的程序,MongoDB 也可以与专用图数据库结合使用。
本文将探讨以下问题的答案
图数据库是一种数据库,它使用节点和边来存储数据——节点用于存储有关实体的信息,边用于存储节点之间的关系或动作的信息。这种数据模型允许图数据库优先考虑数据之间的关系,这使得在数据中搜索连接和模式比传统数据库更容易。
图数据库使用以下关键术语
以下部分包含了一个示例,说明了如何使用节点、边、属性和标签在图数据库中对数据进行建模。
让我们来看看数据在图数据库中是如何存储的。假设您想存储航空旅行信息。
每个机场都将由一个节点表示,而有关机场的信息将存储在节点的属性中。例如,您可以为新西兰的奥克兰机场创建一个节点,并具有诸如 airport_code: AKL
和 country: New-Zealand
这样的属性。
两个机场之间的航班——即两个节点之间的关系——由边表示。边的属性包含有关航班的信息。在本例中,您可以在奥克兰机场节点和布里斯班机场节点之间创建一个边。该边可以具有如 airplane: 73H 388
和 airline: Qantas
这样的属性。
节点表示奥克兰机场,其属性如下所示。边表示从奥克兰机场到布里斯班机场的航班,包含飞机和航空公司的属性。
除了机场节点外,您可能还会创建表示其他相关实体的节点,例如机场餐厅。您可能选择将“机场”标签应用于机场节点,将“餐厅”标签应用于餐厅节点。下面的图显示了包含多个节点、边、属性和标签的图形。
表示机场、机场餐厅和航班的图形。
在新标签页中打开图像.
由于图数据库优先考虑关系,它们允许用户高效地查询节点之间的关系以寻找模式和做出预测。在一个越来越重视智能决策和推荐的世界里,图数据库在关系数据库无法胜任的领域大放异彩。
此外,图数据库提供了一种灵活的架构。这允许开发者在需求不可避免地变化和发展的同时,轻松地对他们的数据库进行更改。灵活的架构对于构建现代应用的敏捷团队来说非常有价值。
图数据库适用于各种用例。其中一些最常见的是检测欺诈、构建推荐引擎、管理IT网络和计算数据之间的图算法。
检测欺诈。图数据库常用于洗钱、信用卡欺诈、保险欺诈、税务欺诈和其他犯罪活动的检测。近年来,犯罪分子在他们的阴谋中变得更加复杂。他们不是从单一点或账户开始工作,而是创建了一个由更小的阴谋组成的欺诈团伙,这些阴谋更难被发现。图数据库允许分析师查看数据之间的联系,以找到欺诈模式。
构建推荐引擎。现代企业希望通过提供智能推荐作为增加收入的一种战略手段。图数据库允许应用程序分析以前的购买数据,以确定客户可能想要购买什么。
管理IT网络。图数据库可以帮助IT专家建模和管理网络、IT基础设施和物联网设备。因为这些实体在现实世界中是物理连接的,所以它们自然映射到图上。图数据库可以使组织轻松进行影响分析和计划中断。
计算图算法。当您需要在数据之间的连接上进行高效计算时,图数据库是一个很好的选择。它们被广泛用于计算图算法,如最短路径和PageRank。这些算法被用于从寻找两个位置之间的最便宜航班到确定社交网络中的影响力的各个方面。
如上所述,当您需要分析实体之间的关系以寻找模式、生成智能推荐、建模网络或计算图算法时,图数据库是一个很好的选择。
图数据库对于非遍历查询的性能通常较差。大多数应用程序都需要此类查询,因此它们需要一个通用数据库。对于既需要图数据库又需要通用数据库的应用程序,开发者有两个选择
MongoDB是一个通用文档数据库。如图下所示,文档模型是其他数据处理方式的超集,包括键值对、关系、对象、图和地理空间。
文档是所有其他数据模型的超集。
MongoDB 有一个用于查询图的 $graphLookup
聚合管道阶段。 $graphLookup
非常适合遍历图、树和层次化数据。请注意,$graphLookup
可能不如独立的图数据库性能好,也不提供完整的图算法功能。
如果您的应用程序将频繁运行图查询,考虑将您的 MongoDB 数据库与图数据库相结合。请注意,数据库的耦合会显著增加您的架构复杂性,需要您在两个不同的系统中保持数据同步,并使用不同的语言查询它们。因此,如果您的图查询需求可以通过 MongoDB 内置的功能满足,您可能最好将所有内容放在一个地方,并使用单个 API 与您的数据交互。
有关 MongoDB 中图功能的信息,请查看关于 在 MongoDB 中处理图数据 的网络研讨会。
MongoDB 有一个执行递归搜索的 $graphLookup
聚合管道阶段,可以用于遍历文档之间的连接。
让我们看看来自 routes
集合 的一个例子,该集合包含在 MongoDB Atlas 示例数据集 中。 routes
集合包含关于机场之间航空路线的信息。以下是 routes
集合中的一个示例文档。
{
_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)和空客 380-800(388)。该文档还表明,运营此路线的航空公司是 Qantas。
让我们查询所有可以从奥克兰机场直接或通过转机航班到达的可能目的地。我们可以使用 MongoDB 的 聚合管道 来构建我们的查询。我们可以从 $match
阶段开始,以匹配 src_airport
为 AKL
的文档。然后我们可以使用 $graphLookup
阶段递归搜索匹配当前文档 dst_airport
的 src_airport
的文档。以下是将在 MongoDB shell 中运行的完整 aggregate 命令。请注意,此查询可能需要几分钟才能运行,因为它搜索所有可能的路线。
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 中运行的完整 aggregate
命令。
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
的数组,其中包含有关从连接处开始并由 Qantas 运营的航线的详细信息。以下是运行上述聚合命令的部分输出。
[
{
_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'
},
…
]
}
…
]
上面提到的例子只是对您可以使用 $graphLookup
做的事情的一个品尝。请查看 MongoDB 官方文档中的 $graphLookup
,以及关于 聚合框架 的免费 MongoDB 大学课程。
$graphLookup
聚合管道阶段 可以用于遍历图。对于需要更高级图功能的应用程序,可以将通用数据库(如 MongoDB)与专用图数据库相结合。