Создать иерархическое дерево для ответа JSON


Есть приблизительно 43.000 документов (уникальных узлов). Построение древовидной структуры, которая имеет 4 уровня.

пример 4 различных уровнях: 13000000 - сегмента 13010000 - основная группа 13010100 - группы 13010101 - товар класса

Я использую компонент угловой дерево, которое нужно данные, выполните следующие структуры.

Код я прикрепил ниже сгенерирует массив объектов и дереве отображается правильно, но это займет приблизительно 1 минута, чтобы создать эту структуру.

Любая помощь/идеи будут высоко ценится!

Как вы видите, я использую кратные циклы foreach, чтобы

  1. генерация уровня
  2. создания детей (основные группы) на уровне сегмента
  3. создать детей (групп) основных уровня группы
  4. создания детей (товарного класса) уровень группы

Пример node массива, которые являются завершающим проектом этот код выглядит так

nodes = [{
  "id": "13000000",
  "name": "13 Development (Service)",
  "hasChildren": true,
  "children": [{
    "id": "13010000",
    "name": "1301 Concept development",
    "hasChildren": true,
    "children": [{
      "id": "13010100",
      "name": "130101 Feasibility analysis",
      "hasChildren": true,
      "children": [{
        "id": "13010190",
        "name": "13010190 Feasibility analysis (unspecified)",
        "isLeaf": true
      }]
    }, {
      "id": "13010200",
      "name": "130102 Product definition (concept definition)",
      "hasChildren": true,
      "children": [{
        "id": "13010290",
        "name": "13010290 Product definition (concept definition, unspecified)",
        "isLeaf": true
      }]
    }]
  }]
}]

Пример сырого data приходит из базы данных, используемый для создания узлов массива выше.

data = [
  {
    "_id": "59cbb85b4c4eff813d359ae3",
    "preferredName": "Public safety and military technology",
    "codedName": "49000000"
  },
  {
    "_id": "59cbb85b4c4eff813d359b99",
    "preferredName": "Interior furnishing",
    "codedName": "50000000"
  },
  {
    "_id": "59cbb85b4c4eff813d359c4a",
    "preferredName": "Garden furniture, terrace furniture, balcony furniture",
    "codedName": "50090000"
  },
  {
    "_id": "59cbb85b4c4eff813d359c4b",
    "preferredName": "Outdoor combination",
    "codedName": "50090100"
  },
  {
    "_id": "59cbb85b4c4eff813d359c4c",
    "preferredName": "Outdoor combination (unspecified)",
    "codedName": "50090190"
  },
  {
    "_id": "59cbb85b4c4eff813d359c4d",
    "preferredName": "Outdoor combination (parts)",
    "codedName": "50090191"
  },
  {
    "_id": "59cbb85b4c4eff813d359c4e",
    "preferredName": "Outdoor combination (accessories)",
    "codedName": "50090192"
  },
  {
    "_id": "59cbb85b4c4eff813d359c4f",
    "preferredName": "Outdoor lounge furniture",
    "codedName": "50090200"
  },
  {
    "_id": "59cbb85b4c4eff813d359c50",
    "preferredName": "Outdoor lounge furniture (unspecified)",
    "codedName": "50090290"
  },
  {
    "_id": "59cbb85b4c4eff813d359c51",
    "preferredName": "Outdoor lounge furniture (parts)",
    "codedName": "50090291"
  },
  {
    "_id": "59cbb85b4c4eff813d359c52",
    "preferredName": "Outdoor lounge furniture (accessories)",
    "codedName": "50090292"
  }]

Мой рабочий код

/* GET WHOLE eCl@ss Tree. */
router.get("/all", (req, res, next) => {
  const nodes = [];
  Eclass.find({}, "level codedName preferredName").sort({ codedName: 1 })
    // Level 1 - segment
    .then(data => {
      data.forEach(item => {
        if (item.codedName !== undefined && item.codedName.substring(2, 4) === "00") {
          const node = {
            id: item.codedName,
            name: `${item.codedName.substring(0, 2)} ${item.preferredName}`,
            hasChildren: true,
            children: []
          };
          nodes.push(node);
        }
      });
      // console.log(nodes);
      return data;
    })
    // Level 2 - main group
    .then(data => {
      nodes.forEach(parent => {
        data.forEach(item => {
          if (item.codedName !== undefined && item.codedName.substring(2, 4) !== "00" && item.codedName.substring(4, 6) === "00") {
            if (parent.id.substring(0, 2) === item.codedName.substring(0, 2)) {
              const node = {
                id: item.codedName,
                name: `${item.codedName.substring(0, 4)} ${item.preferredName}`,
                hasChildren: true,
                children: []
              };
              parent.children.push(node);
            }
          }
        });
      });
      return data;
      // console.log(JSON.stringify(nodes, null, 2));
    })
    // Level 3 - group
    .then(data => {
      nodes.forEach(parent => {
        data.forEach(item => {
          if (item.codedName !== undefined && item.codedName.substring(4, 6) !== "00" && item.codedName.substring(6, 8) === "00") {
            parent.children.forEach(child => {
              if (child.id.substring(0, 4) === item.codedName.substring(0, 4)) {
                const node = {
                  id: item.codedName,
                  name: `${item.codedName.substring(0, 6)} ${item.preferredName}`,
                  hasChildren: true,
                  children: []
                };
                child.children.push(node);
              }
            });
          }
        });
      });
      return data;
    })
    // Level 4 - commodity class
    .then(data => {
      nodes.forEach(parent => {
        data.forEach(item => {
          if (item.codedName !== undefined && item.codedName.substring(6, 8) !== "00") {
            parent.children.forEach(child => {
              child.children.forEach(child => {
                if (child.id.substring(0, 6) === item.codedName.substring(0, 6)) {
                  const node = {
                    id: item.codedName,
                    name: `${item.codedName.substring(0, 8)} ${item.preferredName}`,
                    isLeaf: true
                  };
                  child.children.push(node);
                }
              });
            });
          }
        });
      });
      // console.log(JSON.stringify(nodes, null, 2));
      res.status(200).json(nodes);
    })
    .catch(err => console.error(err));
});


