Mongo $ in查询可在独立的mongo实例中使用,但不适用于AWS DocumentDB实例

时间:2020-06-11 11:42:55

标签: mongodb amazon-web-services mongodb-query aws-documentdb

db.getCollection('docs').aggregate([
    {
      $project: {
        "has books" : 
          { $in: ["A", {$cond: {if: {$gt: ["$books", null]}, then: "$books", else: []}}] }
      }
    }
])

以上查询在独立的MongoDB上执行时有效,并给出以下结果:

/* 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
}

但是,在AWS DocumentDB实例上执行相同的查询时,会给出以下错误:

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

查询的目的是检查数组中是否存在特定值,并且预期输出为布尔值。 docs集合具有一个数组字段= books,该字段可以为空,因此要克服空值问题,如果$cond用于将books字段替换为空数组,字段不存在或为空。 AWS DocumentDB不支持$ifNull,因此无法使用。

更正上述查询或使用AWS DocumentDB支持的替代查询来获得预期结果的建议将有极大帮助。

1 个答案:

答案 0 :(得分:1)

所以问题在于您有books既不是null也不是数组的字段。

您可以使用$ifNull来解决此问题,


db.getCollection('docs').aggregate([
    {
        $project: {
            "has books" :
                { $in: ["A", {$cond: {if: {$ne: [{$ifNull: ["$books", null]}, null]}, then: "$books", else: []}}] }
        }
    }
])

或使用$isArray

db.getCollection('docs').aggregate([
    {
        $project: {
            "has books" :
                { $in: ["A", {$cond: {if: {$isArray: "$books"}, then: "$books", else: []}}] }
        }
    }
])

或者不使用任何这些运算符(因为不支持这些运算符),则可以添加一个type字段,然后继续:

db.getCollection('docs').aggregate([
    {
        $addFields: {
            booksType: {$type: "$books"}
        }
    },
    {
        $project: {
            "has books" :
                { $in: ["A", {$cond: {if: {$eq: ["$booksType", 4]}, then: "$books", else: []}}] }
        }
    }
])