Reputation: 9275
I am using Shopify's bulk operation mutation in GraphQL to fetch bulk data for products, invoices, transactions etc.
Shopify returns this data as JSONL. Each line is an object and if it is related to another item then it will have a __parentid
which can be used to figure out its parent.
For example, the returned data will look something like this:
const data = [
{
id: "1",
__typename: "parent"
},
{
id: "2",
__parentId: "1",
__typename: "child"
},
{
id: "3",
__parentId: "2",
__typename: "grandChild"
},
{
id: "4",
__parentId: "2",
__typename: "grandChild"
}
]
In order to save this in my database, I need to nest each child value within its parent.
So the above would become
[
{
id: "1",
__typename: "parent",
child: [
{
id: "2",
__parentId: "1",
__typename: "child",
grandChild: [
{
id: "3",
__parentId: "2",
__typename: "grandChild"
},
{
id: "4",
__parentId: "2",
__typename: "grandChild"
}
]
}
]
},
]
This is one approach I tried where you can see I am trying to attach the children to the parent object and then once it has been moved, delete the original object.
export const reduceBulkResult = (chunks) => {
chunks.reverse()
chunks.forEach(chunk => {
const parent = chunks.find(node =>{
return node.id === chunk.__parentId
})
if( parent ) {
if( parent[chunk.__typename] ) {
parent[chunk.__typename].push(chunk)
} else {
parent[chunk.__typename] = [chunk]
}
}
})
return chunks;
}
console.log("reduceBulkResult", reduceBulkResult(data))
[
{
"__parentId": "2",
"__typename": "grandChild",
"id": "4"
},
{
"__parentId": "2",
"__typename": "grandChild",
"id": "3"
},
{
"__parentId": "1",
"__typename": "child",
"grandChild": [
{
"__parentId": "2",
"__typename": "grandChild",
"id": "4"
},
{
"__parentId": "2",
"__typename": "grandChild",
"id": "3"
}
],
"id": "2"
},
{
"__typename": "parent",
"child": [
{
"__parentId": "1",
"__typename": "child",
"grandChild": [
{
"__parentId": "2",
"__typename": "grandChild",
"id": "4"
},
{
"__parentId": "2",
"__typename": "grandChild",
"id": "3"
}
],
"id": "2"
}
],
"id": "1"
}
]
As you can see, there is a lof of duplication here and I need to get rid of the original objects some how and just keep the parent objects which have all the nested data.
I feel like I'm missing a trick here. There must be an easier way.
Shopify have some good tips such asReading the JSONL file in reverse makes it easier to group child nodes
Upvotes: 0
Views: 386
Reputation: 5977
I get the parent with filter() and then use recursive in getChildren
to get the result.
I cannot find a simple way and you may change codes to make it more simple.
const data = [ { id: "1", __typename: "parent", }, { id: "2", __parentId: "1", __typename: "child", }, { id: "3", __parentId: "2", __typename: "grandChild", }, { id: "4", __parentId: "2", __typename: "grandChild", }, ]; const o = [ { id: "1", __typename: "parent", child: [ { id: "2", __parentId: "1", __typename: "child", grandChild: [ { id: "3", __parentId: "2", __typename: "grandChild", }, { id: "4", __parentId: "2", __typename: "grandChild", }, ], }, ], }, ];
const convert = data => {
const parent = data.filter(el => !el.__parentId);
const getChildren = (data, parentId) => {
let store = {};
for (const obj of data) {
if (obj.__parentId === parentId) {
const children = data.reduce((a, b) => {
if (b.__parentId === obj.id) {
if (a[b.__typename]) {
a[b.__typename].push({ ...b, ...getChildren(data, b.id) });
} else {
a[b.__typename] = [{ ...b, ...getChildren(data, b.id) }];
}
}
return a;
}, {});
store = { ...store, ...obj, ...children };
}
}
return store;
};
return parent.map(el => {
const children = data.reduce((a, b) => {
if (b.__parentId === el.id) {
if (a[b.__typename]) {
a[b.__typename].push({ ...b, ...getChildren(data, el.id) });
} else {
a[b.__typename] = [{ ...b, ...getChildren(data, el.id) }];
}
}
return a;
}, {});
return { ...el, ...children };
});
};
const output = convert(data);
console.log(output);
Upvotes: 1