我可以在 Sequelize.js 中的单个查询中获取 ID 为 1 的类别和该类别的所有子类别吗?

Can I get Category with id 1 and all Subcategories of that Category in a single query in Sequelize.js?

我有以下数据库table:

Table: Categories
Columns: id, name, parent_id

以及以下记录:

1 / Category1 / 0
2 / Category2 / 0
3 / Subcategory1 / 1
4 / Subcategory2 / 1

所以我有 2 个类别 - Category1 和 Category2 以及 Category1 的 2 个子类别 - Subcategory1 和 Subcategory2。

如果parent_id字段为0,则表示该记录是一个类别,如果它不为0且具有另一个类别的id,则它是该类别的子类别。

现在我得到的所有类别都是这样的:

Category.findAll({
    where: {
        'parent_id': 0
    }
})
.then(result => {
    console.log(result)
})
.catch(error => {
    console.log(error)
})

但现在我还想以某种方式将类别的子类别作为对象包括在内 属性。现在我得到这个:

[
    {
      "id": 1,
      "name": "Category1",
      "parent_id": 0
    }
]

我想得到这样的东西:

[
    {
      "id": 1,
      "name": "Category1",
      "parent_id": 0,
      "subcategories": [
          {
              "id": 3,
              "name": "Subcategory1",
              "parent_id": 1,
          },
          {
              "id": 4,
              "name": "Subcategory2",
              "parent_id": 1,
          }
      ]
    }
]

它类似于预先加载,但它就像模型预先加载本身。我怎样才能以最少的查询次数做到这一点?

您需要使用 sequelize.define() 创建一个支持您的 table 的 Model,在本例中为“类别”

// first define your model, you don't have to define the `id` or `parent_id` as they will be created automatically
const Categories = sequelize.define('categories', {
  name: {
    type: DataTypes.STRING(255),
  },
},
{
  // use underscores in generated column names
  underscored: true,
});

现在为模型创建 parent-

// relate a category to its parent=
Categories.belongsTo(Categories, {
  as: 'parent', 
  foreignKey: 'parent_id', 
  targetKey: 'id',
});

// relate parent to child categories
Categories.hasMany(Categories, {
  as: 'subcategories',
  foreignKey: 'parent_id',
});

现在您可以使用 include 选项传入 Model 并指定 as 参数来加载正确的关系。传入 required: false 以使用左连接,以便在没有子类别时返回结果。

// ... your code

// now you can include the subcategories and 
// pass in the parent_id into the where clause
const category = await Categories.findOne({
  include: {
    model: Categories,
    as: 'subcategories',
    required: false,
  },
  where: {
    parent_id: 0,
  },
});

// if you know the ID you want is 1...
const category = await Categories.findByPk(1, {
  include: {
    model: Categories,
    as: 'subcategories',
    required: false,
  },
});

在相反的方向,从 child 到 parent,或者在这种情况下两者...

// To get a category and its parent and children...
const categoryWithParentAndSubcategories = await Categories.findByPk(123, {
  include: [
    {
      model: Categories,
      as: 'parent',
      required: false,
    },
    {
      model: Categories,
      as: 'subcategories',
      required: false,
    },
  ],
});

// you can keep going for multiple levels if you want

// To get a category and its grandparent, parent and children...
const categoryWithParentAndSubcategories = await Categories.findByPk(123, {
  include: [
    {
      model: Categories,
      as: 'parent',
      required: false,
      include: {
        model: Categories,
        as: 'parent',
        required: false,
      },
    },
    {
      model: Categories,
      as: 'subcategories',
      required: false,
    },
  ],
});