Reputation: 107
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
Reputation: 36094
$map
to iterate loop of questions
array$map
to iterate loop of answer
arrayshape
array ten wrap it in to array bracket$mergeObjects
with sub documents img
, m_IMG
objects$mergeObjects
with current document and updated answer
arraydb.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"]
]
}
}
]
}
}
]
}
}
]
}
}
}
}
]
}
}
}
}
}
])
Upvotes: 1
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