Рекурсивно Найдите и добавьте их в виде массива

#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] , но не получилось. Могу ли я добиться этого с помощью оператора распространения?