Home > OS >  Create new array element only if inner object has different value
Create new array element only if inner object has different value

Time:05-30

{
  FullName: "Emily Clark",
  Details: {
    Income: [
      {
        2021: [
          {
            time: "Sun Apr 11 2021 17:42:39 GMT 0530 (India Standard Time)",
            description: "Web",
            amount: "3700",
          },
          {
            time: "Sun May 21 2022 07:12:59 GMT 0530 (India Standard Time)",
            description: "Pc Monitor",
            amount: "45000",
          },
        ],
      },
      {
        2022: [
          {
            time: "Sat May 28 2022 12:23:34 GMT 0530 (India Standard Time)",
            description: "Class",
            amount: "4100",
          },
        ],
      },
    ],
    Expense: [
      {
        2022: [
          {
            time: "Tue May 17 2022 20:30:39 GMT 0530 (India Standard Time)",
            descritption: "Car Wash",
            amount: 4000,
          },
          {
            time: "Fri May 19 2022 10:23:29 GMT 0530 (India Standard Time)",
            description: "Loundry",
            amount: "300",
          },
        ],
      },
    ],
  },
};

Here I firstly added a new Expense Data object to the Details.Income.0.2021 so it created a new array and object after Income, but after adding new Expense data for a new Year as 2022 it was added to the existing object of first income element, how to create a new array object for new year only if the year not exists?

The second Income element was added by me manually from MongoDB shell.

If the year exist I want the data to look like for Expense where it has two Object data for both the same year.

I know this explanation is a little messy but I am willing to provide more information if needed.

CodePudding user response:

EDIT: Since Income and Expense are arrays of objects, and each year is a key inside it, the all solution is rather complicated.

One option is to do something like:

  1. add the new item to the doc,
  2. calculate the lastYear on the Income
  3. Add a new year if lastYear is not the same as the input year yearString
  4. remove the last year from Details.Income in order to edit it. Keep it as last.
  5. Add the new item to it.
  6. Merge it back to the original structure.
db.collection.update({
  FullName: "Emily Clark"
},
[
  {$addFields: {
      newItem: {a: "test"},
      year: yearString
    }
  },
  {
    $addFields: {
      lastYear: {
        $reduce: {
          input: {$objectToArray: {$last: "$Details.Income"}},
          initialValue: "",
          in: {$concat: ["$$value", "$$this.k"]}
        }
      }
    }
  },
  {
    $addFields: {
      newArr: {
        $cond: [
          {$eq: ["$lastYear", "$year"]},
          [],
          [{yearString: []}]
        ]
      }
    }
  },
  {
    $set: {
      "Details.Income": {
        $concatArrays: ["$Details.Income", "$newArr"]
      },
      year: "$$REMOVE",
      newArr: "$$REMOVE"
    }
  },
  {
    $set: {
      last: {$objectToArray: {$last: "$Details.Income"}},
      "Details.Income": {
        $slice: ["$Details.Income", {$subtract: [{$size: "$Details.Income"}, 1]
          }
        ]
      }
    }
  },
  {
    $set: {
      last: {
        $map: {
          input: "$last",
          as: "item",
          in: {
            v: {$concatArrays: ["$$item.v", ["$newItem"]]},
            k: "$$item.k"
          }
        }
      }
    }
  },
  {$set: {last: {$arrayToObject: ["$last"]}}},
  {
    $set: {
      "Details.Income": {$concatArrays: ["$Details.Income", ["$last"]]},
      last: "$$REMOVE",
      newItem: "$$REMOVE",
      lastYear: "$$REMOVE"
    }
  }
])

Playground example

If Income and Expense were an object instead of array of objects it would be as simple as:

db.collection.update({
  FullName: "Emily Clark"
},
{
  $push: {
    "Details.Expense.2022": 
     {
        time: "Fri May 19 2022 10:23:29 GMT 0530 (India Standard Time)",
        description: "Loundry",
        amount: "300",
      }
  }
})
  • Related