Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@magro
Created March 10, 2011 22:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magro/865065 to your computer and use it in GitHub Desktop.
Save magro/865065 to your computer and use it in GitHub Desktop.
MongoDB hello: Shows how to update a field with the value of another field by using either eval (nolock, for mongodb >= 1.8) or map/reduce (mongodb 1.6).
package hello.mongodb;
import java.net.UnknownHostException;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MapReduceOutput;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
public class MongoDBUpdateFieldByAnotherField {
public static void main( final String[] args ) throws UnknownHostException, MongoException {
final Mongo mongo = new Mongo();
final DB db = mongo.getDB( "helloMR" );
final DBCollection things = db.getCollection( "things" );
things.remove( new BasicDBObject() ); // just clean up
things.insert( new BasicDBObject( "currentVersion", Integer.valueOf( 1 ) ).append( "newVersion", Integer.valueOf( 2 ) ) );
things.insert( new BasicDBObject( "currentVersion", Integer.valueOf( 2 ) ).append( "newVersion", Integer.valueOf( 2 ) ) );
System.out.println( "Have items with version 2: " + things.find( new BasicDBObject( "currentVersion", Integer.valueOf( 2 ) ) ).count() );
final int numUpdated;
final String version = (String) db.command( "serverStatus" ).get( "version" );
if ( version.startsWith( "1.8" ) ) { // a very primitive check on the version...
System.out.println( "Running map/reduce in 1.8 mode." );
numUpdated = updateCurrentVersionViaNewNonBlockingEval( things );
}
else {
System.out.println( "Running map/reduce in 1.6 mode (actual server version: " + version + ")." );
numUpdated = updateCurrentVersionViaOldMapReduce( things );
}
System.out.println( "Updated " + numUpdated + " items." );
System.out.println( "Have items with version 2: " + things.find( new BasicDBObject( "currentVersion", Integer.valueOf( 2 ) ) ).count() );
}
/**
* Sets the currentVersion to newVersion if currentVersion < newVersion using eval without locking (since 1.8).
* @return the number of updated things.
*/
private static int updateCurrentVersionViaNewNonBlockingEval( final DBCollection things ) throws MongoException {
final String code = "var i = 0;" +
"db.things.find({ '$where' : 'this.currentVersion < this.newVersion' })" +
".forEach( function(doc) {" +
" doc.currentVersion = doc.newVersion;" +
" db.things.save(doc);" +
" i += 1; } );" +
"return i;";
final CommandResult commandResult = things.getDB().command( BasicDBObjectBuilder.start()
.add( "$eval" , code )
.add( "nolock" , Boolean.TRUE )
.get() );
commandResult.throwOnError();
return commandResult.getInt( "retval" );
}
/**
* Sets the currentVersion to newVersion if currentVersion &lt; newVersion using map/reduce (mongodb 1.6).
* @return the number of updated things.
*/
@SuppressWarnings( { "boxing" } )
private static int updateCurrentVersion( final DBCollection things ) throws MongoException {
final String mapFunction = "function () {" +
" if (this.currentVersion < this.newVersion) {" +
" emit(this._id, this);" +
" } }";
final String reduceFunction = "function (key, values) { return values[0]; }";
final String finalizeFunction = "function (key, value) { " +
"db.things.update(" +
"{ _id : value._id }, " +
"{ $set : { 'currentVersion' : value.newVersion } } ); }";
final BasicDBObjectBuilder b = BasicDBObjectBuilder.start()
.add("mapreduce", "things")
.add("map", mapFunction )
.add("reduce", reduceFunction )
.add("finalize", finalizeFunction );
final MapReduceOutput output = things.mapReduce( b.get() );
return (Integer) ((DBObject)output.getRaw().get( "counts" )).get( "emit" );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment