Reputation: 73
db.getCollection('docs').aggregate([
{
$project: {
"has books" :
{ $in: ["A", {$cond: {if: {$gt: ["$books", null]}, then: "$books", else: []}}] }
}
}
])
The above query works when executed on a standalone MongoDB and gives the following result:
/* 1 */
{
"_id" : ObjectId("5ca6023ccb9228c0ab417ad5"),
"has books" : false
}
/* 2 */
{
"_id" : ObjectId("5ca631b8cb9228c0ab419174"),
"has books" : false
}
/* 3 */
{
"_id" : ObjectId("5ca64006cb9228c0ab419a54"),
"has books" : false
}
/* 4 */
{
"_id" : ObjectId("5ca6e093cb9228c0ab41cf7c"),
"has books" : true
}
/* 5 */
{
"_id" : ObjectId("5ca6eee9cb9228c0ab41d594"),
"has books" : false
}
However, on executing the same query on AWS DocumentDB instance the following error is given:
Failed to execute script.
Error: command failed: {
"ok" : 0,
"errmsg" : "$in requires an array as a second argument, found: object",
"code" : 40081
} : aggregate failed
Details:
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:534:17
assert.commandWorked@src/mongo/shell/assert.js:618:16
DB.prototype._runAggregate@src/mongo/shell/db.js:260:9
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1062:12
DBCollection.prototype.aggregate@:1:355
@(shell):1:1
The aim of the query is to check if a particular value is present in the array or not, with the output expected as boolean. Thedocs
collection has an array field = books
which can be null, so to overcome the null issue, $cond
is used to replace books
field with an empty array if the field does not exist or is null.
$ifNull
is not supported by AWS DocumentDB so it cannot be used.
Suggestions to correct the above query or use an alternative query which will be supported by AWS DocumentDB to get the expected result will be of immense help.
Upvotes: 2
Views: 309
Reputation: 22296
So the problem is you have books
field that's neither null
nor an array.
You can work around this by using $ifNull like so:
db.getCollection('docs').aggregate([
{
$project: {
"has books" :
{ $in: ["A", {$cond: {if: {$ne: [{$ifNull: ["$books", null]}, null]}, then: "$books", else: []}}] }
}
}
])
Or using $isArray:
db.getCollection('docs').aggregate([
{
$project: {
"has books" :
{ $in: ["A", {$cond: {if: {$isArray: "$books"}, then: "$books", else: []}}] }
}
}
])
Or without using any of these operators because they're not supported then you can add a type
field and then continue:
db.getCollection('docs').aggregate([
{
$addFields: {
booksType: {$type: "$books"}
}
},
{
$project: {
"has books" :
{ $in: ["A", {$cond: {if: {$eq: ["$booksType", 4]}, then: "$books", else: []}}] }
}
}
])
Upvotes: 1