Search code examples
jsonmongodbexpressmongoosefindandmodify

Compare json data from 2 column with in schema and overwrite the latest data to main data in mongoos


I am trying to build a page from json data, column "page_content" will have json and column "override_content" will have one or more parts of json with key. "override_content" will always have the latest update, if column is null no override data. Expected result is compare the data from both the columns "page_content" & "override_content" using internal json "id" and replace content in "page_content" with "override_content" column

Below are the Examples

Data in "page_content" looks like below, components has 3 child each child has unique "id"

{
"components":[
    {
        "id":"uibuilder:fa10894e44b3460c93912198a99e3629",
        "component":{
            "name":"Hero",
            "properties":{
                "imageUrl":"https://images.unsplash.com/photo-1532298229144-0ec0c57515c7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2000&q=80",
                "caption1":"New Collection",
                "caption2":"About this collection",
                "buttonText":"Click Me!"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"20px",
                "minHeight":"20px",
                "minWidth":"20px",
                "overflow":"hidden"
            }
        }
    },
    {
        "id":"uibuilder:8818c12fe5c94b27b7f7033fec7910b6",
        "component":{
            "name":"Text",
            "properties":{
                "text":"<p>This iss text</p>"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"20px",
                "minHeight":"20px",
                "minWidth":"20px",
                "overflow":"hidden"
            }
        }
    },
    {
        "id":"uibuilder:8818c12fe5c94b25c94b23fec033fec7",
        "component":{
            "name":"Text New",
            "properties":{
                "text":"<b>Component heading</b>"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"10px",
                "minHeight":"10px",
                "minWidth":"10px",
                "overflow":"hidden"
            }
        }
    }
]

}

"override_content" column has latest data for 1st and 3rd child like below,

{
"components":[
    {
        "id":"uibuilder:fa10894e44b3460c93912198a99e3629",
        "component":{
            "name":"Hero",
            "properties":{
                "imageUrl":"https://images.unsplash.com/photo-1532298229144-0ec0c57515c7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2000&q=80",
                "caption1":"Faucet Collection",
                "caption2":"",
                "buttonText":"Click Me!"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"10px",
                "minHeight":"10px",
                "minWidth":"10px",
                "overflow":"hidden"
            }
        }
    },
    {
        "id":"uibuilder:8818c12fe5c94b25c94b23fec033fec7",
        "component":{
            "name":"Text New",
            "properties":{
                "imageUrl":"https://images.unsplash.com/photo-1532298229144-0ec0c57515c7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2000&q=80",
                "caption1":"New Collection",
                "caption2":"About this collection",
                "buttonText":"Click Me!"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"50px",
                "minHeight":"50px",
                "minWidth":"50px",
                "overflow":"hidden"
            }
        }
    }
]

}

Expected result: Compare both the column data by child "id". replace the 1st and 3rd child in "page_content" with "override content" Retain the 2nd Child from "page_content" as is

{
"components":[
    {
        "id":"uibuilder:fa10894e44b3460c93912198a99e3629",
        "component":{
            "name":"Hero",
            "properties":{
                "imageUrl":"https://images.unsplash.com/photo-1532298229144-0ec0c57515c7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2000&q=80",
                "caption1":"Faucet Collection",
                "caption2":"",
                "buttonText":"Click Me!"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"10px",
                "minHeight":"10px",
                "minWidth":"10px",
                "overflow":"hidden"
            }
        }
    },
    {
        "id":"uibuilder:8818c12fe5c94b27b7f7033fec7910b6",
        "component":{
            "name":"Text",
            "properties":{
                "text":"<p>This iss text</p>"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"20px",
                "minHeight":"20px",
                "minWidth":"20px",
                "overflow":"hidden"
            }
        }
    },
    {
        "id":"uibuilder:8818c12fe5c94b25c94b23fec033fec7",
        "component":{
            "name":"Text New",
            "properties":{
                "imageUrl":"https://images.unsplash.com/photo-1532298229144-0ec0c57515c7?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2000&q=80",
                "caption1":"New Collection",
                "caption2":"About this collection",
                "buttonText":"Click Me!"
            }
        },
        "componentStyle":{
            "large":{
                "display":"flex",
                "flexDirection":"column",
                "position":"relative",
                "flexShrink":"0",
                "boxSizing":"border-box",
                "marginTop":"50px",
                "minHeight":"50px",
                "minWidth":"50px",
                "overflow":"hidden"
            }
        }
    }
]

}

My API in ExpressJs look like below, Pages is the collection I am trying to use mongoose aggregate

router.get('/pages/findit/:_id', (req: Request, res: Response) => {
  const id = req.params._id;
  if (id && id.length > 0) {
    const pid = mongoose.Types.ObjectId(id);
    Pages.aggregate([
      {
        $match: { _id: pid }
      }
    ]).exec((err, data) => {
      if (err) { res.status(HttpStatusEnum.badserver).json(err); return; };
      let result: IResponse = {
        data: data
      };
      res.status(HttpStatusEnum.success).json(result);
    });
  }
});

Thank you


Solution

  • Couldn't able to find a approach through Mongoose aggregate, but used external method to compare and merge the json array, once we have the result from the collection will pass the data into below script to compare and merge, (In my case merge operation is required for single recorded at a time)

    const sourceJson = { components: [{ id: 'a' }, { id: 'b', test: 'a' }] };
    const customJson = { components: [{ id: 'b', test: 'b' }, { id: 'c' }] };
          const result = sourceJson.components.map(sj => ({
            ...sj, 
            ...customJson.components.find(cj => sj.id === cj.id)
          }))
          return result;
    

    Output:

    {"components":[{"id":"a"},{"id":"b","test":"b"},{"id":"c"}]}