查看: 165|回复: 3

鸿蒙 uni-app x databaseForJQL 适配避坑

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
鸿蒙端为什么值得关注 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 边界和返回结构

基础入口只有一行:
  1. 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 替换检查:
  1. // uni-app x 中错误写法
  2. const db = uniCloud.database()
  3. // uni-app x 中正确写法
  4. const db = uniCloud.databaseForJQL()
复制代码

常用 CRUD 写法可以按场景拆开

最基础的列表查询是把 where 条件对象按 UTSJSONObject 传入,再链式调用 orderBy、limit 和 get:
  1. const db = uniCloud.databaseForJQL()
  2. const queryList = async () => {
  3.   const result = await db.collection('articles').where({
  4.     status: 'active'
  5.   } as UTSJSONObject).orderBy('createTime desc').limit(10).get()
  6.   console.log('查询结果:', result.data)
  7.   console.log('总数:', result.count)
  8. }
复制代码

按 ID 查询用 doc(id).get(),返回的 data 是数组,需要判断长度后再取 data[0]。条件查询用 db.command 操作符,例如 _.gt(100) 查阅读量大于 100 的文章。分页查询则组合 skip、limit 和 get,总页数用 Math.ceil(result.count / pageSize) 计算。

如果列表不需要全字段,可用 field 只返回指定字段,减少数据传输:
  1. const result = await db.collection('articles')
  2.   .where({ status: 'active' } as UTSJSONObject)
  3.   .field('title,author,createTime')
  4.   .orderBy('createTime desc')
  5.   .limit(10)
  6.   .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 中加载列表。核心列表加载逻辑可以收敛为下面这段:
  1. type ArticleItem = {
  2.   _id: string
  3.   title: string
  4.   author: string
  5.   status: string
  6.   createTime: number
  7. }
  8. const db = uniCloud.databaseForJQL()
  9. const articleList = ref([] as Array<ArticleItem>)
  10. const total = ref(0)
  11. const currentPage = ref(1)
  12. const pageSize = 10
  13. const totalPages = computed((): number => {
  14.   return Math.ceil(total.value / pageSize)
  15. })
  16. const loadList = async () => {
  17.   const skip = (currentPage.value - 1) * pageSize
  18.   const result = await db.collection('articles')
  19.     .where({ status: 'active' } as UTSJSONObject)
  20.     .field('_id,title,author,createTime')
  21.     .orderBy('createTime desc')
  22.     .skip(skip)
  23.     .limit(pageSize)
  24.     .get()
  25.   articleList.value = result.data as Array<ArticleItem>
  26.   total.value = result.count || 0
  27. }
复制代码

添加、更新、删除时,原文示例都配合 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 云函数替代方案和跨端操作符写法。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: 鸿蒙 uni-app x databaseForJQL 适配避坑

这个坑总结得挺到位的,尤其是 database() 改成 databaseForJQL() 这一条,我在老项目迁移的时候就是全局搜了一遍才发现还残留着几处,运行起来直接报错,排查了半天。建议大家在迁移前先把所有 uniCloud.database() 的调用点列出来,一次性改干净,比等到运行时一个个撞出来省事。 返回结构的对应关系也确实容易记混,data/count 是 get,total 是 count,updated、deleted、id 分别对应 update、remove、add,我一般会在项目里封一层薄封装,把常用查询和结果里的字段统一成固定的命名,后面写页面就不用每次翻文档确认了。另外 uts 里 where 条件的 as UTSJSONObject 真的别省,省了类型推导容易出问题,编辑器提示不明显,跑起来才暴露。 还有两个小提醒:doc(id).get() 返回的是数组,取 data[0] 之前一定要判长度,不然空数据下直接崩;field 只取需要的字段这个习惯值得养成,列表页尤其明显,传输量下来之后鸿蒙端的加载体感会好不少。至于 action 云函数换成数据库触发器,这块逻辑最好提前梳理一遍,触发器的调试链路和云函数不太一样,别等到上线前才动。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: 鸿蒙 uni-app x databaseForJQL 适配避坑

感谢楼主整理,这篇避坑挺到位的。之前从 uni-app 迁到 uni-app x 的时候,确实最容易在 uniCloud.database() 那里直接报错,一开始还以为是鸿蒙环境的问题,后来才发现是 API 边界变了,得统一换成 databaseForJQL()。 返回结构这块也很有同感,get() 用 data 和 count、count() 用 total、update() 用 updated、remove() 用 deleted、add() 用 id,这几个字段如果按旧项目习惯随便取,很容易拿到 undefined 还不报错,排查起来挺费劲。另外 doc(id).get() 拿到的 data 是数组而不是对象,这个第一眼也容易写错。 想请教两个点:一是你们在实际项目里,where 条件对象都是显式断言成 UTSJSONObject 吗,有没有遇到类型推断不友好的情况;二是 action 云函数改成数据库触发器之后,复杂业务逻辑是都塞进触发器,还是干脆再配合云对象来做,这两种在维护上你们觉得哪种更顺手。再次感谢分享,CRUD 页面那段拿来改改就能用了。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: 鸿蒙 uni-app x databaseForJQL 适配避坑

感谢楼主整理,鸿蒙端这块的迁移差异确实关键。我印象最深的是 uni-app x 里不能再用 uniCloud.database(),只能 databaseForJQL(),混用会直接报错;另外 action 云函数不再支持、要用数据库触发器替代,这两点迁移前就得先排查。CRUD 部分把返回结构列清楚很实用,比如 get 的 data/count、count 的 total、update 的 updated、remove 的 deleted、add 的 id,写页面时不容易取错。页面示例里用 script setup lang=uts、ref 和 computed 管列表与分页,配合 onMounted 加载、where 加 field 再 orderBy/skip/limit,以及 showLoading/showToast/try catch 和 showModal 二次确认,落地性挺强。想问下批量 multiSend 配 getTemp 在鸿蒙端有没有额外限制?分页的 total 用 result.count 在带 where 条件时也是筛选后的总数吧?整体很受用,先收藏了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-10-30 05:43 , Processed in 0.022897 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部