【问题标题】:Create Javascript Object Having Nested Parent Objects创建具有嵌套父对象的 Javascript 对象
【发布时间】:2018-07-24 00:15:52
【问题描述】:

我正在开发一个 Nodejs 项目。我必须创建一个接受对象(子类别)的函数,例如:

{
    id: 65,
    name: 'Outdoor',
    parent_id: 2
}

现在我希望我的函数使用数据库中的parent_id 检查父类别并返回一个数组/对象,如下所示:

{
    id: 2,
    name: 'Furniture',
    parent: {
        id: 1,
        name: 'Residential',
        parent: {
            id: ...,
            name: ...,
            parent: {
                and so on..
            }
        }
    }
}

这是我到目前为止所做的:

* _get_category_parents(category, _array) {

    if(_array === undefined) _array = []

    if( category.parent_id !== 0 ) {
      const c_parent = yield this.Database.from('categories').where('id', '=', category.parent_id)
      _array.push({id: c_parent[0].id, name: c_parent[0].name})
      yield this._get_category_parents(c_parent[0], _array)

    }

    return _array

  }

然后像这样调用这个函数:

const parents = yield this._get_category_parents(category)

这会返回一个这样的父母数组:

[
    {
        "id": 2,
        "name": "Furniture"
    },
    {
        "id": 1,
        "name": "Residential"
    }
]

我希望将 Residential 对象附加到家具的父节点中。

我在这方面花了太多时间,但没有得到我想要的。任何帮助将不胜感激。

【问题讨论】:

  • 生成器的实现似乎很棘手......我相信使用 promises 或 async/await 会更容易
  • 我认为是简单的递归。
  • @ali 你用的是哪个数据库?一些数据库支持递归查询,允许您使用单个查询获取所有数据——即,而不是使用 javascript 一次查询一条记录。
  • @naomik 我正在使用 mysql

标签: javascript node.js recursion adonis.js


【解决方案1】:

您要考虑的是递归解决方案。

由于您正在调用数据库,这可能不太可能,但如果按 id 查找是同步的,您可以使用类似以下的代码来执行此操作(请注意,我在这里伪造了一个 db):

const getHierarchy = (lookup, child) => {
  const {id, name, parent_id} = lookup(child) || 
        {id: null, name: null, parent_id: 0}
  return parent_id == 0  
         ? {id, name, parent_id} 
         :  {...{id, name},  ...{parent: getHierarchy(lookup, {parent_id})}}
}

const items = [
  {id: 1, name: 'Residential', parent_id: 5},
  {id: 2, name: 'Furniture', parent_id: 1},  
  {id: 3, name: 'Other', parent_id: 0},   
  {id: 4, name: 'FooBar', parent_id: 3},   
  {id: 5, name: 'Stuff', parent_id: 0} 
]

const lookup = child => items.find(item => item.id == child.parent_id)

const item = {id: 65, name: 'Outdoor', parent_id: 2}

console.log(getHierarchy(lookup, item))

您必须编写一个适当的lookup 函数,大概使用this.Database.from(...)。您可能还想要简化版本,在您的 lookup 函数中烘焙,在这种情况下,您可以编写

const getAncestry = (item) => getHierarchy(lookup, item)

如果您的查找很可能是异步的,那么这将影响getHierarchy 以及您如何调用它。这是一种可能性:

const getHierarchy = async (lookup, child) => {
  const {id, name, parent_id} = await lookup(child) || 
        {id: null, name: null, parent_id: 0}
  return parent_id == 0  
         ? {id, name, parent_id} 
         :  {...{id, name},  ...{parent: await getHierarchy(lookup, {parent_id})}}
}

const items = [
  {id: 1, name: 'Residential', parent_id: 5},
  {id: 2, name: 'Furniture', parent_id: 1},  
  {id: 3, name: 'Other', parent_id: 0},   
  {id: 4, name: 'FooBar', parent_id: 3},   
  {id: 5, name: 'Stuff', parent_id: 0} 
]

const lookup = async child => new Promise(
  (resolve, reject) => setTimeout(
    () => resolve(items.find(item => item.id == child.parent_id)), 
    1000
  )
)
const getAncestry = async item => getHierarchy(lookup, item)

const item = {id: 65, name: 'Outdoor', parent_id: 2}

getAncestry(item).then(console.log)

注意调用函数的方式发生了变化。你需要调用 .then() 来获得任何有用的行为。

【讨论】:

  • 哇.. 工作就像一个魅力。正是我需要的。那是一个单一的解决方案。非常感谢 Scott Sauyet。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-14
  • 2018-09-30
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
相关资源
最近更新 更多