在前端开发中,树形结构数据查询是常见的需求。Sequelize 是一款 Node.js 的 ORM(对象关系映射)框架,提供了非常便捷的数据库操作方式。本文将介绍在 Sequelize 中如何查询树形结构数据。
关系型数据库中的树形结构
在关系型数据库中,树形结构数据通常以两种方式存储:
- 存储父节点 ID。表中会有一个字段存储当前节点的父节点 ID,如果该节点没有父节点,则父节点 ID 为 NULL。
- 存储子节点列表。表中会有一个字段存储当前节点的子节点列表,通常以 JSON 或数组的格式存储。
以下以第一种方式为例,介绍在 Sequelize 中如何实现树形结构查询。
准备工作
在开始之前,需要先安装 Sequelize 和 mysql2。可以使用 npm 安装:
npm install sequelize mysql2
数据库模型
假设有一个表 categories
存储商品分类信息,表结构如下:
CREATE TABLE `categories` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `parent_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
其中,parent_id
表示当前节点的父节点 ID,如果该节点没有父节点,则 parent_id
为 NULL。
在 Sequelize 中,可以定义一个 Category
模型来操作该表:
const { Sequelize, Model } = require('sequelize'); const sequelize = new Sequelize('database', 'username', 'password', { dialect: 'mysql', }); class Category extends Model {} Category.init( { name: Sequelize.STRING, parentId: Sequelize.INTEGER, }, { sequelize, modelName: 'category' } ); module.exports = Category;
查询树形结构数据
首先,可以通过以下方法查询顶级节点:
const Category = require('./models/category'); const rootCategories = await Category.findAll({ where: { parentId: null, }, });
然后,可以递归查询子节点。以下是基础版的递归查询方法:
async function loadChildren(categories) { for (const category of categories) { const children = await Category.findAll({ where: { parentId: category.id, }, }); if (children.length > 0) { await loadChildren(children); } category.children = children; } }
以上方法中,category.children
存储每个节点的子节点列表。
但是,以上方法会导致 N + 1 查询问题,影响性能。为了解决这个问题,可以使用 Sequelize 提供的 bulkCreate
和 bulkUpdate
方法进行批量操作。
以下是优化版的递归查询方法:
async function loadChildren(categories) { const map = new Map(); for (const category of categories) { map.set(category.id, category); } const children = await Category.findAll({ where: { parentId: { [Sequelize.Op.in]: Array.from(map.keys()), }, }, }); for (const child of children) { const parent = map.get(child.parentId); if (!parent.children) { parent.children = []; } parent.children.push(child); } if (children.length > 0) { await loadChildren(children); } }
以上方法中,loadChildren
通过 Map
存储节点对象,以 parentId
为条件查询子节点,并将子节点添加到父节点的 children
属性中。这样,就实现了一次查询获取所有数据的目的。此时,可以通过以下方法查询所有数据:
const rootCategories = await Category.findAll({ where: { parentId: null, }, }); await loadChildren(rootCategories);
总结
本文介绍了在 Sequelize 中如何查询树形结构数据。通过递归查询和批量操作,可以优化查询性能,提高网页响应速度。对于需要查询树形结构数据的应用场景,可以根据实际需求灵活运用本文介绍的技术方案。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b09996add4f0e0ff9f3e74