TergOfSky
TergOfSky

Reputation: 107

mongo convert single object to one element array

I have the following problem. In this example dataset:

https://mongoplayground.net/p/itNnrDzZ4JQ

[
  {
    "name": "test",
    "questions": [
      {
        "headline": "headline 1",
        "answer": {
          "@id": "001",
          "m_IMG": {
            "type": "06",
            "img": {
              "@id": "1111",
              "shape": [
                {
                  "@src": "/1_1.jpg",
                  "@type": "Z05"
                },
                {
                  "@src": "/1_2.jpg",
                  "@type": "Z08"
                }
              ]
            }
          },
          "text": "text1"
        }
      },
      {
        "headline": "Headline 2",
        "answer": [
          {
            "@id": "001",
            "m_IMG": {
              "@type": "24",
              "img": {
                "@id": "1111",
                "shape": {
                  "@src": "/2_1.jpg",
                  "@type": "Z05"
                }
              },
              "text": "Test2"
            }
          },
          {
            "@id": "002",
            "m_IMG": {
              "@typeName": "",
              "@type": "25",
              "img": {
                "@id": "2222",
                "shape": [
                  {
                    "@src": "/2_1.jpg",
                    "@type": "Z05"
                  },
                  {
                    "@src": "2_2.jpg",
                    "@type": "Z08"
                  }
                ]
              }
            },
            "text": "Test3"
          }
        ]
      }
    ]
  }
]

You will find that if only a single answer to a question exists it is represented as an object. If more than one exists then it is an array. This is also true in the shape node. I wonder what is the best way to convert those nodes to be always arrays (so if one answer exists it would be an array of one element).

Upvotes: 3

Views: 661

Answers (2)

turivishal
turivishal

Reputation: 36094

  • $map to iterate loop of questions array
  • check condition if answer is not array then put into array bracket and input as $map to iterate loop of answer array
  • check condition is not shape array ten wrap it in to array bracket
  • $mergeObjects with sub documents img, m_IMG objects
  • $mergeObjects with current document and updated answer array
