MongoDB最佳实践
实践中的问题
- Mongodb并没有Schema的概念,所以一个字段可以随意更改类型.只能通过Schema Validation来做验证,但Schema Validation很麻烦.
- 数据中不存在的字段的默认值用null或者干脆不写(not exist)?
- 利用mongoexport产生的dump文件以csv格式保存,重新import回去date类型字段都会变成string.
- 时间类型字段到底用什么存?用String存难以做数据处理,用ISODate存经常有人误把String写入.
脏数据产生可能
- 直接操作数据库产生, 除非有Schema Validation.
- dumpfile导出csv格式文件,重新导入就可能产生.
- 利用pymongo等简单框架产生.
- mongoengine等ORM框架产生.
最佳实践
- 数据类型只用int,decimal,string,boolean,date. 不用timestamp和其他类型.
- 统一用Mongoengine做数据库操作,不直接操作数据库或者用Pymongo操作数据库.
- 靠MongoEngine的Model层来做验证, 不使用Schema Validation来做验证.
- 不存在的字段不写,时间类型字段必须用ISODate存,python下是datetime格式,和Mongoengine的行为一致.
- dump文件统一格式为JSON, 如果试图通过dump文件导入数据,对于时间格式必须按照
"date": {"$date": "2020-05-03T09:33:31.332Z"}
书写,并注意检查字段类型是否一致.
- 常规mongo插入数据,无法校验类型,导致存入的数据和预期的数据类型有差异,且容易忽略此类问题(比如date类型)
- dumpfile可能产生脏数据
- 插入重复的字段,产生多余脏数据
- 插入多余字段
行为测试
- 读取一个类型不一致的脏数据.如尝试以int类型方式读取一个数据.
- 给字段类型不匹配的数据.如给一个int字段一个字符串
- 给字段一个空字符串或者NULL.
- 给模型插入多余的字段.
Git仓库地址
git@gitlab.tasitech.com.cn:luxin/mongo-test.git
MongoEngine的行为
MongoDB分动态文档(Dynamic Document)跟静态文档(document)
静态文档
字段必须严格对应模型,否则连接后就会报错.(未测试有多余字段的数据是否会报错.)
1的行为是: 只有int和decimal数据可以自动转换,对于不可转换的数据,会原样读出数据的格式.比如尝试用date读取一个string值,会直接读出一个string.
2的行为是: 保存的时候数据不匹配数据直接报错.
3的行为是: 给非字符串类型赋值空字符串报错,给null值不会报错.但不会写入到数据库.
4的行为是: 可以给对象赋值, 但实际不会插入多余字段.
动态文档
1的行为和静态文档一直, 234的行为都不会报错并且插入数据库.
PyMongo的行为
没有模型的概念,所以所有的操作都是被允许的,和直接操作数据库行为类似.1234均不会报错并且可以执行.
Dumpfile的行为
没有行为1的测试,234操作都被允许,存入的类型以值的类型为准.并且如果不按照"date": {"$date": "2020-05-03T09:33:31.332Z"}
,无法存入Date类型,会被识别成String类型.
相关思考
- csv文件导入,必须要用程序处理.可以考虑写程序.
- 模型库包非常有意义,可以避免脏数据的产生
参考文献
https://www.infoq.com/articles/Starting-With-MongoDB/
https://jsongrid.com/json-grid
https://www.mongodb.com/blog/post/performance-best-practices-mongodb-data-modeling-and-memory-sizing
https://www.compose.com/articles/mongodb-with-and-without-schemas/
https://docs.mongodb.com/manual/core/schema-validation/