mongodb实现同库联表查询方法示例

1. MongoDB简介

MongoDB是一款面向文档的开源数据库系统,由C++语言编写,旨在为WEB应用提供可扩展、高性能、完全无操作数据库的解决方案。在MongoDB中,数据存储在类似于JSON的BSON格式中,BSON是一种二进制编码格式,能够高效地存储数据。MongoDB的特点是高性能、高可扩展性、丰富的查询语言、支持的复杂数据结构以及灵活的数据模型。

2. MongoDB联表查询

MongoDB是一款NoSQL数据库,相对于关系型数据库而言,它对于联表查询有自己独特的处理方式。在关系型数据库中,为了实现两张表的关联查询,需要使用JOIN操作,而在MongoDB中,可以通过嵌套数据结构和引用方式完成多张表的关联操作。

2.1. 嵌套数据结构

在MongoDB中,可以将一个文档对象嵌套在另一个文档对象中,从而实现对多个集合的关联操作。例如:

// 学生集合

{

"_id": ObjectId("5e3f7e72c287e604696a0e96"),

"name": "张三",

"age": 18,

"class": "1班",

"grade": {

"math": 90,

"english": 80,

"chinese": 85

}

}

// 班级集合

{

"_id": ObjectId("5e3f7e72c287e604696a0e97"),

"name": "1班",

"teacher": "李老师"

}

上述代码中,可以看到学生集合中的class属性和班级集合中的name属性可以建立起联系,达到关联查询的目的。在查询时,可以使用$lookup操作符完成两张表之间的关联操作,示例如下:

db.students.aggregate([

{

$lookup: {

from: "classes",

localField: "class",

foreignField: "name",

as: "class_info"

}

}

])

其中,$lookup操作符将学生集合与班级集合进行关联,通过localField和foreignField指定关联的字段,as用来指定关联之后的输出结果。执行完成后,将返回下面的结果:

{

"_id": ObjectId("5e3f7e72c287e604696a0e96"),

"name": "张三",

"age": 18,

"class": "1班",

"grade": {

"math": 90,

"english": 80,

"chinese": 85

},

"class_info": [

{

"_id": ObjectId("5e3f7e72c287e604696a0e97"),

"name": "1班",

"teacher": "李老师"

}

]

}

2.2. 引用方式

除了嵌套数据结构,MongoDB还支持引用方式进行多张表的关联操作。在引用方式中,通过在一个集合中添加另一个集合文档的id字段,实现两张表之间的关联。例如:

// 学生集合

{

"_id": ObjectId("5e3f7e72c287e604696a0e96"),

"name": "张三",

"age": 18,

"class_id": ObjectId("5e3f7e72c287e604696a0e97"),

"grade": {

"math": 90,

"english": 80,

"chinese": 85

}

}

// 班级集合

{

"_id": ObjectId("5e3f7e72c287e604696a0e97"),

"name": "1班",

"teacher": "李老师"

}

在上述代码中,学生集合中的class_id属性和班级集合中的_id属性可以建立起联系,达到关联查询的目的。在查询时,可以使用$lookup操作符完成两张表之间的关联操作,示例如下:

db.students.aggregate([

{

$lookup: {

from: "classes",

localField: "class_id",

foreignField: "_id",

as: "class_info"

}

}

])

其中,$lookup操作符将学生集合与班级集合进行关联,通过localField和foreignField指定关联的字段,as用来指定关联之后的输出结果。执行完成后,将返回下面的结果:

{

"_id": ObjectId("5e3f7e72c287e604696a0e96"),

"name": "张三",

"age": 18,

"class_id": ObjectId("5e3f7e72c287e604696a0e97"),

"grade": {

"math": 90,

"english": 80,

"chinese": 85

},

"class_info": [

{

"_id": ObjectId("5e3f7e72c287e604696a0e97"),

"name": "1班",

"teacher": "李老师"

}

]

}

3. 同库联表查询方法示例

在MongoDB中,同库联表查询可以通过$lookup操作符和嵌套数据结构的方式来实现。下面是使用嵌套数据结构方式进行同库联表查询的示例:

// 创建订单集合

db.createCollection("orders")