Комментарии
1 ответ

Смотрел кстати вы принять эти уровни, как подуровень имеет тот же префикс как и его родитель, если отсортировать данные по codedNameвы будете иметь данные сортируются таким образом, что если вы видите n уровень узла, последний n - 1 уровень узла обработки будет своего родителя.

Например, когда вы переходите после сортировки и codedName это 13010190, вы знаете, что 13010100 был уже обработан (т. к. количество ниже) и что все узлы обработаны между 13010100 и 13010190 будет 4-го уровня, потому что следующим возможным уровнем 3 узла (13010200) будет появляться после 13010190.

Имея это в виду, мы можем сортировать все данные по codedName а потом просто добавлять каждый узел нижнего уровня последний раз видели узел, который будет правильным родителем для него.

Чтобы избежать пограничных случаях с узлы 1-го уровня, я решил сделать поддельные уровне 0 узел корень, который будет иметь все узлы 1-го уровня. Своих детей будет то, что вам нужно называется nodes в вашем первом примере.

Кроме того, я не создать свойства hasChildren и isLeaf так что может быть легко проверено children.length == 0. Если в вашем требовании, чтобы иметь их, должен быть легким, чтобы добавить их.

Этот код также будет работать более чем на 4 уровнях так долго, как следует, тот же формат. Вот код:



data = [
{
"_id": "59cbb85b4c4eff813d359ae3",
"preferredName": "Public safety and military technology",
"codedName": "49000000"
},
{
"_id": "59cbb85b4c4eff813d359b99",
"preferredName": "Interior furnishing",
"codedName": "50000000"
},
{
"_id": "59cbb85b4c4eff813d359c4a",
"preferredName": "Garden furniture, terrace furniture, balcony furniture",
"codedName": "50090000"
},
{
"_id": "59cbb85b4c4eff813d359c4b",
"preferredName": "Outdoor combination",
"codedName": "50090100"
},
{
"_id": "59cbb85b4c4eff813d359c4c",
"preferredName": "Outdoor combination (unspecified)",
"codedName": "50090190"
},
{
"_id": "59cbb85b4c4eff813d359c4d",
"preferredName": "Outdoor combination (parts)",
"codedName": "50090191"
},
{
"_id": "59cbb85b4c4eff813d359c4e",
"preferredName": "Outdoor combination (accessories)",
"codedName": "50090192"
},
{
"_id": "59cbb85b4c4eff813d359c4f",
"preferredName": "Outdoor lounge furniture",
"codedName": "50090200"
},
{
"_id": "59cbb85b4c4eff813d359c50",
"preferredName": "Outdoor lounge furniture (unspecified)",
"codedName": "50090290"
},
{
"_id": "59cbb85b4c4eff813d359c51",
"preferredName": "Outdoor lounge furniture (parts)",
"codedName": "50090291"
},
{
"_id": "59cbb85b4c4eff813d359c52",
"preferredName": "Outdoor lounge furniture (accessories)",
"codedName": "50090292"
}]




sortedData = data.sort((a, b) => Number(a.codedName) - Number(b.codedName))

var latestNodesPerLevel = [{id: "root", children:[]}]

sortedData.forEach(function(item){

if (item.codedName === undefined) return;

var level = 1;
var index = 2;

while (index < item.codedName.length && item.codedName.substring(index, index + 2) != 0) {
index += 2;
level++;
}

var node = {
id: item.codedName,
children: [],
name: `${item.codedName.substring(0, index)} ${item.preferredName}`,
}

if (latestNodesPerLevel[level - 1] === undefined || latestNodesPerLevel[level - 1].id.substring(0, index - 2) != item.codedName.substring(0, index - 2)) {
console.warn("Parent missing in data", item);
} else {
latestNodesPerLevel[level - 1].children.push(node)
latestNodesPerLevel[level] = node;
}
})

console.log(latestNodesPerLevel[0].children)




2
ответ дан 1 февраля 2018 в 06:02 Источник Поделиться