1.生成自己的主键
在项目中,最好不要把"_id"当做业务主键,也不要依赖它作为插入时间排序的依据。
MongoDB在文档插入时,客户端默认会生成一个主键"_id",这个键的值可以是任何类型的,默认是个ObjectId对象,该对象前4个字节表示时间戳,这个时间戳是在mongo-driver生成的,并不是服务端的时间。
在一个集合里面,每个文档都有唯一的"_id"值,来确保集合里面每个文档都能被唯一标识。但在不同的文档中"_id"的值可以相同。可以看见下图中两个集合中的记录拥有相同的"_id"。一般情况下,我们都希望我们的业务主键是全局唯一的。
基于以上原因,个人"_id"在项目中使用意义不大,因此在查询文档时,可以不返回这个字段。
db.collection.find( <query filter>, {"_id":1} )
2.合理的schema设计
MongoDB是schema free的数据库,没有模式并不意味着我们就可以随意将数据进行插入。为了保证数据的可读、可维护性,我们应该重视MongoDB的schema设计。schema free只是增强应用应变能力的一种可用手段,绝不是银弹。
一对多的关系,通过内嵌文档来表示时,要注意限制内嵌文档的个数。一是因为Mongo对于单个文档的大小有限制,二是便于查询。比如在文章的评论,可以将精选的热门评论内嵌置文章中。MongoDB推荐的schema设计
3.不做Model映射
MongoDB的文档的存储形式是BSON,即Binary JSON。项目中前端和后端的数据交互也都是采用json的格式。在后端java程序中,我们并没有按照以往的做法将schema映射成java bean。我认为这样做损失了MongoDB schema free的灵活性。当我们的需求发生变动,需要修改或者增加字段时,只需要在前端做出字段的修改,然后以json的形式发送给后端,后端直接将json存入mongo集合即可,不用再去考虑修改哪个model/entity。
4.完备的文档检查
由于是直接操作前端传回的json,无论从程序还是业务面考虑,我们都应该对json文档进行校验。常规的校验包括必须字段是否存在,字段的值类型是否正确。尤其是字段的值类型校验一定要谨慎,很有可能之前定义的值类型为int,然后传回的是string并且"成功的"写入了数据集合中,下次程序中对这个字段进行求和或者大小比较等操作时,一不小心就会抛出类型错误。
MongoDB在3.2版本之后,对insert和update提供了Document validation。能够限制字段的值类型,值范围,设置string类型字段的正则匹配规则。