Получить все родительские объекты по значению js

Есть мультивложенный json

let dataset = [
    {
        "id": 456,
        "name": "Name1",
        "children": [
            {
                "id": 3111,
                "name": "Name1.1",
                "children": [                    
                        {
                            "id": 504,                           
                            "name": "Name1.1.1",                           
                            "children": [
                                {
                                    "id": 509,
                                    "name": "Name1.1.1.1",
                                    "children": []
                                },
                            ]
                        },
                ]                
            },
            {
                "id": 3120,
                "name": "Name1.2",
                "children": [
                    {
                        "id": 877,
                        "name": "Name1.2.1",
                        "children": []
                    },
                ]
            },
        ]
    },
    {
        "id": 456,
        "name": "Name2",
        "children": [
            {
                "id": 50,
                "name": "Name2.1",
                "children": []
            },
        ]
    },
]

Как получить по значению "id": 509 всех его родителей?

upd сделал такой вариант, но он выводит только самые первые ветки родителей, "id": 877 не выводит.

var current = dataset[0], titles = [];
while(current && current.id != 509){
    titles.push(current.name);
    current = current.children[0] || {}
}
console.log(titles.join(" > "));

Ответы (3 шт):

Автор решения: id1

Есть очень хорошое решение для таких задач tree-model-js

Очень просто с ним работать:

var TreeModel = require('tree-model'),
    tree = new TreeModel();
    // ваш dataset конвертировали в дерево
    root = tree.parse(dataset);
    // теперь у вас доступны много функций для работы с деревом. 
    // особенно обратите внимание на функцию .walk([options], action, [context])

→ Ссылка
Автор решения: Андрей Иванов

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

let currentArr = []
let data = []
function printReverseList(list, id) {
    if (list.id !== id){
        currentArr.push(list.name)
    }
        else {
            data = currentArr.slice()
        }
    if (list.children) {
        list.children.forEach(element => {
            printReverseList(element, id);
            }
        );
    }
    currentArr.splice(0)
}

printReverseList(dataset[0], 509); // надо крутить в цикле
console.log(data)

Затем, не стал заморачиваться и последовал совету @id1

Теперь всё отлично работает.

function getAllParentThisNode(dataset, nodeId)
{
    let parents = []
    var TreeModel = require('tree-model'),
    tree = new TreeModel();
    dataset.forEach(element => {      
            let rootMain = tree.parse(element);
                rootMain.walk(function (node) {
                    if (node.model.id === nodeId) {
                        let x = node.getPath()
                        x.forEach(element => {                                  
                            parents.push(element.model.name)                               
                            }
                        )
                    }
                });
    })
    return parents
}

console.log(getAllParentThisNode(dataset, 877))
→ Ссылка
Автор решения: Стив Ривз

Функция, возвращающая массив объектов-родителей, может может выглядеть так:

С использованием tree-model-js:

const getParentsById = (id, data) => {
const TreeModel = require('tree-model'),
 tree = new TreeModel(),
 root = tree.parse(data);

const path
root.walk(function (node) {
    // Halt the traversal by returning false
    if (node.model.id === id) {
        path= node.getPath()
        return false;
    }
}); 
path.pop()
return  path.map(item => item.model)
}

Без использования tree-model-js (если data - массив объектов):

const getParentsById = (id, data) => {
const isFoundChild = (id, data, parents) => {
    if (data.find(item => item.id == id)) {
        return true;
    }
    else {
        for (let item of data) {
            if (item.children.length)
                if (isFoundChild(id, item.children)) {
                    parents.push(item);
                    return true;
                }
        }
        return false;
    }
}

const parents = [];
if (data.find(item => item.id == id))
    return [];
else {
    for (let item of data) {
        if (item.children.length)
            if (isFoundChild(id, item.children, parents)) {
                parents.push(item);
                return parents;
            }
    }
}
}
→ Ссылка