Created
March 10, 2011 22:24
-
-
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 < 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