【问题标题】:Node - Knex to return array of objects as a result of joined tables节点 - Knex 作为连接表的结果返回对象数组
【发布时间】:2021-02-15 18:17:07
【问题描述】:

我正在使用 knexjs 和 node 并使用这些表运行 postgres db:menu 和 menuItem 具有一对多的关系。我在这里找到了一个解决方案 knex: what is the appropriate way to create an array from results? 但这会返回一个字符串数组。我需要的是返回一个对象数组和一个空数组(如果为 null),看起来与下面的示例完全相同:

[
  {
    id: 123,
    name: 'Sunday Menu',
    items: []
  }, 
  {
    id: 456,
    name: 'Monday Menu',
    items: [
      { 
         id: 987,
         name: 'Fried Chicken',
         pcs: 69
      },
      { 
         id: 876,
         name: 'Egg Soup',
         pcs: 50
      },
    ]
  }
]

我的菜单和 menuItem 表架构类似于:

menu_table: {
  id,
  name,
  timestamps
}
menuItem_table: {
  id,
  menu_id,
  name,
  pcs,
  timestamps
}

目前,我的代码是这样的:

knex('menu').leftJoin('menuitem', 'menu.id', 'menuitem.menu_id')
.select(['menu.id as menuID', knex.raw('ARRAY_AGG(menuitem.name) as items')])
.groupBy('menu.id')

结果如下:

[
  {
     "menuID": "20091fff-ca8b-42d6-9a57-9f6e1922d0fa",
     "items": [
         null
     ]
  },
  {
     "menuID": "2ddad4fa-7293-46c5-878f-cb2881be3107",
     "items": [
         "Fried Chicken",
         "Egg Soup",
         "Vegetable Dish"
     ]
  }
]

更新:我发现了如何使用原始查询来做到这一点,但我无法使用 knex 进行翻译。这是我的代码:

SELECT menu.*, COALESCE(menuitem.items, '[]') AS items FROM menu LEFT JOIN LATERAL ( 
   SELECT json_agg(menuitem.*) AS items FROM menuitem WHERE menu.id = menuitem.menu_id 
) menuitem ON true

【问题讨论】:

  • 你能告诉我们你的尝试吗?
  • 我目前尝试过这个:knex('menu').leftJoin('menuitem', 'menu.id', 'menuitem.menu_id').select(['menu.id as menuID', knex.raw('ARRAY_AGG(menuitem.name) as items')]).groupBy('menu.id') 并返回items: ['Fried Chicken', 'Egg Soup']
  • 将其添加到您的问题中。这是可以使您的问题有效且不会作为“我的家庭作业”类型问题而结束的事情之一

标签: node.js postgresql knex.js


【解决方案1】:

我终于找到了解决问题的方法。由于我能够通过原始查询获得我想要的结果,我只是将它翻译成 knex。我的最终代码是这样的:

const coalesce = knex.raw(`coalesce(menuitem.items, '[]') as items`)
const sub = knex('menuitem').select(knex.raw('json_agg(menuitem.*) as items')).whereRaw('menu.id = menuitem.menu_id')

return knex('menu').select(['menu.*', coalesce]).joinRaw('left join lateral ? menuitem on true', sub)

我将同时使用这段代码,直到有人给我最准确的答案。

【讨论】:

  • 一个缺点是行在从数据库返回之前被转换为 json 类型。因此,例如由 pg-types 完成的自定义反序列化将不起作用。
  • 会注意到这一点。谢谢!
【解决方案2】:

这项工作,我添加附件,ty DevWannabe:

const results = await knex.column({
  'id': 'str.id',
  'projectName': 'str.project_name',
})
.from('venturedoor.startups as str')
.leftJoin('venturedoor.attachments as att', 'str.id', 'att.startup_id')
// join array attachments
.select(['str.id', knex.raw('ARRAY_AGG(att.*) as attachments')])
.groupBy('str.id')   

【讨论】:

    【解决方案3】:
    knex.raw('coalesce(usr.userName,usr.email ,seat.username) as username')
    

    我们可以这样使用。如果 userName 为空,则将调用电子邮件,如果电子邮件也将调用名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      • 2011-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多