数组项中数组的管理
js-lite-rest 支持对数组项内嵌套数组的直接操作,使用 [index] 语法可以访问数组中特定项的数组字段。
概述
通过字符串路径的形式,你可以直接访问和操作数组项中的数组,支持所有标准的 CRUD 操作。
路径语法
表名[索引].字段名例如:
books[0].comments- 访问第1本书的评论数组posts[1].tags- 访问第2篇文章的标签数组users[2].orders- 访问第3个用户的订单数组
基本操作
数据结构示例
javascript
const store = await JsLiteRest.create({
books: [
{
id: 1,
title: 'JavaScript权威指南',
comments: [
{ id: 1, content: '很好的书', author: 'Alice' },
{ id: 2, content: '推荐阅读', author: 'Bob' }
]
},
{
id: 2,
title: 'CSS揭秘',
comments: [
{ id: 3, content: '很实用', author: 'Charlie' }
]
},
{
id: 3,
title: 'HTML5权威指南',
comments: []
}
]
});GET - 获取嵌套数组
javascript
// 获取第1本书的所有评论
const comments = await store.get('books[0].comments');
console.log(comments);
// [
// { id: 1, content: '很好的书', author: 'Alice' },
// { id: 2, content: '推荐阅读', author: 'Bob' }
// ]
// 获取第2本书的评论
const comments2 = await store.get('books[1].comments');
console.log(comments2);
// [{ id: 3, content: '很实用', author: 'Charlie' }]
// 获取第3本书的评论(空数组)
const comments3 = await store.get('books[2].comments');
console.log(comments3); // []POST - 添加到嵌套数组
javascript
// 为第1本书添加新评论
const newComment = await store.post('books[0].comments', {
content: '非常棒的书!',
author: 'David'
});
console.log(newComment);
// { id: 'GENERATED_ID', content: '非常棒的书!', author: 'David' }
// 为没有评论的书添加第一条评论
await store.post('books[2].comments', {
content: '第一条评论',
author: 'Eve'
});PUT - 更新嵌套数组中的项
javascript
// 完整更新第1本书的第1条评论
await store.put('books[0].comments/1', {
content: '更新后的评论',
author: 'Alice-Updated'
});PATCH - 部分更新嵌套数组中的项
javascript
// 只更新评论的作者
await store.patch('books[0].comments/2', {
author: 'Bob-Patched'
});DELETE - 删除嵌套数组中的项
javascript
// 删除第1本书的第1条评论
const deletedComment = await store.delete('books[0].comments/1');
console.log(deletedComment);
// { id: 1, content: '很好的书', author: 'Alice' }高级查询
嵌套数组同样支持所有查询功能:
过滤查询
javascript
// 获取特定作者的评论
const aliceComments = await store.get('books[0].comments', {
author: 'Alice'
});
// 使用运算符查询
const recentComments = await store.get('books[0].comments', {
id_gte: 10, // ID 大于等于 10 的评论
author_ne: 'Spam' // 作者不是 'Spam' 的评论
});排序
javascript
// 按内容排序
const sortedComments = await store.get('books[0].comments', {
_sort: 'content',
_order: 'asc'
});
// 多字段排序
const multiSortComments = await store.get('books[0].comments', {
_sort: 'author,content',
_order: 'desc,asc'
});分页
javascript
// 分页获取评论
const pagedComments = await store.get('books[0].comments', {
_page: 1,
_limit: 5
});
console.log(pagedComments.count); // 总评论数
console.log(pagedComments.list); // 当前页的评论全文搜索
javascript
// 搜索包含特定关键词的评论
const searchResults = await store.get('books[0].comments', {
_q: '推荐'
});复杂示例
博客系统
javascript
const store = await JsLiteRest.create({
posts: [
{
id: 1,
title: '我的第一篇博客',
content: '这是内容...',
comments: [
{ id: 1, content: '写得不错', author: 'reader1', likes: 5 },
{ id: 2, content: '继续加油', author: 'reader2', likes: 3 }
],
tags: ['JavaScript', 'Web开发']
}
]
});
// 获取第一篇文章的热门评论(按点赞数排序)
const hotComments = await store.get('posts[0].comments', {
_sort: 'likes',
_order: 'desc',
_limit: 3
});
// 为第一篇文章添加新评论
await store.post('posts[0].comments', {
content: '学到了很多',
author: 'student',
likes: 0
});
// 给评论点赞(部分更新)
await store.patch('posts[0].comments/1', {
likes: 6
});电商系统
javascript
const store = await JsLiteRest.create({
users: [
{
id: 1,
name: 'Alice',
orders: [
{ id: 'order1', total: 299.99, items: ['book1', 'pen1'] },
{ id: 'order2', total: 199.99, items: ['notebook1'] }
]
}
]
});
// 获取用户的所有订单
const userOrders = await store.get('users[0].orders');
// 添加新订单
await store.post('users[0].orders', {
total: 499.99,
items: ['laptop1', 'mouse1']
});
// 查找大额订单
const bigOrders = await store.get('users[0].orders', {
total_gte: 400
});错误处理
索引超出范围
javascript
try {
// 尝试访问不存在的数组项
await store.get('books[999].comments');
} catch (error) {
console.error('错误:', error.message); // 索引超出范围的错误
}
try {
// 尝试向不存在的数组项添加数据
await store.post('books[999].comments', { content: 'test' });
} catch (error) {
console.error('错误:', error.message); // 数组索引超出范围
}路径错误
javascript
try {
// 访问不存在的字段
await store.get('books[0].nonexistent');
} catch (error) {
console.error('字段不存在');
}性能考虑
1. 索引效率
- 数组索引访问是 O(1) 操作
- 大数组建议使用过滤查询而不是遍历所有索引
javascript
// 推荐:使用查询过滤
const result = await store.get('posts', { authorId: 123 });
const comments = result[0]?.comments || [];
// 不推荐:遍历所有索引
for (let i = 0; i < 1000; i++) {
try {
const comments = await store.get(`posts[${i}].comments`);
// 处理评论...
} catch (error) {
// 索引不存在
}
}2. 批量操作
对于大量数据操作,考虑在父级进行批量更新:
javascript
// 推荐:批量更新父级数据
const books = await store.get('books');
books[0].comments.push(newComment);
await store.put('books/1', books[0]);
// 适用场景:单个评论操作
await store.post('books[0].comments', newComment);限制和注意事项
- 索引必须存在: 数组索引必须在有效范围内,否则会抛出错误
- 字段必须是数组: 目标字段必须是数组类型,否则无法进行数组操作
- 路径解析: 路径中的
[index]语法仅支持数字索引 - 嵌套深度: 理论上支持任意深度的嵌套,但建议保持合理的层级结构