// 向订单集合中插入数据

db.orders.insert([

{

"_id": ObjectId("5e3f7e72c287e604696a0e98"),

"product": "牛仔裤",

"price": 200.0,

"quantity": 2,

"customer": {

"name": "张三",

"address": "北京市朝阳区"

}

},

{

"_id": ObjectId("5e3f7e72c287e604696a0e99"),

"product": "衬衫",

"price": 100.0,

"quantity": 1,

"customer": {

"name": "李四",

"address": "上海市浦东新区"

}

}

])

// 查询订单集合并关联顾客集合

db.orders.aggregate([

{

$lookup: {

from: "orders",

localField: "customer",

foreignField: "_id",

as: "customer_info"

}

}

])

上述代码中,插入了两条订单数据,每条订单都包含一个顾客对象。在执行查询时,$lookup操作符将订单集合与顾客集合进行关联,通过localField和foreignField指定关联的字段,as用来指定关联之后的输出结果。执行完成后,将返回下面的结果:

{

"_id": ObjectId("5e3f7e72c287e604696a0e98"),

"product": "牛仔裤",

"price": 200.0,

"quantity": 2,

"customer": {

"name": "张三",

"address": "北京市朝阳区"

},

"customer_info": []

},

{

"_id": ObjectId("5e3f7e72c287e604696a0e99"),

"product": "衬衫",

"price": 100.0,

"quantity": 1,

"customer": {

"name": "李四",

"address": "上海市浦东新区"

},

"customer_info": []

}

由于顾客集合并不存在,因此返回的结果中,customer_info数组为空。

3.1. $unwind操作符

在上面的示例中,如果将顾客对象改成数组格式,结果如下:

db.orders.insert([

{

"_id": ObjectId("5e3f7e72c287e604696a0e98"),

"product": "牛仔裤",

"price": 200.0,

"quantity": 2,

"customer": [

{

"name": "张三",

"address": "北京市朝阳区"

}

]

},

{

"_id": ObjectId("5e3f7e72c287e604696a0e99"),

"product": "衬衫",

"price": 100.0,

"quantity": 1,

"customer": [

{

"name": "李四",

"address": "上海市浦东新区"

}

]

}

])

执行同样的查询操作,结果如下:

{

"_id": ObjectId("5e3f7e72c287e604696a0e98"),

"product": "牛仔裤",

"price": 200.0,

"quantity": 2,

"customer": [

{

"name": "张三",

"address": "北京市朝阳区"

}

]

},

{

"_id": ObjectId("5e3f7e72c287e604696a0e99"),

"product": "衬衫",

"price": 100.0,

"quantity": 1,

"customer": [

{

"name": "李四",

"address": "上海市浦东新区"

}

]

}

可以看到,查询结果并没有关联顾客信息。这是因为如果字段值为数组,则需要使用$unwind操作符将数组拆分。例如:

db.orders.aggregate([

{ $unwind: "$customer" },

{

$lookup: {

from: "orders",

localField: "customer",

foreignField: "_id",

as: "customer_info"

}

}

])

执行上述操作后,将返回如下结果:

{

"_id": ObjectId("5e3f7e72c287e604696a0e98"),

"product": "牛仔裤",

"price": 200.0,

"quantity": 2,

"customer": {

"name": "张三",

"address": "北京市朝阳区"

},

"customer_info": []

},

{

"_id": ObjectId("5e3f7e72c287e604696a0e99"),

"product": "衬衫",

"price": 100.0,

"quantity": 1,

"customer": {

"name": "李四",

"address": "上海市浦东新区"

},

"customer_info": []

}

$unwind操作符将顾客对象拆分成单独的文档,然后关联订单集合得到最终的查询结果。

4. 总结

在MongoDB中,联表查询有嵌套数据结构和引用方式两种方式。如果需要关联的字段为对象,则可以使用嵌套数据结构方式;如果需要关联的字段为数组,则需要使用$unwind操作符拆分成单独的文档,然后再使用嵌套数据结构方式关联查询。$lookup操作符是MongoDB中关联查询操作的关键操作符,通过它可以实现对多张表的关联查询操作。

数据库标签