MongoDB关联关系

MongoDB关联关系

[toc]

一对一

在设计的时候,应该优先考试内嵌方式,如果内嵌方式满足不了,再使用引用方式,主要原因有:

  • 内嵌方式性能最高,但大小最大为16MB

而引用方式也就意味着把数据分别存在两个集合当,而Mongodb是不支持事务的,所以,在一些强事务场景是不适合的

方式一:内嵌

插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

db.users.insert(
{
name:'lvxx',
age:31,
address:{
info:'SongJiang,ShangHai City',
used:1
},
});

db.users.insert({
name:'maschen',
age:31,
address:{
info:'XiaSha,HangZhou City',
used:1
},
});

查询

1
2
3
4
# 查询 
db.users.find({
'address.used':1
});

更新

1
2
3
4
5
6
7
8
9
10
11

# 更新
db.users.update(
{
'name':'lvxx'
},
{
#更新的时候结构要写全,否则结构会乱掉
$set:{address:{'info':'SongJiang,ShangHai City','used':0}}
},
);

删除子文档里的某个字段

1
2
3
4
5
6
7
8
9
10

# 删除子文档里的某个字段
db.users.update(
{
'name':'lvxx'
},
{
$unset:{"address.used":""} //$unset
},
);

删除整个子文档

1
2
3
4
5
6
7
8
9
# 删除整个子文档
db.users.update(
{
'name':'lvxx'
},
{
$unset:{address:{}}
},
);

方式二:引用

插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
db.users.insertMany([ //是数组
{
name:'lvxx',
age:31,
},
{
name:'maschen',
age:31,
}
]);

db.address.insertMany([{
name:'ShangHai',
code:1000,
},
{
name:'HangZhou',
code:1001,
}]);

更新

1
2
3
4
5
6
7
8
9
#更新
db.users.update({
'name':'lvxx'
},{
$set:{address:ObjectId('5bfb936de983c23ee94af93d')}
});

# 查询略,和普通查询无区别,和mysql不同,是不能联表查询,
所以只能分两次查询,拿到address object id ,然后再address里进行查询

一对多

内嵌

插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 插入数据
db.users.insertMany([
{
name:'lvxx',
age:31,
address:[
{
info:'SongJiang,ShangHai City',
used:1
},
{
info:'XuHui,ShangHai City',
used:0
}
],
},
{
name:'maschen',
age:31,
address:[
{
info:'XiaSha,HangZhou City',
used:1
}
],
}
]);

查询

1
2
3
4
5

# 查询
db.users.find({
'address.used':0
});

添加子文档

1
2
3
4
5
6
7
8
9
10
11
#添加子文档
db.users.update({
'name':'maschen'
},{
$push:{ //添加子项用 $push
address:{
'info':'WenZhou,ZheJiang',
'used':0
}
}
});

更新子文档中的某一个字段

1
2
3
4
5
6
7
8
9
10
#更新子文档中的某一个字段

db.users.update({
'name':'maschen'
'address.used':1 //条件必须,#需注意这里如果匹配到两条,则只更新一条,子文档无法批量更新,需要批量更新,则需要循环处理
},
{
$set:{"address.$.used":0}
},false,true
);

更新子文档且子文档是多个条件

1
2
3
4
5
6
7
8
9
10
# 更新子文档且子文档是多个条件

db.users.update({
'name':'maschen',
address:{$elemMatch:{used:1,info:'xxx'}}
},
{
$set:{"address.$.used":0}
}
);

移除操作

移除数组中的第一个或者最后一个元素(1为最后一个元素,-1为第一个元素)

1
2
3
4
5
6
7
8
# 移除操作
db.users.update({
'name':'maschen'
},
{
$pop:{address:1}
}
);

引用

初始化数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
db.users.insertMany([
{
name:'lvxx',
age:30,
address:[]
},{
name:'maschen',
age:28,
address:[]
}
]);


db.address.insertMany([
{
info:'ShangHai',
code:30
},{
name:'HangZhou',
code:28
},{
info:'WenZhou',
code:17
}
]);

设置对应关系

1
2
3
4
5
6
7
8
db.users.update({
'name':'lvxx'
},{
$set:{address:[
ObjectId('5bfbad4ae983c24f3471d7c7'),
ObjectId('5bfbad4ae983c24f3471d7c9'),
]}
});

追加

1
2
3
4
5
db.users.update({
'name':'lvxx'
},{
$push:{address:ObjectId('5bfbad4ae983c24f3471d7c8')}
});

删除

1
2
3
4
5
6
7
8
9
10
11
12
db.users.update({
'name':'lvxx'
},{
$pop:{address:-1}
});

# 删除指定元素
db.users.update({
'name':'lvxx'
},{
$pull:{address:ObjectId('5bfbad4ae983c24f3471d7c8')}
});

查询

1
2
3
db.users.find({
address:{$in:[ObjectId('5bfbad4ae983c24f3471d7c7')]}
});

多对多

初始化数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
db.users.insertMany([
{
name:'lvxx',
age:30,
roles:[]
},{
name:'maschen',
age:28,
roles:[]
}
]);


db.roles.insertMany([
{
name:'超级管理员',
users:[]
},{
name:'普通管理员',
users:[]
}
]);

设置数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
db.users.update({
'name':'lvxx'
},{
$set:{roles:[
ObjectId('5bfbb7e9e983c24f3471d7ce'),
ObjectId('5bfbb7e9e983c24f3471d7cf'),
]}
});

db.roles.update({
'name':'超级管理员'
},{
$set:{users:[
ObjectId('5bfbb7c0e983c24f3471d7cc'),
ObjectId('5bfbb7c0e983c24f3471d7cd'),
]}
});

查询和更新及删除请参考前面的一对多(略)

关于mysql迁移至MongoDB

如果是单表的话,不牵涉一些关联关系,可以使用一些mysql工具,比如phpMyAdmin,Navicat for mysql 等工具导出excel 或者是csv,然后再使用 Navicat for MongoDB 或者mongodb的命令,可以进行直接导入。
如果有关联关系的,还是需要借助脚本来进行处理