简体   繁体   中英

Nested array with knex and node.js

I currently have a table in the database that I use to register the system menus, it is called menu and has a field id_menu, dsc_menu and parent_item. Id_menu is autoincrement and parent_item receives the id_menu of its main menu items. In this case, they become submenus. It turns out that I have tried in many ways to generate a json by nesting with my query, that is, the main menu items and if there is one, a node containing the submenus of that item in question. I thought about making a first query, which will bring me only the main menus, then I would do a foreach in this array, take the id_menu and make a new query now only for the items that have parent_item = id_menu. Then I could concatenate this data again and transform it into a complete array. I made an outline below my idea, however, it doesn't work.

// here I take all the parent menus
var result = await knex.raw("SELECT * FROM menus WHERE parent_item is null");

result[0].forEach(element => { 

    // Here I need to use the parent menu id to get the child menus and add them to a new array that will be inside the "submenus" element of the main array.
    if(element.num_sub_menus > 0) {
         var jsonSubMenus = await knex.raw("SELECT dsc_menu FROM menus WHERE parent_item = ?", element.num_sub_menus);
         // if I try to call the knex again here, using await, it gives an error and if I don't use awaita it returns an empty promisse.
    }

    resultado += '{';
    resultado += '"id_menu_admin": ' + element.id_menu_admin + ',';
    resultado += '"dsc_menu": "' + element.dsc_menu + '",';
    resultado += '"parent_item": ' + element.parent_item + ',';
    resultado += '"rota": "' + element.rota + '",';
    resultado += '"icone": "' + element.icone + '",';
    resultado += '"num_sub_menus": ' + element.num_sub_menus + ',';
    resultado += '"submenus": ['+jsonSubMenus+']';
    resultado += '},';}
);

For subqueries, either return an empty promise if I don't use await, as an example, or give a compilation error if I use await.

I imagine that there must be a more professional way of doing this, bringing a nested array through a single query. Remembering that my menu items and submenu are in the same table.

While you could use a for loop instead of forEach so that await would be permitted inside, it'd be better to use a somewhat different approach - use Promise.all so that all submenus are queried at once, in parallel, then construct the resultado .

It looks like resultado is JSON, so you should use an object literal and then JSON.stringify instead of manually concatenating. Something along the lines of:

const getSubmenus = elm => elm.num_sub_menus > 0
  ? knex.raw("SELECT dsc_menu FROM menus WHERE parent_item = ?", elm.num_sub_menus)
  : null;
const withSubmenus = await Promise.all(result[0].map(
  elm => Promise.all([element, getSubmenus(element)])
);
const resultArr = withSubmenus.map(([e, submenus]) => ({
  id_menu_admin: e.id_menu_admin,
  dsc_menu: e.dsc_menu,
  // ...,
  ...(submenus ? { submenus } : {})
}));
const resultJSON = JSON.stringify(resultArr);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM