跳到主要内容

查询参数详解

云开发数据模型提供了强大的查询功能,支持复杂的查询条件、字段选择、排序、分页和关联查询。本文将详细介绍数据模型查询操作的各种参数和使用方法。

查询参数概览

数据模型的查询操作主要包含以下参数:

参数类型说明必填
selectSelectParams指定返回的字段
filterFilterParams查询过滤条件
orderByOrderByParams[]排序条件
pageSizenumber分页大小, 最大200
pageNumbernumber页码
getCountboolean是否返回总数

字段选择 select

select 参数用于指定查询结果中应包含的字段,支持主模型字段和关联模型字段的精确控制。

✅ 建议仅选择需要的字段和关系来减少响应数据的大小并提高查询速度。

返回主模型所有字段

使用 $master: true 可以返回主模型的所有字段:

const {
data
} = await models.post.get({
select: {
$master: true, // 查询主模型所有的字段
},
filter: {
where: {
_id: {
$eq: _id, // 推荐传入_id数据标识进行操作
},
},
},
});

console.log(data);
// {
// "owner": "Anonymous(95fblM7nvPi01yQmYxBvBg)",
// "createdAt": 1717488585078,
// "createBy": "Anonymous(95fblM7nvPi01yQmYxBvBg)",
// "updateBy": "Anonymous(95fblM7nvPi01yQmYxBvBg)",
// "_openid": "95fblM7nvPi01yQmYxBvBg",
// "_id": "e2764d2d665ecbc9024b058f1d6b33a4",
// "title": "你好,世界👋",
// "body": "文章内容...",
// "slug": "hello-world",
// "updatedAt": 1717490751944
// }

返回指定字段

通过指定字段名为 true 来选择特定字段:

const {
data
} = await models.post.list({
select: {
_id: true,
title: true,
updatedAt: true,
},
filter: {
where: {},
},
getCount: true,
});

console.log(data);
// {
// "records": [
// {
// "_id": "e2764d2d665ecbc9024b058f1d6b33a4",
// "title": "你好,世界👋",
// "updatedAt": 1717492882289
// }
// // ... 更多记录
// ],
// "total": 51
// }

返回关联模型字段

可以同时查询关联模型的字段:

const {
data
} = await models.post.list({
select: {
_id: true,
title: true,
updatedAt: true,
// 关联查询评论数据
comments: {
_id: true,
createdAt: true,
comment: true,
}, // 也可以直接传 true 返回评论中所有的字段
},
filter: {
where: {},
},
getCount: true,
});

console.log(data);
// {
// "records": [
// {
// "_id": "9FSAHWM9VV",
// "title": "Bonjour le Monde👋",
// "updatedAt": 1718096503886,
// "comments": [
// {
// "_id": "9FSAJF3GLG",
// "createdAt": 1718096509916,
// "comment": "这是一条评论"
// }
// ]
// }
// // ... 更多记录
// ],
// "total": 2
// }

查询过滤 filter

filter 参数用于指定查询条件,支持基础查询和关联查询两种方式。

基础查询 where

基础查询用于对主模型字段进行过滤:

const {
data
} = await models.post.list({
filter: {
where: {
// 标题包含"世界"
title: {
$search: "世界",
},
// 正文不为空
body: {
$nempty: true,
},
},
},
select: {
$master: true,
},
});

关联查询 relateWhere

关联查询用于根据关联模型的条件进行过滤:

const {
data
} = await models.post.list({
filter: {
// 查询有评论的文章
relateWhere: {
comments: {
where: {
comment: {
$nempty: true, // 评论内容不为空
},
},
},
},
where: {}, // 主模型查询条件
},
select: {
$master: true,
comments: {
comment: true,
},
},
});

组合查询示例

需要用到与或关系时,可以使用 where 参数的 $and$or 操作符

如果用到了 $and$or 操作符,需要将它们放在一个数组中:

const {
data
} = await models.post.list({
filter: {
where: {
$and: [{
// 标题包含"技术"或"教程"
$or: [{
title: {
$search: "技术"
}
},
{
title: {
$search: "教程"
}
}
]
},
{
// 创建时间在最近30天内
createdAt: {
$gte: Date.now() - 30 * 24 * 60 * 60 * 1000
}
},
{
// 状态为已发布
status: {
$eq: "published"
}
}
]
},
},
select: {
_id: true,
title: true,
createdAt: true,
status: true,
},
});

查询运算符

操作符说明示例
$eq等于{status: {$eq: "active"}}
$ne不等于{status: {$ne: "deleted"}}
$gt大于{score: {$gt: 80}}
$gte大于等于{age: {$gte: 18}}
$lt小于{price: {$lt: 100}}
$lte小于等于{discount: {$lte: 0.5}}
$in在数组中{category: {$in: ["tech", "news"]}}
$nin不在数组中{status: {$nin: ["deleted", "banned"]}}
$and逻辑与{$and: [{age: {$gte: 18}}, {status: {$eq: "active"}}]}
$or逻辑或{$or: [{priority: {$eq: "high"}}, {urgent: {$eq: true}}]}
$search模糊查询, 大小写敏感{status: {$search: "active"}}
$search_ci模糊查询, 大小写不敏感{status: {$search_ci: "active"}}
$nsearch查找不包含指定字符串值的记录, 大小写敏感{status: {$nsearch: "active"}}
$nsearch_ci查找不包含指定字符串值的记录, 大小写不敏感{status: {$nsearch_ci: "active"}}
$empty数据为 null{status: {$empty: true}}
$nempty数据不为 null{status: {$nempty: true}}

排序 orderBy

orderBy 参数用于指定查询结果的排序方式,支持多字段排序(最多3个字段)。

单字段排序

const {
data
} = await models.post.list({
filter: {
where: {},
},
orderBy: [{
createdAt: "desc", // 按创建时间倒序
}, ],
select: {
$master: true,
},
});

多字段排序

const {
data
} = await models.post.list({
filter: {
where: {},
},
orderBy: [{
featured: "desc", // 首先按推荐状态倒序
},
{
createdAt: "desc", // 然后按创建时间倒序
},
{
title: "asc", // 最后按标题升序
},
],
select: {
$master: true,
},
});

排序方向:

  • "asc": 升序排列
  • "desc": 降序排列

分页参数

pageSizepageNumber

用于实现分页查询:

const {
data
} = await models.post.list({
filter: {
where: {},
},
pageSize: 10, // 每页10条记录
pageNumber: 2, // 第2页(从1开始)
getCount: true, // 获取总数用于计算总页数
select: {
$master: true,
},
});

console.log(data);
// {
// "records": [...], // 第2页的10条记录
// "total": 156 // 总记录数
// }

// 计算总页数
const totalPages = Math.ceil(data.total / 10);

getCount

控制是否返回满足条件的记录总数:

const {
data
} = await models.post.list({
filter: {
where: {
status: {
$eq: "published"
}
},
},
getCount: true, // 设置为 true 时返回 total 字段
select: {
_id: true,
title: true,
},
});

console.log(data.total); // 满足条件的总记录数

完整查询示例

以下是一个包含所有参数的完整查询示例:

const {
data
} = await models.post.list({
// 字段选择
select: {
_id: true,
title: true,
excerpt: true,
createdAt: true,
updatedAt: true,
author: {
_id: true,
name: true,
avatar: true,
},
comments: {
_id: true,
content: true,
createdAt: true,
},
},

// 查询条件
filter: {
where: {
$and: [{
status: {
$eq: "published"
}
},
{
$or: [{
title: {
$search: "技术"
}
},
{
tags: {
$in: ["前端", "后端"]
}
}
]
},
{
createdAt: {
$gte: Date.now() - 7 * 24 * 60 * 60 * 1000 // 最近7天
}
}
]
},
relateWhere: {
comments: {
where: {
status: {
$eq: "approved"
} // 只查询已审核的评论
}
}
}
},

// 排序
orderBy: [{
featured: "desc"
},
{
createdAt: "desc"
}
],

// 分页
pageSize: 20,
pageNumber: 1,
getCount: true,
});

