基本概念

  • 文档:mongo存储的数据本质上就是类似JSON格式的字符串,叫document。每个文档都有一个_id字段,也叫主键ID,和MySQL的主键一个意思。
  • 集合:一个文档,类似于mysql的一行数据。当很多个document组合在一起就是集合(collection),MySQL这边叫做表。

使用场景:

  • 嵌套关系多的情况,这种在MySQL里面就是一对多,需要几张表。但是mysql一个集合就完事儿了。

存储

mongo的存储本质上就是在JSON的基础上做Base64编码存储,叫BSON编码。这些BSON文档会组成为一个集合存储在磁盘上,后缀名是wt。

wt文件里面也有分页,为了加快读取。其实和mysql的分页很相似,索引也是使用的B+Tree的变种索引,需要注意的是:

  • mysql的B+Tree写入数据的时候,会有行锁;
  • 但是mongo采用的是copy on write,就是复制一页出来改,不影响读。这个分页其实就是变种索引的“变”。

还有缓存相关的东西,可以提高热点数据的访问速度。
还有类似mysql的Binlog的日志叫,写前日志 Journal。用于保护缓存中数据丢失的。
Checkpoint、WiredTiger、Server 层架构、oplog这些以后在了解

增删改查

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
@SpringBootApplication
public class MongoTemplateDemoApplication implements CommandLineRunner {

@Autowired
private MongoTemplate mongoTemplate;

public static void main(String[] args) {
SpringApplication.run(MongoTemplateDemoApplication.class, args);
}

@Override
public void run(String... args) {

// ========== 1. 增 ==========
User user = new User("张三", 20, "北京");
mongoTemplate.insert(user);
System.out.println("插入成功,id = " + user.getId());

// 批量插入
User li = new User("李四", 30, "上海");
User wang = new User("王五", 17, "广州");
mongoTemplate.insert(List.of(li, wang), User.class);

// ========== 2. 查 ==========
// 根据 id 查
User byId = mongoTemplate.findById(user.getId(), User.class);
System.out.println("findById: " + byId);

// 条件查多条:age > 18
Query query = Query.query(Criteria.where("age").gt(18));
List<User> adultList = mongoTemplate.find(query, User.class);
System.out.println("age > 18: " + adultList);

// 查一条
User one = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("张三")),
User.class
);
System.out.println("findOne: " + one);

// ========== 3. 改 ==========
// 修改一条:city 改为深圳,age + 1
Update update = new Update()
.set("city", "深圳")
.inc("age", 1);

mongoTemplate.updateFirst(
Query.query(Criteria.where("name").is("张三")),
update,
User.class
);

// 批量修改:age >= 18 的全部 age + 1
mongoTemplate.updateMulti(
Query.query(Criteria.where("age").gte(18)),
new Update().inc("age", 1),
User.class
);

// ========== 4. 删 ==========
// 删一条
mongoTemplate.remove(
Query.query(Criteria.where("name").is("张三")),
User.class
);

// 删多条:age < 18
mongoTemplate.remove(
Query.query(Criteria.where("age").lt(18)),
User.class
);

// 统计剩余数量
long count = mongoTemplate.count(new Query(), User.class);
System.out.println("剩余文档数: " + count);
}
}

参考

小白debug