[SERVER-6769] ExpressionNary (and others) do not properly serialize constant expressions, can cause a valid expression on mongos to be unparsable or incorrect on shards. Created: 15/Aug/12  Updated: 11/Jul/16  Resolved: 11/Sep/13

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: None
Fix Version/s: 2.5.2

Type: Bug Priority: Major - P3
Reporter: Aaron Staple Assignee: Matt Dannenberg
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Participants:

 Description   

An object or string specified as a constant to an ExpressionNary may not be parsed as a constant on a shard. This is because ExpressionNary does not use requireExpression with addToBsonArray, so constants are not represented using $const.

Test

// Set up a sharding test.                                                                                                             
s = new ShardingTest( "aggregation", 2, 0, 2 );
s.adminCommand( { enablesharding:"test" } );
s.adminCommand( { shardcollection:"test.data", key:{ _id:1 } } );
s.stopBalancer()
 
d = s.getDB( "test" );
d.data.save( { dollar:false } );
 
// Currently the shard will get $cond:[ '$dollar', '$1.00', '$.99' ] and treat the second and third arguments as field paths.
result = d.data.aggregate( { $project:{ _id:0, cost:{ $cond:[ '$dollar', { $const:'$1.00' }, { $const:'$.99' } ] } } } );
 
printjson( result );
assert.eq( [ { cost:'$.99' } ], result.result );
 
s.stop();

When fixing this we should also do a general audit for other cases that do not serialize properly.



 Comments   
Comment by Matt Dannenberg [ 11/Sep/13 ]

done as part of this commit:
https://github.com/mongodb/mongo/commit/cd81198d0280abc8144bd7fa291a15564c1c0ae4

added a test based on the description here to jstests/aggregation/testshard1.js

Comment by Mathias Stearn [ 17/Aug/12 ]

Good point.

Comment by Aaron Staple [ 17/Aug/12 ]

An explicit $const made the test a bit easier to write, but it's not the only way something like this can happen. See following test, I think there are other ways it can happen as well

 
// Set up a sharding test.                                                                                                                                  
s = new ShardingTest( "aggregation", 2, 0, 2 );
s.adminCommand( { enablesharding:"test" } );
s.adminCommand( { shardcollection:"test.data", key:{ _id:1 } } );
s.stopBalancer()
 
d = s.getDB( "test" );
d.data.save( { dollar:false } );
 
// Currently the shard will get $cond:[ '$dollar', '$1.00', '$.99' ] and treat the second and third arguments as field paths.                               
result = d.data.aggregate( { $project:{ _id:0, cost:{ $cond:[ '$dollar', { $substr:[ '_$1.00', 1, 5 ] }, { $substr:[ '_$.99', 1, 4 ] } ] } } } );
 
printjson( result );
assert.eq( [ { cost:'$.99' } ], result.result );
 
s.stop();

Comment by Mathias Stearn [ 17/Aug/12 ]

FYI - At least for now, $const is supposed to be an implementation detail of the serialization between mongos and mongod and NOT a user visible feature. In particular it is not documented for cases such as this.

Comment by Aaron Staple [ 15/Aug/12 ]

Tentatively scheduling for 2.3.0.

Generated at Thu Feb 08 03:12:39 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.