#javascript #arrays #recursion
Вопрос:
У меня есть такая таблица (или структура данных)
Есть parentIdeaId
то, что относится к идентификатору в ideas
самой таблице.
Вот мои неструктурированные данные (пожалуйста, имейте в виду, что это существующие данные в базе данных, а не данные, которые уже есть, поэтому я должен сначала запросить их при некоторых условиях).
[{
"id": "1",
"title": "Title 1",
"parentIdeaId": null
},{
"id": "2",
"title": "Title 2",
"parentIdeaId": 1
},{
"id": "3",
"title": "Title 3",
"parentIdeaId": 2
},{
"id": "4",
"title": "Title 4",
"parentIdeaId": null
}]
Я также создал функцию для поиска данных (я использую Prisma в своем реальном коде).
function find({ id }) {
return prisma.idea.findUnique({
where: {
id
}
});
}
И функция для поиска детей
function responseIdeas({ parentIdeaId }) {
return prisma.idea.findMany({
where: {
parentIdeaId
}
});
}
Я хочу, чтобы данные фильтровались только по связанным данным (по их parentIdeaId
), поэтому, если я запрошу идентификатор "1"
, результат будет
[{
"id": "1",
"title": "Title 1",
"parentIdeaId": null
},{
"id": "2",
"title": "Title 2",
"parentIdeaId": 1
}{
"id": "3",
"title": "Title 3",
"parentIdeaId": 2
}]
The id: "4"
isn’t inserted because it’s not related by its parent
Here’s what I made:
const data = [
{
id: "1",
title: "Title 1",
parentIdeaId: null
},
{
id: "2",
title: "Title 2",
parentIdeaId: 1
},
{
id: "3",
title: "Title 3",
parentIdeaId: 2
},
{
id: "4",
title: "Title 4",
parentIdeaId: null
}
];
function find({ id }) {
return data.find(e => e.id === id);
}
function responseIdeas({ parentIdeaId }) {
return data.filter(e => e.parentIdeaId == parentIdeaId);
}
async function detail({ id }) {
const findChildren = async ({ id }) => {
const idea = await find({ id });
const responses = await responseIdeas({ parentIdeaId: id });
if (responses.length !== 0) {
const resolveResponses = await Promise.all(
responses.map(async ({ id }) => findChildren({ id }))
);
return [idea, ...resolveResponses];
}
return { ...idea };
};
return findChildren({ id });
}
async function run() {
const result = await detail({ id: "1" });
console.dir(result, { depth: null });
}
run();
Но все закончилось вот так
[
{
"id": "1",
"title": "Title 1",
"parentIdeaId": null
},
[
{
"id": "2",
"title": "Title 2",
"parentIdeaId": 1
},
{
"id": "3",
"title": "Title 3",
"parentIdeaId": 2
}
]
]
Где я все испортил? Спасибо
Комментарии:
1. Если ваша база данных не очень велика (миллионы или записи) или не очень динамична, вам, возможно, будет лучше загрузить все данные сразу и выполнить все поиски в памяти без вложенных обещаний.
2. @georg Hi Georg. Да, это динамично, и я могу предсказать, какие данные у меня будут, поэтому я даю это в обещаниях.
Ответ №1:
findChildren потенциально возвращает массив массивов из-за того, что вы возвращаете Promise.all () ->, который представляет собой массив обещаний, и некоторые из этих обещаний могут быть массивами.
Таким образом, вы можете использовать concat для объединения результата в основной массив, например, вот так https://codesandbox.io/s/quizzical-sun-c4khx?file=/src/index.js
Комментарии:
1. Это работает, спасибо! Обычно я использую concat с оператором распространения, но на этот раз я немного перепутал с самим оператором и попытался поэкспериментировать с чем-то подобным
[idea, ...resolveResponse]
, но не получилось. Могу ли я добиться этого с помощью оператора распространения?