Mongo $ in query работает в автономном экземпляре mongo, но не в экземпляре 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 имеет массив field = books, который может быть нулевым, поэтому для преодоления проблемы с нулевым значением $cond используется для замены поля books пустым массивом, если поле не существует или имеет значение NULL. $ifNull не поддерживается AWS DocumentDB, поэтому его нельзя использовать.

Предложения по исправлению вышеуказанного запроса или использованию альтернативного запроса, который будет поддерживаться AWS DocumentDB для получения ожидаемого результата, окажут огромную помощь.


person Ritu Raut    schedule 11.06.2020    source источник
comment
может сначала поменять $gt на $ne?   -  person Tom Slabbaert    schedule 11.06.2020
comment
пробовал, то же самое происходит с использованием $ne   -  person Ritu Raut    schedule 11.06.2020
comment
Убедитесь, что поле четко определено во всех документах, undefined! == null.   -  person Tom Slabbaert    schedule 11.06.2020
comment
проверено на наличие неопределенного поля, а их нет.   -  person Ritu Raut    schedule 11.06.2020
comment
Просто убедитесь, что вы проверили с помощью books: {$exits: false}?   -  person Tom Slabbaert    schedule 11.06.2020
comment
Еще нужно проверить, что все book являются массивами типов. используйте $type для этого.   -  person Tom Slabbaert    schedule 11.06.2020
comment
с books: {$exits: false} я получил документы, в которых не было поля, и я также проверил с {books: {$type: 6}, который дал мне 0 документов.   -  person Ritu Raut    schedule 11.06.2020
comment
6 устарел. если у вас есть документы с {$exists: false}, значит, в этом проблема. напишу ответ с решением как его обойти \   -  person Tom Slabbaert    schedule 11.06.2020


Ответы (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: []}}] }
        }
    }
])
person Tom Slabbaert    schedule 11.06.2020
comment
Как упоминалось выше, $ifNull не поддерживается AWS DocumentDB, поэтому его нельзя использовать :( - person Ritu Raut; 11.06.2020
comment
как насчет $isArray, когда я добавил к своему ответу? - person Tom Slabbaert; 11.06.2020
comment
все вышеперечисленное не работает для экземпляра DocumentDB, но работает для автономного экземпляра mongodb. - person Ritu Raut; 11.06.2020
comment
Я добавил другую версию, которая выглядит менее привлекательно, но не использует никаких операторов, которые не поддерживаются. - person Tom Slabbaert; 11.06.2020