【问题标题】:How to nest data from a join table in a one (or many) to many relationship in knex.js?如何将连接表中的数据嵌套在 knex.js 中的一对多关系中?
【发布时间】:2019-10-24 07:19:52
【问题描述】:

假设我有用户、技能和 user_skill 表。

如何查询,以便如果我有 3 个用户,我会得到 3 个对象(显然是在一个数组中),并且对于每个用户的对象应该有一个包含所有技能的嵌套数组?

类似这样的:

{
    "users": [
        {
            "name": "dusan",
            "id": 1,
            "facebook": "dusan's facebook",
            "skills": [
                {"name": "skill1", "id": 1}
                {"name": "skill2", "id": 2}
            ]
        },
        {
            "name": "jenny",
            "id": 2,
            "facebook": "jenny's facebook",
            "skills": [
                {"name": "skill1", "id": 1}
                {"name": "skill2", "id": 2}
            ]
        },
        {
            "name": "michael",
            "id": 3,
            "facebook": "michael's facebook",
            "skills": [
                {"name": "skill1", "id": 1}
                {"name": "skill2", "id": 2}
            ]
        },

    ]
}

我的代码:

await db("users")
  .join("user_skill",  "users.id", "skills.user_id")
  .join("skills", "skills.id", "user_skill.id")
  .select(
    "users.name as name",
    "users.id as id",
    "skills.name as skill",
    "skills.id as skill_id"
);

上面的代码返回了一个完全扁平化的 JSON,我希望有技能嵌套在用户对象中。

{
    "users": [
        {
            "name": "dusan",
            "id": 1,
            "skill": "node.js",
            "skill_id": 1
        },
        {
            "name": "dusan",
            "id": 1,
            "skill": "php",
            "skill_id": 2
        },
        {
            "name": "dusan",
            "id": 1,
            "skill": "mongodb",
            "skill_id": 3
        },
        {
            "name": "jaca",
            "id": 2,
            "skill": "angular",
            "skill_id": 4
        },
        {
            "name": "jaca",
            "id": 2,
            "skill": "reactjs",
            "skill_id": 5
        },
    ]
}

我知道 SQL 是这样设计的,返回平面结构,但是有没有办法可以完成相关数据的嵌套?

【问题讨论】:

  • 您可以自己或使用 ORM 将平面数据格式化为结构化数据。
  • 如果你能提供一个如何自己完成的例子,那将非常有帮助。与此同时,我会尝试自己做。我认为需要 .map 和 .reduce,只需要头脑清醒。

标签: sql node.js postgresql orm knex.js


【解决方案1】:

一位开发人员提出了这个解决方案,所以我决定分享它,希望有人会觉得它有帮助:

returnedUsers = {
  "users": [{
      "name": "dusan",
      "id": 1,
      "skill": "node.js",
      "skill_id": 1
    },
    {
      "name": "dusan",
      "id": 1,
      "skill": "php",
      "skill_id": 2
    },
    {
      "name": "dusan",
      "id": 1,
      "skill": "mongodb",
      "skill_id": 3
    },
    {
      "name": "jaca",
      "id": 2,
      "skill": "angular",
      "skill_id": 4
    },
    {
      "name": "jaca",
      "id": 2,
      "skill": "reactjs",
      "skill_id": 5
    },
  ]
};

const groupBy = (array, key) =>
  array.reduce((a, c) => ({
    ...a,
    [c[key]]: [...a[c[key]] || [], c]
  }), {});

const uniques = (...values) =>
  Array.from(new Set([].concat(...values).filter(Boolean)));

const singularize = array =>
  array.length == 1 ? array[0] : array;

const singularizedUniques = (...values) =>
  singularize(uniques(...values));

const mergeCollect = array =>
  array.reduce((mergedObject, curentObject) =>
    Object.entries(curentObject).reduce((newObject, [k, v]) => ({
      ...newObject,
      [k]: singularizedUniques(newObject[k], v)
    }), mergedObject), {});

const groupByKey = (array, key) =>
  Object.fromEntries(Object.entries(groupBy(array, key)).map(([k, v]) => [k, mergeCollect(v)]));

console.log(groupByKey(returnedUsers.users, 'id'));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2017-12-11
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多