当前位置:网站首页>使用Mongoose populate实现多表关联存储与查询,内附完整代码
使用Mongoose populate实现多表关联存储与查询,内附完整代码
2022-08-08 23:03:00 【@魏大大】
文章目录
使用Mongoose populate实现多表关联与查询
mongodb
不是传统的关系型数据库,我们可以使用monogoose
方便的将多个表关联起来,实现一对多、多对多的数据表存储和查询功能。
本文已最常见的一对多关系模型,介绍简单的数据模型定义、存储、查询。
一、 数据模型创建
我们创建一个Person
模型和一个Story
模型,其中一个Person
对应多个Story
,也就是典型的一对多关系。
1. 创建一个PersonSchema
创建PersonSchema
时,不需要为其指定_id
属性,因为数据库会自动为其添加主键属性。
由于一个Person
对象可以拥有多个Story
对象,所以需要添加一个stories
数组属性,存储与其关联的Story
。
具体代码如下:
const PersonSchema = new Schema({
// _id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{
type: Schema.Types.ObjectId, ref: 'Story' }]
})
问题解答
其中的Schema.Types.ObjectId
是一种内置的特殊类型,专门用来表示对象的ID
官方解读:An ObjectId is a special type typically used for unique identifiers.
2. 创建一个StorySchema
每个Story
都有一个唯一的author
,也就是一个Person
对象。和普通的属性不同的是,我们需要指定引用属性的类型和引用的模型名称。同样的,每个Story
对象还可以拥有多个fans
,同样是Person
对象。这里实际上有一个循环的引用。
如果学习过关系型数据库的同学,可能对这里非常容易了解。
const StorySchema = new Schema({
author: {
type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{
type: Schema.Types.ObjectId, ref: 'Person' }]
})
3. 使用Schema创建对应的model
创建模型需要使用mongoose.model
方法,该方法可以接收三个参数,其中:
- 第一个参数指模型的名称
- 第二个参数指使用的Schema
- 第三个参数指对应的mongodb数据表(集合)
以下代码分别使用StorySchema
和PersonSchema
创建了一个Story
模型和一个Person
模型
const Story = mongoose.model('Story', StorySchema, 'tb_story')
const Person = mongoose.model('Person', PersonSchema, 'tb_person')
二、数据存储
使用mongoose
可以非常简单的使用面向对象的方式完成数据的存取。
1. 创建模型实例
创建一个名为xiaoming
的Person
对象,然后再创建一个Story
,并使其引用Person._id
属性。
let p1 = new Person({
name: 'xiaoming',
age: 12
})
let s1 = new Story({
title: 'The life of snow white and the dwarfs',
author: p1._id
})
s1.fans.push(p1.id)
问题解读
这里有一个不符合常理的地方,就是我在这里把故事的作者设为了故事的粉丝~~
2. 存储模型数据
使用模型的.save()
方法存储对象的数据到数据库中。
p1.save().then(person => {
console.log('Pserson save success.\n', person)
s1.save().then(story => {
console.log('Story save success.\n', story)
})
})
代码指向结果如下:
Pserson save success.
{
name: 'xiaoming',
age: 12,
stories: [],
_id: new ObjectId("62ef6fb11c8795f4e1327adb"), //注意,这里对应了下面的Story.author
__v: 0
}
Story save success.
{
author: new ObjectId("62ef6fb11c8795f4e1327adb"), //注意,这里对应了上面的Person._id
title: 'The life of snow white and the dwarfs',
fans: [ new ObjectId("62ef6fb11c8795f4e1327adb") ],
_id: new ObjectId("62ef6fb11c8795f4e1327adc"),
__v: 0
}
这样数据存储工作就完成了。
三、数据关联查询
- 使用故事的标题,查询故事作者的名称
Story.findOne({
title: 'The life of snow white and the dwarfs' })
.populate('author').then(story => {
console.log(story.author.name)
})
执行结果会输出:xiaoming
2. 使用故事标题,查询粉丝信息
Story.findOne({
title: 'The life of snow white and the dwarfs' })
.populate('fans').then(story => {
console.log(story.fans)
})
代码执行结果:
[
{
name: 'xiaoming',
age: 12,
stories: [],
_id: new ObjectId("62ef781a8123a8ec47f40736"),
__v: 0
}
]
四、完整代码
const mongoose = require('mongoose')
const Schema = mongoose.Schema
mongoose.connect('mongodb://ahohAdmin:[email protected]:27017/db_ahoh')
.then('database connected')
.catch(err => console.log(err))
const PersonSchema = new Schema({
// _id: Schema.Types.ObjectId,
name: String,
age: Number,
stories: [{
type: Schema.Types.ObjectId, ref: 'Story' }]
})
const StorySchema = new Schema({
author: {
type: Schema.Types.ObjectId, ref: 'Person' },
title: String,
fans: [{
type: Schema.Types.ObjectId, ref: 'Person' }]
})
const Story = mongoose.model('Story', StorySchema, 'tb_story')
const Person = mongoose.model('Person', PersonSchema, 'tb_person')
let p1 = new Person({
name: 'xiaoming',
age: 12
})
let s1 = new Story({
title: 'The life of snow white and the dwarfs',
author: p1._id
})
s1.fans.push(p1.id)
p1.save().then(person => {
console.log('Pserson save success.\n', person)
s1.save().then(story => {
console.log('Story save success.\n', story)
})
})
Story.findOne({
title: 'The life of snow white and the dwarfs' })
.populate('author').then(story => {
console.log(story.author.name)
})
Story.findOne({
title: 'The life of snow white and the dwarfs' }).populate('fans').then(story => {
console.log(story.fans)
})
边栏推荐
- MPLS Virtual Private Network Everywhere in Life
- thinkphp5 if else的表达式怎么写?
- laravel6框架跨域请求利器之 Laravel CORS 扩展包的安装和使用
- Unity ScrollView无限循环左右滑动翻页带阻尼效果
- Taro小程序跨端开发入门实战
- 4399 it operations intern interview experience
- 三国战绩物品序号.txt
- 按键精灵 for ts API 使用
- Virtual router redundancy protocol VRRP - double-machine hot backup
- 生活中无处不在的MPLS虚拟专用网
猜你喜欢
随机推荐
C language library function summary2019.10.31
【CUDA】版本自由切换
加载 已训练模型 张量的 几种方法
机器学习之知识点(一)
DHCP's defense mechanism - DHCP Snooping (DHCP snooping)
Unity Text三重渐变色
Firewall first contact
Mysql8.0.21 Community Server远程连接报错
The concept of GIL and pools
ArcPy elements batch to dwg
CTF Attack and Defense World
用工具实现 Mock API 的整个流程
按键精灵 for ts API 使用
Unity Text自定义多重渐变色且渐变色位置可调
想要精准营销,从学习搭建一套对的标签体系开始丨DTVision分析洞察篇
Button Wizard Delete File Command
windows10安装vagrant+VirtualBox搭建PHP开发环境
Kubernetes 资源编排系列之二: Helm 篇
IMConversation 或 IMUser 类型数据
三国战绩 风云再起 网络版 物品序号 和 基址列表