console.log("查询结果:", data.records);
console.log("总记录数:", data.total);
console.log("总页数:", Math.ceil(data.total / 20));

关联查询详解

按关联关系过滤

使用 relateWhere 可以根据关联模型的条件来过滤主模型:

// 查询有特定评论的文章
const {
data
} = await models.post.list({
filter: {
relateWhere: {
// 文章必须有评论
comments: {
where: {
$and: [{
content: {
$nempty: true
}
}, // 评论内容不为空
{
status: {
$eq: "approved"
}
}, // 评论已审核
{
rating: {
$gte: 4
}
} // 评论评分>=4
]
}
},
// 文章必须有标签
tags: {
where: {
name: {
$in: ["技术", "教程", "分享"]
}
}
}
},
where: {
status: {
$eq: "published"
}
}
},
select: {
$master: true,
comments: {
content: true,
rating: true,
status: true,
},
tags: {
name: true,
}
}
});

关联查询性能优化

  1. 精确选择字段:只选择需要的关联字段
  2. 合理使用关联过滤:避免过于复杂的关联条件
  3. 分页处理:对于大量关联数据使用分页
// 优化示例:只获取必要的关联数据
const {
data
} = await models.post.list({
filter: {
where: {
status: {
$eq: "published"
}
}
},
select: {
_id: true,
title: true,
excerpt: true,
// 只获取作者的基本信息
author: {
_id: true,
name: true,
},
// 只获取最新的3条评论
comments: {
_id: true,
content: true,
createdAt: true,
}
},
orderBy: [{
createdAt: "desc"
}],
pageSize: 10,
pageNumber: 1,
});

最佳实践

1. 字段选择优化

// ❌ 不推荐:查询所有字段
const {
data
} = await models.post.list({
select: {
$master: true
},
filter: {
where: {}
}
});

// ✅ 推荐:只选择需要的字段
const {
data
} = await models.post.list({
select: {
_id: true,
title: true,
excerpt: true,
createdAt: true,
},
filter: {
where: {}
}
});

2. 查询条件优化

// ✅ 推荐:使用索引字段进行查询
const {
data
} = await models.post.list({
filter: {
where: {
_id: {
$eq: "specific-id"
}, // 主键查询,性能最佳
status: {
$eq: "published"
}, // 索引字段
createdAt: {
$gte: timestamp
} // 时间范围查询
}
}
});

// ⚠️ 注意:模糊查询性能较差,谨慎使用
const {
data
} = await models.post.list({
filter: {
where: {
title: {
$search: "关键词"
} // 模糊查询,建议配合其他条件
}
}
});

3. 分页处理

// ✅ 推荐:合理的分页大小
const pageSize = 20; // 建议10-50之间
const pageNumber = 1;

const {
data
} = await models.post.list({
filter: {
where: {}
},
pageSize,
pageNumber,
getCount: true, // 获取总数用于分页计算
select: {
_id: true,
title: true,
createdAt: true,
}
});

// 计算分页信息
const totalPages = Math.ceil(data.total / pageSize);
const hasNextPage = pageNumber < totalPages;
const hasPrevPage = pageNumber > 1;

4. 错误处理

try {
const {
data
} = await models.post.list({
filter: {
where: {
status: {
$eq: "published"
}
}
},
select: {
_id: true,
title: true,
},
pageSize: 10,
pageNumber: 1,
getCount: true,
});

console.log("查询成功:", data);
} catch (error) {
console.error("查询失败:", error);
// 处理错误情况
}

通过合理使用这些查询参数,可以实现高效、灵活的数据查询操作,满足各种复杂的业务需求。