db.collection.aggregate([
  {
    $set: {
      questions: {
        $map: {
          input: "$questions",
          as: "q",
          in: {
            $mergeObjects: [
              "$$q",
              {
                answer: {
                  $map: {
                    input: {
                      $cond: [
                        { $eq: [{ $isArray: "$$q.answer" }, true] },
                        "$$q.answer",
                        ["$$q.answer"]
                      ]
                    },
                    as: "a",
                    in: {
                      $mergeObjects: [
                        "$$a",
                        {
                          m_IMG: {
                            $mergeObjects: [
                              "$$a.m_IMG",
                              {
                                img: {
                                  $mergeObjects: [
                                    "$$a.m_IMG.img",
                                    {
                                      shape: {
                                        $cond: [
                                          { $eq: [{ $isArray: "$$a.m_IMG.img.shape" }, true] },
                                          "$$a.m_IMG.img.shape",
                                          ["$$a.m_IMG.img.shape"]
                                        ]
                                      }
                                    }
                                  ]
                                }
                              }
                            ]
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Playground

Upvotes: 1

Dheemanth Bhat
Dheemanth Bhat

Reputation: 4452

From MongoDb version >= 4.4 you can use the $function operator to define custom functions to implement behavior not supported by the MongoDB Query Language. Try this:

db.collection.aggregate([
  { $unwind: "$questions" },
  {
    $addFields: {
      "questions.answer": {
        $function: {
          body: function (answers) {
            if (Array.isArray(answers)) {
              answers.map(function (answer) {
                if (!Array.isArray(answer.m_IMG.img.shape)) {
                  answer.m_IMG.img.shape = [answer.m_IMG.img.shape]
                }
              })

              return answers;
            } else {
              if (!Array.isArray(answers.m_IMG.img.shape)) {
                answers.m_IMG.img.shape = [answers.m_IMG.img.shape]
              }

              return [answers];
            }
          },
          args: ["$questions.answer"],
          lang: "js"
        }
      }
    }
  }
]);

Output:

/* 1 createdAt:3/29/2021, 5:57:13 PM*/
{
    "_id" : ObjectId("6061c7a1e801471ae43210ae"),
    "name" : "test",
    "questions" : {
        "headline" : "headline 1",
        "answer" : [
            {
                "@id" : "001",
                "m_IMG" : {
                    "type" : "06",
                    "img" : {
                        "@id" : "1111",
                        "shape" : [
                            {
                                "@src" : "/1_1.jpg",
                                "@type" : "Z05"
                            },
                            {
                                "@src" : "/1_2.jpg",
                                "@type" : "Z08"
                            }
                        ]
                    }
                },
                "text" : "text1"
            }
        ]
    }
},

/* 2 createdAt:3/29/2021, 5:57:13 PM*/
{
    "_id" : ObjectId("6061c7a1e801471ae43210ae"),
    "name" : "test",
    "questions" : {
        "headline" : "Headline 2",
        "answer" : [
            {
                "@id" : "001",
                "m_IMG" : {
                    "@type" : "24",
                    "img" : {
                        "@id" : "1111",
                        "shape" : [
                            {
                                "@src" : "/2_1.jpg",
                                "@type" : "Z05"
                            }
                        ]
                    },
                    "text" : "Test2"
                }
            },
            {
                "@id" : "002",
                "m_IMG" : {
                    "@typeName" : "",
                    "@type" : "25",
                    "img" : {
                        "@id" : "2222",
                        "shape" : [
                            {
                                "@src" : "/2_1.jpg",
                                "@type" : "Z05"
                            },
                            {
                                "@src" : "2_2.jpg",
                                "@type" : "Z08"
                            }
                        ]
                    }
                },
                "text" : "Test3"
            }
        ]
    }
},

/* 3 createdAt:3/29/2021, 5:57:13 PM*/
{
    "_id" : ObjectId("6061c7a1e801471ae43210ae"),
    "name" : "test",
    "questions" : {
        "headline" : "headline 3",
        "answer" : [
            {
                "@id" : "003",
                "m_IMG" : {
                    "@type" : "25",
                    "img" : {
                        "@id" : "1221",
                        "shape" : [
                            {
                                "@src" : "/2_6.jpg",
                                "@type" : "Z07"
                            }
                        ]
                    },
                    "text" : "Test21"
                }
            }
        ]
    }
}

Test data:

[
    {
        "name": "test",
        "questions": [
            {
                "headline": "headline 1",
                "answer": {
                    "@id": "001",
                    "m_IMG": {
                        "type": "06",
                        "img": {
                            "@id": "1111",
                            "shape": [
                                {
                                    "@src": "/1_1.jpg",
                                    "@type": "Z05"
                                },
                                {
                                    "@src": "/1_2.jpg",
                                    "@type": "Z08"
                                }
                            ]
                        }
                    },
                    "text": "text1"
                }
            },
            {
                "headline": "Headline 2",
                "answer": [
                    {
                        "@id": "001",
                        "m_IMG": {
                            "@type": "24",
                            "img": {
                                "@id": "1111",
                                "shape": {
                                    "@src": "/2_1.jpg",
                                    "@type": "Z05"
                                }
                            },
                            "text": "Test2"
                        }
                    },
                    {
                        "@id": "002",
                        "m_IMG": {
                            "@typeName": "",
                            "@type": "25",
                            "img": {
                                "@id": "2222",
                                "shape": [
                                    {
                                        "@src": "/2_1.jpg",
                                        "@type": "Z05"
                                    },
                                    {
                                        "@src": "2_2.jpg",
                                        "@type": "Z08"
                                    }
                                ]
                            }
                        },
                        "text": "Test3"
                    }
                ]
            },
            {
                "headline": "headline 3",
                "answer": {
                    "@id": "003",
                    "m_IMG": {
                        "@type": "25",
                        "img": {
                            "@id": "1221",
                            "shape": {
                                "@src": "/2_6.jpg",
                                "@type": "Z07"
                            }
                        },
                        "text": "Test21"
                    }
                }
            }
        ]
    }
]

Upvotes: 1

Related Questions