Skip to content

数据模型

MongoDB对于文档的格式并没有强制性的要求, 但不等于我们不能在文档中表达数据的关系 在MongoDB中我们可以通过'内嵌式结构'和'规范式结构'来表达文档之间的关系

内嵌式结构

在文档中又包含一个文档,我们就称之为内嵌式的结构

{
    name:'zs',
    age:'18',
    card:{
        num:'420626200002023556',
        date: 88
    }
}

一对一

一个人有一张身份证

1.1内嵌式结构

db.person.insert({
    name:'zs',
    age:'18',
    card:{
        num:'420626200002023556',
        date: 88
    }
})
db.person.find({name:'zs'})
  • 优势: 一次查询就能得到所有数据
  • 劣势: 如果数据比较复杂, 不方便管理和更新
  • 应用场景: 数据不复杂/查询频率较高数据

一对多

一个人有多本书

db.person.insert({
    name:'zs',
    age:'18',
    books:[{
        name:'玩转HTML',
        price: 88
    },
    {
        name:'玩转CSS',
        price: 88
    }]
})
db.person.find({name:'zs'})
  • 优势: 一次查询就能得到所有数据
  • 劣势: 冗余数据较多, 不方便管理和更新
  • 应用场景: 数据不复杂/查询频率较高数据

多对多

一个学生有多个老师, 一个老师有多个学生

db.students.insert([{name:'zs', teachers:[{name:'it666'}, {name:'itzb'}]},
{name:'ls', teachers:[{name:'it666'}, {name:'itzb'}]}])

db.teachers.insert([{name:'it666', students:[{name:'zs'}, {name:'ls'}]},
{name:'itzb', students:[{name:'zs'}, {name:'ls'}]}])
db.students.find({name:'zs'})
db.teachers.find({name:'itzb'})
  • 优势: 一次查询就能得到所有数据
  • 劣势: 冗余数据较多, 更新和管理较为复杂
  • 应用场景: 数据比较简单/查询频率较高数据

规范是结构

将文档存储在不同的集合中, 然后通过某一个字段来建立文档之间的关系, 我们就称之为规范式

{
    _id: 1,
    num:'420626200002023556',
    date: 88
}
{
    name:'zs',
    age:'18',
    cardId: 1
}

一对一

一个人有一张身份证

db.card.insert({
    _id: 123,
    num:'420626200002023556',
    date: '2022-12-08',
    userId: 456
})
db.person.insert({
    _id: 456,
    name:'zs',
    age:'18',
    cardId: 123
})
## 聚合查询
db.person.aggregate([
    {$lookup:{
        from: 'card',
        localField: 'cardId',
        foreignField: '_id',
        as: 'card'
    }}
])
  • 优势: 如果数据比较复杂, 也方便管理和更新
  • 劣势: 查询数据相对内嵌结果稍微有点复杂
  • 应用场景: 数据比较复杂/更新频率较高数据

一对多

一个人有多本书

db.books.insert([{
    _id: 1,
    name:'玩转HTML',
    price: 88,
    userId:123
},
{
    _id: 2,
    name:'玩转CSS',
    price: 88,
    userId:123
}])
db.person.insert({
    _id: 123,
    name:'ls',
    age:'20',
    booksId:[1, 2]
})
## 聚合查询
db.person.aggregate([
    {$lookup:{
        from: 'books',
        localField: 'booksId',
        foreignField: '_id',
        as: 'books'
    }}
])
  • 优势: 冗余数据较少, 更新较为方便
  • 劣势: 查询数据相对内嵌结果稍微有点复杂
  • 应用场景: 数据比较复杂/更新频率较高数据

多对多

一个学生有多个老师, 一个老师有多个学生

db.students.insert([{_id:1, name:'zs'},{_id:2, name:'ls'}])
db.teachers.insert([{_id:3, name:'it6666'},{_id:4, name:'itzb'}])
db.relation.insert([{stuId:1, teacherId:3},{stuId:1, teacherId:4},{stuId:2, teacherId:3},{stuId:2, teacherId:4}])
## 聚合操作
db.students.aggregate([
    {$lookup:{
        from: 'relation',
        localField: '_id',
        foreignField:'stuId',
        as: 'relation'
    }},
    {$lookup:{
        from: 'teachers',
        localField: 'relation.teacherId',
        foreignField:'_id',
        as: 'teachers'
    }},
    {$project:{_id:0, name:1, teachers:1}}
])
  • 优势: 冗余数据较少, 更新较为方便
  • 劣势: 查询数据相对内嵌结果稍微有点复杂
  • 应用场景: 数据比较复杂/更新频率较高数据

树形结构

在MongoDB中我们除了可以使用'内嵌式结构'和'规范式结构'来表示数据的关系以外

由于MongoDB数据的灵活性, 我们还可以使用'树形结构'来表示数据之间的关系

什么是树形结构


            Database
               |
     |--------------------|
 Relational           No-Relational
     |          |-----------|-------------|
   MySQL      Key-Value                Document
                |                         |
              Redis                    MongoDB

对于经常需要查询子节点的数据

{name:'Database', parent:null}
{name:'No-Relational', parent:'Database'}
{name:'Document', parent:'No-Relational'}
{name:'MongoDB', parent:'Document'}
{name:'Key-Value', parent:'No-Relational'}
{name:'Redis', parent:'Key-Value'}

例如:我们要查询非关系型数据库有几种类型, 我们可以使用find({parent:'No-Relational'})

对于经常需要查询父节点的数据

{name:'Database', children:['Relational', 'No-Relational']}
{name:'No-Relational', children:['Key-Value', 'Document']}
{name:'Document', children:['MongoDB']}
{name:'MongoDB', children:[]}

例如:我们要查询MongoDB是什么类型的的数据, 我们可以使用find({children:{$in:['MongoDB']}})

对于经常查询祖先或者后代节点的数据

{name:'Database', ancestors:[]}
{name:'No-Relational', ancestors:['Database']}
{name:'Document', ancestors:['Database', 'No-Relational']}
{name:'MongoDB', ancestors:['Database', 'No-Relational', 'Document']}

例如: 我们要查询MongoDB的祖先有哪些, 我们可以使用find({name:'MongoDB'})

例如: 我们要查询Database的后代有哪些, 我们可以使用find({ancestors:{$in:['Database']}}})

Released under the MIT License.