2
votes

I have a problem with a query with aggregation framework. Given a collection with documents like:

db.testSize.insert([{
    "internalId" :1,
    "first" : {
            "second" : [
                {
                    "value" : 1
                }
            ]
    }

}])

this aggregation :

db.testSize.aggregate([
 { $addFields: { tmpSize: { $strLenCP: { $ifNull: [ { $toString: "$first.second.value" }, "" ] } } } },
])

return this error:

{
    "message" : "Unsupported conversion from array to string in $convert with no onError value",
    "ok" : 0,
    "code" : 241,
    "codeName" : "ConversionFailure",
    "name" : "MongoError"
}

Now, the solution on this problem is to use unwind in the following way:

db.testSize.aggregate([
 { $unwind: "$first.second"},
 { $addFields: { tmpSize: { $strLenCP: { $ifNull: [ { $toString: "$first.second.value" }, "" ] } } } },
])

But my requirement is to create a general approach for documents with various shape and possible nested array inside array. Due this bug https://jira.mongodb.org/browse/SERVER-6436 seems to be impossible to unwind array inside array, so how to solve this problem ?

There is an approach ?

Some context:

  • I cannot change document structure before aggregation
  • I don't know where array will be in "field hierarchy", if first for example is an array, or is second

Thanks in advance

1
could you please elaborate ? I'm not able to find a way to use $map in my case, because what I need is a general approach, as I writtenVokail
check new answerValijon

1 Answers

1
votes

You can use $reduce.

====== Aggregate ======

db.testSize.aggregate([
  {
    "$addFields": {
      "first.second.tmpSize": {
        "$reduce": {
          "input": "$first.second",
          "initialValue": "",
          "in": {
            $strLenCP: {
              $ifNull: [
                {
                  $toString: "$$this.value"
                },
                ""
              ]
            }
          }
        }
      }
    }
  }
])

====== Result ======

[
  {
    "_id": ObjectId("5d925bd3fabc692265f950d5"),
    "first": {
      "second": [
        {
          "tmpSize": 1,
          "value": 1
        }
      ]
    },
    "internalId": 1
  }
]

Mongo Playground