@@ -269,11 +269,7 @@ public CommandResult command( DBObject cmd , int options, ReadPreference readPre
269269 */
270270 public CommandResult command ( DBObject cmd , int options , ReadPreference readPrefs , DBEncoder encoder ){
271271 readPrefs = getCommandReadPreference (cmd , readPrefs );
272-
273- // TODO: automate an integration test for this condition
274- if (getMongo ().isMongosConnection ()) {
275- cmd .put (QueryOpBuilder .READ_PREFERENCE_META_OPERATOR , readPrefs .toDBObject ());
276- }
272+ cmd = wrapCommand (cmd , readPrefs );
277273
278274 Iterator <DBObject > i =
279275 getCollection ("$cmd" ).__find (cmd , new BasicDBObject (), 0 , -1 , 0 , options , readPrefs ,
@@ -288,6 +284,22 @@ public CommandResult command( DBObject cmd , int options, ReadPreference readPre
288284 return cr ;
289285 }
290286
287+ // Only append $readPreference meta-operator if connected to a mongos, read preference is not primary
288+ // or secondary preferred,
289+ // and command is an instance of BasicDBObject. The last condition is unfortunate, but necessary in case
290+ // the encoder is not capable of encoding a BasicDBObject
291+ // Due to issues with compatibility between different versions of mongos, also wrap the command in a
292+ // $query field, so that the $readPreference is not rejected
293+ private DBObject wrapCommand (DBObject cmd , final ReadPreference readPrefs ) {
294+ if (getMongo ().isMongosConnection () &&
295+ !(ReadPreference .primary ().equals (readPrefs ) || ReadPreference .secondaryPreferred ().equals (readPrefs )) &&
296+ cmd instanceof BasicDBObject ) {
297+ cmd = new BasicDBObject ("$query" , cmd )
298+ .append (QueryOpBuilder .READ_PREFERENCE_META_OPERATOR , readPrefs .toDBObject ());
299+ }
300+ return cmd ;
301+ }
302+
291303 /**
292304 * Executes a database command.
293305 * @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
0 commit comments