首页 > 解决方案 > mongo 将单个对象转换为一个元素数组

问题描述

我有以下问题。在此示例数据集中:

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"
          }
        ]
      }
    ]
  }
]

你会发现,如果answer一个问题只存在一个,它就被表示为一个对象。如果存在多个,则它是一个数组。在shape节点中也是如此。我想知道将这些节点转换为始终数组的最佳方法是什么(因此,如果存在一个答案,它将是一个元素的数组)。

标签: mongodbmongodb-queryaggregation-framework

解决方案


从 MongoDb 版本 >= 4.4 开始,您可以使用$function运算符定义自定义函数以实现 MongoDB 查询语言不支持的行为。尝试这个:

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"
        }
      }
    }
  }
]);

输出:

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

测试数据:

[
    {
        "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"
                    }
                }
            }
        ]
    }
]

推荐阅读