什么“坑”?
使用MongoTemplate对文档进行增改操作时,稍不注意就会造成数据丢失,究其原因在于对增改操作理解不到位,特定场景下没有理解save操作含义。
场景
假设文档共有10个字段,保存文档时保存10个字段,更新文档时只更新1个字段。
“坑”操作
程序只提供一个增改接口,而保存和更新文档却直接使用了save方法。
分析
save方法本身的含义是当数据中不存在_id字段时,直接插入,并且会自动生成_id;当数据中存在_id字段时,先根据_id查询是否存在文档,存在则进行文档替换,不存在则以数据中的_id为主键插入。所以若只有save操作,那么保存后进行更新的过程中,由于只更新1个字段,又含有_id字段,那么实际上会进行文档替换,进而导致数据丢失现象。
怎么办?
若更新时能保证字段最全(比文档中字段只多不少),那么可以直接使用save方法;若不能保证,可以使用两种方式,一是保存前先根据_id查询文档,若查询响应值非空则使用更新的数据覆盖响应值数据,再进行保存,这样就避免了数据丢失;二是使用upsert进行插入和更新,upsert含义是根据查询条件有就更新,没有就插入,本质上和第一种方式并无不同,只是不需要自己显式查询了。
然而,批量数据操作就存在问题了,若mongo集合已存储的数据量很大且查询条件恰好没有索引,那么查询会慢到你怀疑人生,此时上述两种方式都不可取。怎么解决呢?可以使用批量操作BulkOperations,事先定义好要进行的操作,然后调用execute()方法批量执行即可。