The API I use sometimes returns recursive data:
{
"chain": {
"details": "0",
"subChains": [
{
"details": "1",
"subChains": [ more subchains ]
},
{
"details": "2",
"subChains": [ more subchains ]
},
....
]
}
}
As you can see, subchains come as an array, so we have many children for one parent.
My goal is to copy these data to my own DB using Prisma. They should have the same structure as the original, parent-child relation and arrays included. If possible, I'd like to do this in one prismadb.chain.create() call.
The Prisma model might look like this (adapted from this model):
model Chain {
id Int @id
details String
parentId String?
parent Chain? @relation("ParentChildren", fields: [parentId], references: [id])
subChains Chain[] @relation("ParentChildren")
}
Note: I'm not sure what "ParentChildren" is. Since it's also used with sub-chains it looks like a tag to link parent and sub-chains but I didn't find any documentation on this subject yet.
I tried adding creates recursively to the data:
prismadb.chain.create({
data: addCreateRecursive(chain),
})
let id = 1;
// parentId is null for the top-level chain
// hence why we have `parent Chain?` in the model
function addCreateRecursive(chain, parentId = null) {
return {
// generating new ids the easy way
// given this algo is depth-first the id won't be continuous inside
// a single array, but not sure what to do
id: id++,
parentId,
subChains: {
create: chain.subChains.map(ch => addCreateRecursive(ch, id)),
},
};
}
But the top chains had children, where much of the data went deeper than that.
My current workaround is to flatten the tree into an array, while passing parentIds as appropriate.
let id = 0;
function flattenTree(initialChain, parentId = null) {
id += 1;
const chain = {
id,
parentId,
};
const subChains = initialChain.subChains.flatMap(ch => flattenTree(chain, id));
return [chain].concat(subChains)
}