近期对两个应用进行改造,在上线过程中出现一系列问题(其中一部分是由于ObjectId误区导致的)
Query query = new Query(); if (id != null) { query.addCriteria(Criteria.where("_id").gt(id)); } query.with(new Sort(Sort.Direction.ASC, "_id"));
Comparator<DBObject> comparator = new Comparator<DBObject>() { @Override public int compare(DBObject o1, DBObject o2) { return ((ObjectId)o1.get("_id")).compareTo((ObjectId)o2.get("_id")); } }; PriorityQueue<DBObject> queue = new PriorityQueue<DBObject>(200,comparator);
public WriteResult insert(List<DBObject> list, com.mongodb.WriteConcern concern, DBEncoder encoder ){ if (concern == null) { throw new IllegalArgumentException("Write concern can not be null"); } return insert(list, true, concern, encoder); }
protected WriteResult insert(List<DBObject> list, boolean shouldApply , com.mongodb.WriteConcern concern, DBEncoder encoder ){ if (encoder == null) encoder = DefaultDBEncoder.FACTORY.create(); if ( willTrace() ) { for (DBObject o : list) { trace( "save: " + _fullNameSpace + " " + JSON.serialize( o ) ); } } if ( shouldApply ){ for (DBObject o : list) { apply(o); _checkObject(o, false, false); Object id = o.get("_id"); if (id instanceof ObjectId) { ((ObjectId) id).notNew(); } } } WriteResult last = null; int cur = 0; int maxsize = _mongo.getMaxBsonObjectSize(); while ( cur < list.size() ) { OutMessage om = OutMessage.insert( this , encoder, concern ); for ( ; cur < list.size(); cur++ ){ DBObject o = list.get(cur); om.putObject( o ); // limit for batch insert is 4 x maxbson on server, use 2 x to be safe if ( om.size() > 2 * maxsize ){ cur++; break; } } last = _connector.say( _db , om , concern ); } return last; }自动添加ObjectId的操作
/** * calls {@link DBCollection#apply(com.mongodb.DBObject, boolean)} with ensureID=true * @param o <code>DBObject</code> to which to add fields * @return the modified parameter object */ public Object apply( DBObject o ){ return apply( o , true ); } /** * calls {@link DBCollection#doapply(com.mongodb.DBObject)}, optionally adding an automatic _id field * @param jo object to add fields to * @param ensureID whether to add an <code>_id</code> field * @return the modified object <code>o</code> */ public Object apply( DBObject jo , boolean ensureID ){ Object id = jo.get( "_id" ); if ( ensureID && id == null ){ id = ObjectId.get(); jo.put( "_id" , id ); } doapply( jo ); return id; }可以看到,mongoDB的驱动包中是会自动添加ObjectId的。
public WriteResult save( DBObject jo, WriteConcern concern ){ if ( checkReadOnly( true ) ) return null; _checkObject( jo , false , false ); Object id = jo.get( "_id" ); if ( id == null || ( id instanceof ObjectId && ((ObjectId)id).isNew() ) ){ if ( id != null && id instanceof ObjectId ) ((ObjectId)id).notNew(); if ( concern == null ) return insert( jo ); else return insert( jo, concern ); } DBObject q = new BasicDBObject(); q.put( "_id" , id ); if ( concern == null ) return update( q , jo , true , false ); else return update( q , jo , true , false , concern ); }
DBObject update = new BasicDBObject("$inc", new BasicDBObject("counter", 1)); DBObject query = new BasicDBObject("_id", key); DBObject result = getMongoTemplate().getCollection(collectionName).findAndModify(query, update); if (result == null) { DBObject doc = new BasicDBObject(); doc.put("counter", 1L); doc.put("_id", key); // insert(collectionName, doc); getMongoTemplate().save(doc, collectionName); return 1L; } return (Long) result.get("counter");