什么是关联查询?
在传统的关系型数据库中,为了把不同表之间的关系联系起来,我们通常使用“关联查询”。关联查询是指在一个查询中,我们可以通过查找两个或更多的表之间的相关信息,然后将它们聚合到一个结果集中。
在 MongoDB 中,由于其文档存储的灵活性,有些不同的方法可以实现类似的功能。本文将介绍 MongoDB 中的一些不同的关联查询方法。
一对一关联查询
一对一关联查询是指,一个文档中包含了另一个文档的全部信息。在 MongoDB 中,我们可以使用 DBRef
或嵌套子文档来实现一对一关联查询。
DBRef
DBRef
是 MongoDB 中定义的一种特殊的文档类型,用于表示文档之间的关系。它包含了三个字段:
$ref
:引用的集合名称(字符串类型)。$id
:所引用的文档的_id
值(任意类型)。$db
:引用该文档所在的数据库名称。
例如,我们有一个 users
集合和一个 addresses
集合,每个用户只有一个地址,我们可以这样进行关联查询:
db.users.insert({ name: "John", address: { $ref: "addresses", $id: ObjectId("5fcf068237b97f0d7e0b8f68"), $db: "myDB" } }); db.addresses.insert({ _id: ObjectId("5fcf068237b97f0d7e0b8f68"), street: "123 Main St", city: "Anytown", state: "CA" });
使用 $ref
、$id
和 $db
这三个字段,我们可以将 users
集合中的 address
字段与 addresses
集合中的 _id
值进行关联。这样,我们就可以通过单个查询获取用户和他们的地址信息:
db.users.aggregate([ { $lookup: { from: "addresses", localField: "address.$id", foreignField: "_id", as: "address" } } ]);
此查询将返回一个包含 users
和 addresses
信息的新文档,其中 address
字段将是一个数组,包含了每个用户的地址信息。
嵌套子文档
另一种实现一对一关联查询的方法是使用嵌套子文档。在这种情况下,我们可以将所有相关信息存储在一个文档中,并将其作为另一个文档的子节点。
例如,我们可以使用以下方案来存储用户和他们的地址信息:
db.users.insert({ name: "John", address: { street: "123 Main St", city: "Anytown", state: "CA" } });
然后,我们可以通过简单的查询来获取用户和他们的地址信息:
db.users.find();
这将返回包含所有用户信息(包括他们的地址)的文档。
一对多关联查询
在MongoDB中, 一对多 关联查询是指一个集合中的文档可以与多个其他集合中的文档相关联。这种情况下,我们通常使用嵌套子文档或者聚合管道进行关联查询。
嵌套子文档
与一对一关联查询类似,我们可以使用嵌套子文档在一个文档中存储与其他集合中相关联的信息。但是在这种情况中,我们需要将信息存储为数组,以便每个文档可以与多个其他文档相关联。
例如,我们有一个 users
集合和一个 orders
集合。每个用户可以有多个订单,我们可以通过这种方式进行关联查询:
db.users.insert({ name: "John", orders: [ { order_number: 1234, total: 100.0 }, { order_number: 1235, total: 300.0 }, { order_number: 1236, total: 150.0 } ] }); db.users.find();
这将返回包含所有用户信息(包括他们的订单)的文档。
聚合管道
在 MongoDB 中,我们可以使用聚合管道来执行一对多的关联查询。聚合操作可以通过 $lookup
操作符来实现,它类似于一对一关联查询中的 lookup
操作。
例如,我们有一个 users
集合和一个 orders
集合,每个用户可以有多个订单。下面的聚合操作将在查询中将这两个集合关联起来:
-- -------------------- ---- ------- -------------------- - -------- - ----- --------- ----------- ------ ------------- ---------- --- -------- - - ---
此查询将返回包含所有用户信息和其所有订单信息的文档,其中 orders
字段将是一个数组,包含了每个用户的所有订单。
多对多关联查询
多对多关联查询表示两个或多个文档集合之间的多对多关系。我们可以使用嵌套子文档或中间表进行关联查询。
嵌套子文档
我们可以在每个文档中为其关联的文档中存储一个数组。例如,我们有一个 users
集合和一个 groups
集合,每个用户可以隶属于多个组,每个组也可以有多个用户:
db.users.insert({ name: "John", groups: ["admin", "sales"] }); db.users.insert({ name: "Jane", groups: ["sales", "marketing"] }); db.groups.insert({ name: "admin", users: ["John"] }); db.groups.insert({ name: "sales", users: ["John", "Jane"] }); db.groups.insert({ name: "marketing", users: ["Jane"] });
这样,我们可以通过简单的查询来获取每个组和其所有用户的信息:
db.groups.find();
这将返回包含每个组信息和其所有用户信息的文档。
中间表
我们可以使用中间表来记录两个文档之间的关系。中间表存储可以将两个不同文档集合中的文档进行链接的唯一 ID 值。例如,我们可以使用以下方案来实现 users
集合和 groups
集合间的关联查询:
-- -------------------- ---- ------- ----------------- ----- ------ --- ----------------- ----- ------ --- ------------------ ----- ------- --- ------------------ ----- ------- --- ------------------ ----- ----------- --- ----------------------- -------- ------------------------------------- --------- ------------------------------------ --- ----------------------- -------- ------------------------------------- --------- ------------------------------------ --- ----------------------- -------- ------------------------------------- --------- ------------------------------------ --- ----------------------- -------- ------------------------------------- --------- ------------------------------------ ---
在这里,我们创建了一个名为 user_groups
的集合,它记录了 users
和 groups
集合之间的多对多关系。这样,我们可以通过简单的聚合操作来实现关联查询:
-- -------------------- ---- ------- -------------------- - -------- - ----- -------------- ---- - -------- ------ -- --------- - - ------- - ------ - ----- - - ---- - ----------- ----------- - - - - - -- - -------- - ----- --------- ----------- ----------- ------------- ------ --- -------- - - -- --- -------- - - ---
此查询将返回包含每个用户和其隶属于的所有组的信息的文档,其中 groups
字段将是一个数组,包含了每个用户的所有组。
结论
在 MongoDB 中,由于其灵活的文档结构,我们可以使用多种方法来实现关联查询。无论是一对一,一对多还是多对多关系,我们都可以使用嵌套子文档、中间表或聚合管道来实现查询。熟练掌握不同的关联查询方法可以帮助开发人员更好地管理文档集合之间的复杂关系,并提高应用程序的效率。
参考资料
- MongoDB Manual: DBRef
- MongoDB Manual: $lookup
- MongoDB Manual: Aggregation Pipeline Stages
- MongoDB University: M101 MongoDB for Developers
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/673195e20bc820c582395b5c