diff --git a/src/main/com/mongodb/DB.java b/src/main/com/mongodb/DB.java index 10e28e0c52c..95fcaadfd74 100644 --- a/src/main/com/mongodb/DB.java +++ b/src/main/com/mongodb/DB.java @@ -269,11 +269,7 @@ public CommandResult command( DBObject cmd , int options, ReadPreference readPre */ public CommandResult command( DBObject cmd , int options, ReadPreference readPrefs, DBEncoder encoder ){ readPrefs = getCommandReadPreference(cmd, readPrefs); - - // TODO: automate an integration test for this condition - if (getMongo().isMongosConnection()) { - cmd.put(QueryOpBuilder.READ_PREFERENCE_META_OPERATOR, readPrefs.toDBObject()); - } + cmd = wrapCommand(cmd, readPrefs); Iterator i = getCollection("$cmd").__find(cmd, new BasicDBObject(), 0, -1, 0, options, readPrefs , @@ -288,6 +284,22 @@ public CommandResult command( DBObject cmd , int options, ReadPreference readPre return cr; } + // Only append $readPreference meta-operator if connected to a mongos, read preference is not primary + // or secondary preferred, + // and command is an instance of BasicDBObject. The last condition is unfortunate, but necessary in case + // the encoder is not capable of encoding a BasicDBObject + // Due to issues with compatibility between different versions of mongos, also wrap the command in a + // $query field, so that the $readPreference is not rejected + private DBObject wrapCommand(DBObject cmd, final ReadPreference readPrefs) { + if (getMongo().isMongosConnection() && + !(ReadPreference.primary().equals(readPrefs) || ReadPreference.secondaryPreferred().equals(readPrefs)) && + cmd instanceof BasicDBObject) { + cmd = new BasicDBObject("$query", cmd) + .append(QueryOpBuilder.READ_PREFERENCE_META_OPERATOR, readPrefs.toDBObject()); + } + return cmd; + } + /** * Executes a database command. * @see List of Commands