[SERVER-30461] aggregation $concat expression is inconsistent in type checking with all other string expressions Created: 01/Aug/17  Updated: 06/Dec/22

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

Type: Improvement Priority: Major - P3
Reporter: Asya Kamsky Assignee: Backlog - Query Optimization
Resolution: Unresolved Votes: 0
Labels: query-44-grooming, usability
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-8239 $concat should fail on non-string types Closed
related to SERVER-6195 consider $concat to concatenate strin... Closed
is related to SERVER-85081 Standardize behavior of non-string in... Closed
is related to SERVER-6203 Aggregation operators should have wel... Backlog
Assigned Teams:
Query Optimization
Participants:

 Description   

$concat expression tests if all arguments passed to it are of type String and then calls coerceToString before concatenating them.

All other expressions that expect a string just call coerceToString on the argument(s) and rely on that to throw an error if the conversion is impossible.

I think all string-expecting expressions should be consistent - if the passed in value can be coerced to string then do that.

db.foo.aggregate({$project:{dateToString:{$substr:["$d",0,4]},_id:0}})
{ "dateToString" : "2017" }
db.foo.aggregate({$project:{dateToString:{$toUpper:"$d"},_id:0}})
{ "dateToString" : "2017-08-01T17:29:05" }
db.foo.aggregate({$project:{dateToString:{$toLower:"$d"},_id:0}})
{ "dateToString" : "2017-08-01t17:29:05" }
db.foo.aggregate({$project:{dateToString:{$concat:["$d","_"]},_id:0}})
assert: command failed: {
	"ok" : 0,
	"errmsg" : "$concat only supports strings, not date",
	"code" : 16702,
	"codeName" : "Location16702",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1501608545, 1),
		"signature" : {
			"hash" : BinData(0,"y9mqIQNK2OhW40Hm2VIctAxrgcQ="),
			"keyId" : NumberLong("6448521287567409154")
		}
	},
	"operationTime" : Timestamp(1501608545, 1)
} : aggregate failed
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:16:14
assert.commandWorked@src/mongo/shell/assert.js:403:5
DB.prototype._runAggregate@src/mongo/shell/db.js:250:9
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1269:12
@(shell):1:1
 
2017-08-01T10:48:52.841-0700 E QUERY    [thread1] Error: command failed: {
	"ok" : 0,
	"errmsg" : "$concat only supports strings, not date",
	"code" : 16702,
	"codeName" : "Location16702",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1501608545, 1),
		"signature" : {
			"hash" : BinData(0,"y9mqIQNK2OhW40Hm2VIctAxrgcQ="),
			"keyId" : NumberLong("6448521287567409154")
		}
	},
	"operationTime" : Timestamp(1501608545, 1)
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:16:14
assert.commandWorked@src/mongo/shell/assert.js:403:5
DB.prototype._runAggregate@src/mongo/shell/db.js:250:9
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1269:12
@(shell):1:1

I can work-around by wrapping what's passed to $concat in {{$substr:[ <expr>, 0, 99999]]] but it seems silly and inconsistent.



 Comments   
Comment by Charlie Swanson [ 12/Feb/18 ]

Bumping this out of the epic since it expanded in scope and is not strictly required. We also don't want to hold up the design on this, which is (hopefully) nearing completion.

Comment by Charlie Swanson [ 12/Feb/18 ]

I'm kicking this back out of this sprint. After looking a little more closely, there's not a behavior that's obviously more correct/consistent than this. We'll need to take a look at the larger picture and decide what semantics we want for non-string input to the string expressions.

Comment by Asya Kamsky [ 08/Sep/17 ]

Note that all relational DBs that I checked seem to do implicit type conversions in simple cases like these.

Generated at Thu Feb 08 04:23:53 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.