鸿蒙端为什么值得关注 databaseForJQL
在 uni-app x 里,uniCloud.databaseForJQL() 是客户端直接访问云数据库的 API,也叫 clientDB。它把增删改查、条件查询、排序、分页、聚合等能力放到客户端完成,开发者不必先写云函数或云对象。原文明确提到,鸿蒙 4.61 起开始支持 databaseForJQL,并且与云函数、云对象是同一批支持的能力。
对鸿蒙项目来说,真正需要先厘清的不是会不会写 where,而是迁移差异:uni-app x 不再支持 uniCloud.database(),只支持 uniCloud.databaseForJQL()。这是它与 uni-app 项目的重要区别,混用会直接报错。另外,uni-app x 不再支持 action 云函数,原文给出的替代方案是数据库触发器。
先确认 API 边界和返回结构
基础入口只有一行:
- const db = uniCloud.databaseForJQL()
复制代码
它返回 Database 实例。原文列出的能力范围包括 Database 属性与方法、Collection 方法、UniCloudDBFilter、UniCloudDBQuery 链式调用,以及 UniCloudDBGetResult、UniCloudDBCountResult、UniCloudDBUpdateResult、UniCloudDBRemoveResult 等返回类型。结合实际示例,get() 结果里常用 data 和 count,count() 结果里用 total,update() 结果里用 updated,remove() 结果里用 deleted,add() 结果里用 id。
迁移时要先做一次 API 替换检查:
- // uni-app x 中错误写法
- const db = uniCloud.database()
- // uni-app x 中正确写法
- const db = uniCloud.databaseForJQL()
复制代码
常用 CRUD 写法可以按场景拆开
最基础的列表查询是把 where 条件对象按 UTSJSONObject 传入,再链式调用 orderBy、limit 和 get:
- const db = uniCloud.databaseForJQL()
- const queryList = async () => {
- const result = await db.collection('articles').where({
- status: 'active'
- } as UTSJSONObject).orderBy('createTime desc').limit(10).get()
- console.log('查询结果:', result.data)
- console.log('总数:', result.count)
- }
复制代码
按 ID 查询用 doc(id).get(),返回的 data 是数组,需要判断长度后再取 data[0]。条件查询用 db.command 操作符,例如 _.gt(100) 查阅读量大于 100 的文章。分页查询则组合 skip、limit 和 get,总页数用 Math.ceil(result.count / pageSize) 计算。
如果列表不需要全字段,可用 field 只返回指定字段,减少数据传输:
- const result = await db.collection('articles')
- .where({ status: 'active' } as UTSJSONObject)
- .field('title,author,createTime')
- .orderBy('createTime desc')
- .limit(10)
- .get()
复制代码
更新、删除、添加分别对应 doc(id).update、doc(id).remove 和 add。批量操作则把条件放在 where 后面,再调用 update 或 remove;批量删除示例还用了 _.lt 组合 30 天前的时间条件。批量查询可以用 multiSend 配合 getTemp(),一次发送多个查询并按下标读取结果。
鸿蒙端页面的落地重点
原文给出的完整 CRUD 页面包含添加、查询、更新、删除和分页,使用 script setup lang=uts,定义 ArticleItem 类型,用 ref 保存 articleList、total、currentPage,用 computed 计算 totalPages,并在 onMounted 中加载列表。核心列表加载逻辑可以收敛为下面这段:
- type ArticleItem = {
- _id: string
- title: string
- author: string
- status: string
- createTime: number
- }
- const db = uniCloud.databaseForJQL()
- const articleList = ref([] as Array<ArticleItem>)
- const total = ref(0)
- const currentPage = ref(1)
- const pageSize = 10
- const totalPages = computed((): number => {
- return Math.ceil(total.value / pageSize)
- })
- const loadList = async () => {
- const skip = (currentPage.value - 1) * pageSize
- const result = await db.collection('articles')
- .where({ status: 'active' } as UTSJSONObject)
- .field('_id,title,author,createTime')
- .orderBy('createTime desc')
- .skip(skip)
- .limit(pageSize)
- .get()
- articleList.value = result.data as Array<ArticleItem>
- total.value = result.count || 0
- }
复制代码
添加、更新、删除时,原文示例都配合 uni.showLoading、uni.showToast 和 try/catch 做反馈与异常处理。编辑和删除前用 uni.showModal 二次确认,更新成功后重新 loadList。分页按钮通过 currentPage 与 totalPages 判断禁用状态。这些做法适合直接作为鸿蒙端管理列表页的骨架。
排障与选型:别把客户端数据库当成万能层
原文列出三类容易踩的点。第一,不能在 uni-app x 中继续使用 uniCloud.database(),只能使用 databaseForJQL()。第二,Android 非蒸汽模式存在限制:不支持泛型传递、不支持 getOne、不支持 db.command.aggregate、不支持 db.command.xxx 链式调用;原文明确鸿蒙平台没有这些限制。第三,操作符链式调用本身也有注意点,原文踩坑部分提示可改用数组写法,跨端复用代码时应重点验证这部分。
选型上,客户端数据库与 callFunction 云函数都能操作数据库。客户端数据库省去云函数开发,一个 where().get() 就能完成查询;复杂业务逻辑仍然应该放在云函数或云对象中。与鸿蒙原生开发自行对接云服务 SDK、处理 HTTP 请求和序列化相比,databaseForJQL 把请求细节收进了 API 内部,适合鸿蒙端 uni-app x 项目快速实现数据层,但迁移时必须同步检查 API 名称、action 云函数替代方案和跨端操作符写法。 |