- 云函数代码问题(数据库导入导出)?
/* eslint-disable */ const request = require('request'); const cloud = require('wx-server-sdk'); // 环境变量 const env = 'xxxx'; cloud.init({ env }); // 换取 access_token async function getAccessToken(appid, secret) { return new Promise((resolve, reject) => { request.get( `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${secret}`, (err, res, body) => { if (err) { reject(err); return; } resolve(JSON.parse(body)); } ); }); } // 创建导出任务 async function createExportJob(accessToken, collection) { const date = new Date().toISOString(); return new Promise((resolve, reject) => { request.post( `https://api.weixin.qq.com/tcb/databasemigrateexport?access_token=${accessToken}`, { body: JSON.stringify({ env, file_path: `${date}.json`, file_type: '1', query: `db.collection("${collection}").get()` }) }, (err, res, body) => { if (err) { reject(err); } resolve(JSON.parse(body)); } ); }); } // 查询导出任务状态 async function waitJobFinished(accessToken, jobId) { return new Promise((resolve, reject) => { // 轮训任务状态 const timer = setInterval(() => { request.post( `https://api.weixin.qq.com/tcb/databasemigratequeryinfo?access_token=${accessToken}`, { body: JSON.stringify({ env, job_id: jobId }) }, (err, res, body) => { if (err) { reject(err); } const { status, file_url } = JSON.parse(body); console.log('查询'); if (status === 'success') { clearInterval(timer); resolve(file_url); } } ); }, 500); }); } exports.main = async (event, context) => { // 从云函数环境变量中读取 appid 和 secret 以及数据集合 const { appid, secret, backupColl, backupInfoColl } = process.env; const db = cloud.database(); try { // 获取 access_token const { errmsg, access_token } = await getAccessToken(appid, secret); if (errmsg && errcode !== 0) { throw new Error(`获取 access_token 失败:${errmsg}` || '获取 access_token 为空'); } // 导出数据库 const { errmsg: jobErrMsg, errcode: jobErrCode, job_id } = await createExportJob(access_token, backupColl); // 打印到日志中 console.log(job_id); if (jobErrCode !== 0) { throw new Error(`创建数据库备份任务失败:${jobErrMsg}`); } // 将任务数据存入数据库 const res = await db.collection('db_back_info').add({ data: { date: new Date(), jobId: job_id } }); // 等待任务完成 const fileUrl = await waitJobFinished(access_token, job_id); console.log('导出成功', fileUrl); // 存储到数据库 await db .collection(backupInfoColl) .doc(res._id) .update({ data: { fileUrl } }); } catch (e) { throw new Error(`导出数据库异常:${e.message}`); } };我想走这段代码env为环境变量但是走不了,会被抓到错误。不知道是不是代码写的有问题
2019-08-20 - 小程序备案有很多不明白的地方,有没有关于小程序备案客服的电话,想相关咨询一下?
麻烦知道的宝子们,在线提供一下,谢谢!或者平台的在线客服都帮帮忙,谢谢!感谢家人们!
2023-12-26 - APP可以和小程序共用微信的云数据库吗?
因为一些功能在小程序里无法实现,所以需要开发移动端APP进行补充,看了一些文档,貌似可以使用服务端api进行实现,只是需要管理access token,很多内容不太了解。所以有下几个问题需要确认: 1、为了降低开发周期,确保APP和小程序的数据、内容、功能等实时同步,APP是否可以和小程序共用微信云数据库? 2、如果可以共用,是否有并发数、延时或功能权限的差异或限制? 3、如果不可以,是否有其他的解决方案? 新手小白,没有开发过APP,请各位大神指点。
2022-05-08 - 营业执照变更了法人,小程序怎么备案?
11月份营业执照变更了法人,小程序还是原来的信息,现在想备案,该怎么操作?
2023-12-06 - 云函数线上环境new Date() 有时差的问题 请问如何解决?
环境变量肯定是设置了的: [图片] 代码是这样的: [图片] 执行结果是这样的: [图片] 日期不对 但是时间戳又是对的。我都蒙了 为什么会这样? 我存数据库字段的时候 用的是 db.serverDate()。所以我查询的时候 要传递时间对象进去。好像查询却是对的? 请问大佬们 我要怎么写才对呢?
2022-06-16 - 云函数中如何根据a字段[number]大于等于(当前日期-b字段[更新日期])更新c字段?
已解决 数据举例: { showDay:3, updateDate:Tue Jan 19 2021 08:00:01 GMT+0800 (中国标准时间) flag:1 } 需求: showDay 大于等于 (现在时间减去updateDate除以86400000)的数据,flag更新为0。 问题: .where中使用$.divide([($.subtract([currentTime, '$updateDate'])),86400000])无效。 代码: .where({ showDay:_.gte($.divide([($.subtract([currentTime,'$updateDate'])),86400000])) }) 是因为$.是在聚合阶段使用的原因吗? 但如果.aggregate()后如何update呢? 试了很久都没有成功,特来求助。 感谢各位。 ---------------------------- 有时候思路会陷入自己的预设,不能break。 为什么一定要在aggregate以后update呢?它本身就不是update的前置条件呀。 所以一定是在update之前筛选出数据,而不是聚合数据。 所以,如下: .where( _.expr( $.eq(["$goodsFlag","1"]), $.gte([("$showDay"),($.divide([($.subtract([currentTime,'$updateDate'])),86400000]))]) ) )
2021-01-26 - 使用group查询的数据不全,该怎么补全呢?
我现在接上次的group的统计问题,假设我要统计过去30天每一天的订单量,这时候通过时间条件判断以及group的强大功能,终于查出了数据,但是,发现一个问题,若某一天数据为空,这一天的数据就查询不到了,例如下图,我要查询11月12号前30天的数据,但是只显示4天的数据,我怎么把前几天的数据补齐呢?有没有简单一点的办法呢? [图片]
2019-11-12 - 云函数写md5加密?(已解决)
[图片] index.js? [sm]:37 Error: cloud.callFunction:fail Error: errCode: -504002 functions execute fail | errMsg: Runtime.ImportModuleError: Error: Cannot find module '../getsetzcm/md5.js' 请问错在哪里么?谢谢。 在需要使用到的云函数安装npm install md5..... --------------
2022-11-23 - 云函数调用startTransaction()启用数据库事务,部署后调用失败的原因?
云函数调用startTransaction()引用数据库事务,安装"wx-server-sdk": "^1.7.0,云函数本地调试可以成功调用。 但上传并部署(所有文件)调用则报错,请问什么原因? {"errorCode":1,"errorMessage":"user code exception caught","stackTrace":"transaction is not defined\nReferenceError: transaction is not defined\n at EventHandler.exports.main [as realHandler] (/var/user/index.js:92:5)\n at \u003canonymous\u003e\n at process._tickCallback (internal/process/next_tick.js:188:7)"}
2019-12-26 - 同样的代码,云函数中使用where语句查询数据,导出excel表中无数据,不使用where则有数据?
代码1:使用where查询 // 云函数入口文件 const cloud = require('wx-server-sdk'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境 const xlsx = require('node-xlsx'); let db = cloud.database(); const comd = db.command; // 云函数入口函数 exports.main = async (event, context) => { try{ //let userdata = await db.collection('Data_cj').get(); let start_time = event.start; let end_time = event.end; let khbm = event.khbm; let userdata; if(khbm == ""){ userdata = await db.collection('Data_cj').where({ cj_pdrq:comd.gte(start_time).and(comd.lte(end_time)) }).get(); }else{ userdata = await db.collection('Data_cj').where({ cj_pdrq:comd.gte(start_time).and(comd.lte(end_time)), cj_khbm:khbm, }).get(); } console.log(userdata); //定义excel表格名 let dataCVS ='test.xlsx'; let alldata = []; //表属性 let row = ['客户姓名','客户编码','商品条码','商品包码','商品名称','单包零售价格','条装零售价格','市场批发价','订货电话','经营地址','盘点日期','当前库存量','断货天数']; alldata.push(row); console.log(alldata); for(let i=0;i<userdata.data.length;i++){ let arr =[]; let key="data"; arr.push(userdata[key][i].cj_khxm); arr.push(userdata[key][i].cj_khbm); arr.push(userdata[key][i].cj_tiaoma); arr.push(userdata[key][i].cj_baoma); arr.push(userdata[key][i].cj_spmc); arr.push(userdata[key][i].cj_dbjg); arr.push(userdata[key][i].cj_tzjg); arr.push(userdata[key][i].cj_pfjg); arr.push(userdata[key][i].cj_dhdh); arr.push(userdata[key][i].cj_jydz); arr.push(userdata[key][i].cj_pdrq); arr.push(userdata[key][i].cj_dqkc); arr.push(userdata[key][i].cj_dhts); alldata.push(arr); }; console.log(alldata); //把数据保存到excel let buffer = await xlsx.build([ { name:"test", data:alldata } ]); //把excel文件保存到云存储里 return await cloud.uploadFile({ cloudPath:dataCVS, fileContent:buffer,//excel二进制文件 }) }catch(e){ console.error(e); return e; } } 代码2:不使用where查询 // 云函数入口文件 const cloud = require('wx-server-sdk'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) // 使用当前云环境 const xlsx = require('node-xlsx'); let db = cloud.database(); const comd = db.command; // 云函数入口函数 exports.main = async (event, context) => { try{ let userdata = await db.collection('Data_cj').get(); // let start_time = event.start; // let end_time = event.end; // let khbm = event.khbm; // let userdata; // if(khbm == ""){ // userdata = await db.collection('Data_cj').where({ // cj_pdrq:comd.gte(start_time).and(comd.lte(end_time)) // }).get(); // }else{ // userdata = await db.collection('Data_cj').where({ // cj_pdrq:comd.gte(start_time).and(comd.lte(end_time)), // cj_khbm:khbm, // }).get(); // } console.log(userdata); //定义excel表格名 let dataCVS ='test.xlsx'; let alldata = []; //表属性 let row = ['客户姓名','客户编码','商品条码','商品包码','商品名称','单包零售价格','条装零售价格','市场批发价','订货电话','经营地址','盘点日期','当前库存量','断货天数']; alldata.push(row); console.log(alldata); for(let i=0;i<userdata.data.length;i++){ let arr =[]; let key="data"; arr.push(userdata[key][i].cj_khxm); arr.push(userdata[key][i].cj_khbm); arr.push(userdata[key][i].cj_tiaoma); arr.push(userdata[key][i].cj_baoma); arr.push(userdata[key][i].cj_spmc); arr.push(userdata[key][i].cj_dbjg); arr.push(userdata[key][i].cj_tzjg); arr.push(userdata[key][i].cj_pfjg); arr.push(userdata[key][i].cj_dhdh); arr.push(userdata[key][i].cj_jydz); arr.push(userdata[key][i].cj_pdrq); arr.push(userdata[key][i].cj_dqkc); arr.push(userdata[key][i].cj_dhts); alldata.push(arr); }; console.log(alldata); //把数据保存到excel let buffer = await xlsx.build([ { name:"test", data:alldata } ]); //把excel文件保存到云存储里 return await cloud.uploadFile({ cloudPath:dataCVS, fileContent:buffer,//excel二进制文件 }) }catch(e){ console.error(e); return e; } } 不使用where查询则导出excel有数据: [图片] 使用where查询则导出excel无数据: [图片] 同样的查询条件,不知道为什么会这样,请各位大神协助,不胜感激!
2023-06-28 - 如何突破一次只能获取20条记录的limit限制?只需要一行代码。
笔者刚遇到需要一次性拉取超过100条(云函数里超过1000条)记录的这种需求。 一般情况下,会有下面两种处理方式: 1、先获取总数,再for循环,每次拉取limit条记录;(可结合Promise.all并发) 2、递归拉取,每次拉取limit条记录,直到拉取的记录数量小于limit。 以上两种方式都比较麻烦,于是动了一脑筋,以最简单的方式实现上面的需求。 极简代码如下: db.collection('order').aggregate() .match({ status:'已付费' }) .addFields({ tempTag:1 //增加一个临时标签;也可以不要addFields这个阶段; }) .group({ _id:'$tempTag', orders:$.push('$$ROOT') //一次性拉取超过100条或者1000条记录 }) .end() .then(res=>{ let orders = res.list[0].orders console.log(orders) }) 一个临时标签,搞定。 小心数据量太大搞崩了,崩溃的极限是多少,需要各位自行摸索了。 需要注意的是,如果是云函数里执行以上代码(比如lookup),返回小程序端的数据量不要超过1M。
2021-03-15 - fileSystemManager.saveFile保存的文件在哪里能找到?
场景是:在小程序中下载docx,并且客户需要拿到这个文件,后续去转发或者打印。 现在找不到这个文件。 请问需要怎么做才能找到这个文件。
2019-09-11 - 基础库超过2.30.2以上的就报unexpected loadSdkSubPackage case?
工具是最新的1.06版本 只要超过2.30.2基础库 就会 报一下的错 2.30.2版本 组件有问题 每次修改组件都有强制刷新工具 [图片][图片]
2023-04-27 - 首页模拟隐私弹窗
官方demo1基础上改的,用模拟隐私接口,省得还要配置,甚至后台开通的接口。复制到实际应用中,再改成用到的接口。 然后还用了手机号获取的按钮,这个不需要审核,体验方便些。 [图片] 有人担心拒绝后,后续无法再调涉及隐私的接口: [图片] 其实拒绝是需要调用api来设置的,你不要设置就好啦。没调用过不同意的api,后续其他时机再同意隐私后,就能用啦。 // this.resolvePrivacyAuthorization({ event:'disagree' }); 如果通过按钮类型的隐私接口来触发回调,会有bug。你等同意隐私后再点获取手机号按钮,会报频繁使用的错误。实际应用中,就都用模拟接口来触发隐私弹窗,同意后在回调里使用具体api,或者引导用户点击按钮。 [图片]
2023-08-25 - 一个组件解决隐私授权:小程序用户隐私保护授权弹窗组件
项目链接:https://github.com/94xy/miniprogram-privacy 效果预览: [图片] 使用方法: 1、复制项目 [代码]component[代码] 文件夹中的 [代码]privacy[代码] 文件夹到小程序项目中的组件目录; 2 、在 page.json 中引入组件 { "usingComponents": { "Privacy": "/component/privacy/privacy" } } 3 、在 page.wxml 中使用组件,需要授权显示弹窗,不需要不显示 <Privacy /> 4 、可以在所有使用了隐私接口的页面都加上该组件,授权一次之后使用所有隐私接口不再需要授权 跳过阅读: 可以不阅读就点击“同意”按钮 <Privacy skipRead="{{true}}" /> 流程: 页面显示时使用 wx.getPrivacySetting 接口查询是否需要授权,需要授权则显示组件;用户点击“拒绝”直接退出小程序,用户点击“同意”关闭弹窗并同步给微信,之后可以正常使用所有隐私接口。 注意事项: 2023 年 9 月 15 号之前,默认不会启用隐私相关功能,所以检测不到需要弹窗的情况,可以在 app.json 中配置 "__usePrivacyCheck__": true 之后,接口才可以检测到是否需要弹窗。个人实际情况:我在开发者工具中配置了 "__usePrivacyCheck__": true ,needAuthorization 无论如何返回的都是 false,但在真机模拟的情况下可以返回 true自动打开隐私保护指引界面需在「小程序管理后台」配置《小程序用户隐私保护指引》,官方用户隐私保护指引填写说明。 取消授权: 微信中「微信下拉-最近-最近使用的小程序」中删除小程序可取消授权。 开发者工具中「清除模拟器缓存-清除授权数据」可取消授权。
2023-08-28 - Skyline|长列表也可以丝滑~
[图片] [图片] 对于长列表出现的白屏、卡顿、界面跳动等问题,小程序提供了新 scroll-view 来解决这一系列问题。我们先来看看效果~ 快速滚动效果对比我们通过一组长列表来展示新旧 scroll-view 在快速滚动下的效果对比。 当长列表快速滚动时,旧 scroll-view 容易出现白屏的情况,新 scroll-view 则不会出现白屏。 左:旧 scroll-view、右:新 scroll-view [视频] 在安卓机器快速滚动过程中,旧 scroll-view 反应卡顿,容易出现手指离开操作时,滚动动画还在进行。 而新 scroll-view 则可以保持界面滚动效果跟随手指,停止滚动则缓慢结束动画效果。 左:旧 scroll-view、右:新 scroll-view ,测试机型:Xiaomi MIX 3 [视频] 反向滚动效果对比在对话等场景下,反向滚动是常见的功能,旧 scroll-view 并没有提供反向滚动的能力,我们来看看旧 scroll-view 下是怎么完成反向滚动的~ 在对话数据在加载的时候,对话列表需要在更新完列表数据之后,再使用 scroll-into-view 或者 scroll-top 来保持当前滚动位置,因为设置滚动位置会有延迟,所以容易出现 界面跳动 的情况。 // .js // scroll-view 滚动到顶部时触发 bindscrolltoupper() { // 先更新列表数据 this.setData({ recycleList: getnewList() }, () => { // 更新完数据后再设置滚动位置 this.setData({ scrollintoview: scrollintoview }) }) } 为了解决界面跳动的问题,社区上也有通过翻转的方法来解决,将 scroll-view 与 scroll-view 的子元素进行翻转。 // .wxss .reserve { transform: rotateX(180deg); } // .wxml 然而进行翻转之后,会遇到手指滚动方向与列表滚动方向相反、scroll-into-view 属性无效等问题。 为了帮开发者们解决反向滚动类列表的一系列问题,新 scroll-view 直接提供了 reverse 属性支持反向滚动的能力,滚动效果更加顺滑。 左:旧 scroll-view、右:新 scroll-view(图片加载期间,GIF 渲染较慢) [视频] 怎么接入新 scroll-view ?新的 scroll-view 使用起来很简单,主要有以下两个步骤: 修改小程序配置scroll-view 增加 type="list"// app.json // "renderer": "skyline" 开启之后所有页面会变成自定义导航,可参考 https://developers.weixin.qq.com/s/Y5Y8rrm37qEY 实现自定义导航 // 也可在 page.json 中配置 "renderer": "skyline" 逐个页面开启 { ... "lazyCodeLoading": "requiredComponents", "renderer": "skyline" } // page.json { ... "disableScroll": true, "navigationStyle": "custom" } // page.wxml ... // 反向滚动 新的 scroll-view 从安卓 8.0.28 / iOS 8.0.30 开始支持,如需兼容低版本需要进行兼容处理。 wx.getSkylineInfo({ success(res) { if (res.isSupported) { // 使用新版 scroll-view } else { // 使用旧版 scroll-view } } }) 如需体验长列表效果,可在微信开发者工具导入该代码片段即可体验:https://developers.weixin.qq.com/s/Y5Y8rrm37qEY 更多接入详情请参考文档 怎么做到的?大家肯定好奇为什么新 scroll-view 可以解决这个头疼的问题呢? 我们来对比一下新旧 scroll-view 有什么区别就可以知道答案啦~ 旧 scroll-view 逻辑层与渲染层的通信需要通过 JSBridge 进行转换,需要一定的时间开销渲染采用异步分块光栅化,当渲染赶不上滚动的速度,来不及渲染则会出现白屏渲染大量节点内存占用高,需要开发者自行优化只渲染在屏节点,开发成本高新 scroll-view 逻辑层与渲染层的通信无需通过 JSBridge 进行转换,减少了大量通信时间开销渲染采用同步光栅化,滚动与渲染在同一线程,不会出现白屏针对长列表进行优化,只渲染在屏节点,内存占用低,减少了一些渲染耗时,且开发接入成本低[图片] 除此之外,新 scroll-view 后续将提供 type="custom" 支持 sticky 吸顶效果、网格布局、瀑布流布局等能力便于开发者接入使用~
2023-08-03 - 云函数中如何关联2张表查询组合数据?
- 假如我有2张表 A和B,A存储了杂货店的上架商品,B存储了杂货店每种商品的价格,并且使用键值goods_id存储着上架商品的ID。 那么我想一次性查询出上架商品和其对应的价格,组在一个json给小程序返回,这个操作在云函数中怎么操作? 使用return总是拿不到值,可能是异步的问题? - 求各位大侠帮忙看看,怎么写呢?
2018-11-01 - 最佳实践丨云数据库实现联表+聚合查询
聚合是云开发 CloudBase 数据库中非常重要的一种数据批处理操作方式。聚合操作可以将数据分组(或者不分组,即只有一组/每个记录都是一组),然后对每组数据执行多种批处理操作,最后返回结果。 有了聚合能力,可以方便的解决很多没有聚合能力时无法实现或只能低效实现的场景,包括分组查询、只取某些字段的统计值或变换值返回、流水线式分阶段批处理、获取唯一值(去重)等。 本文就以一个简单的实例解释如何在云数据库中,实现十分常用的联表+聚合查询操作。 场景说明假设数据库内存在两个集合:[代码]class[代码] 与 [代码]student[代码],存在以下数据: class(班级信息): [图片] student(学生信息): [图片] 现在需要查询徐老师所带的班级里面所有学生的平均成绩。 代码示例1、lookup 联表查询首先我们需要把 student 内的所有数据,按照 class_id 进行分组,这里我们使用云数据库的 lookup 操作符: lookup({ from: "student", //要关联的表student localField: "id", //class表中的关联字段 foreignField: "class_id", //student表中关联字段 as: "stu" //定义输出数组的别名 }).end(); 这个语句会查出来下面的结果,会查出班级的信息以及该班级所对应的所有学生的信息: {"list": [{ "id":1, "teacher":"王老师", "cname":"一班", "stu":[ { "sname":"宁一", "class_id":1, "score":90 } ] }, { "id":2, "teacher":"徐老师", "cname":"二班", "stu":[ { "class_id":2, "sname":"张二", "score":100 }, { "class_id":2, "sname":"李二", "score":80 } ] }] } 但是我们只需要徐老师所在班级学生的数据,所以需要进一步过滤。 2、match 条件匹配现在就只是返回徐老师所在班级的学生数据了,学生数据在 stu 对应的数组里面: .lookup({ from: 'student', localField: 'id', foreignField: 'class_id', as: 'stu' }) .match({ teacher:"徐老师" }) .end() 现在就只是返回徐老师所在班级的学生数据了,学生数据在 stu 对应的数组里面: { "list": [ { "_id": "5e847ab25eb9428600a512352fa6c7c4", "id": 2, "teacher": "徐老师", "cname": "二班", //学生数据 "stu": [ { "_id": "37e26adb5eb945a70084351e57f6d717", "class_id": 2, "sname": "张二", "score": 100 }, { "_id": "5e847ab25eb945cf00a5884204297ed8", "class_id": 2, "sname": "李二", "score": 80 } ] } ] } 接下来我们继续优化代码,直接返回学生的平均分数。 3、直接返回学生成绩平均值如果想要在被连接的表格中(本课程中的 student)做聚合操作,就用 pipeline 方法: .lookup({ from: 'student', pipeline: $.pipeline() .group({ _id: null, score: $.avg('$score') }) .done(), as: 'stu' }) .match({ teacher:"徐老师" }) .end() 现在输出的数据是这样的: { "list": [ { "_id": "5e847ab25eb9428600a512352fa6c7c4", "id": 2, "teacher": "徐老师", "cname": "二班", "stu": [{ "_id": null, "score": 90 }] } ] } 但是现在输出的数据有点复杂,如果只想显示 teacher 和 score 这两个值,我们再进行下面的操作。 4. 只显示 teacher 和 score 这两个值我们使用 replaceRoot、mergeObjects 和 project 进行最后的处理: .lookup({ from: 'student', pipeline: $.pipeline() .group({ _id: null, score: $.avg('$score') }) .done(), as: 'stu' }) .match({ teacher:"徐老师" }) .replaceRoot({ newRoot: $.mergeObjects([$.arrayElemAt(['$stu', 0]), '$$ROOT']) }) .project({ _id:0, teacher:1, score:1 }) .end() 现在输出的数据是这样的: { "list": [{ "score": 90, "teacher": "徐老师" }] } 相关文档:云开发聚合搜索:https://docs.cloudbase.net/database/aggregate.html 产品介绍云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等serverless化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。 开通云开发:https://console.cloud.tencent.com/tcb?tdl_anchor=techsite 产品文档:https://cloud.tencent.com/product/tcb?from=12763 技术文档:https://cloudbase.net?from=10004 技术交流加Q群:601134960 最新资讯关注微信公众号【腾讯云云开发】
2021-04-08 - 如何使用数据库聚合match过滤$.and
我需要在云函数中查询数据库,聚合计算一个人的某月1-31号的消费金额: [代码]let queryFeeSum = await db[代码][代码] [代码][代码].collection([代码][代码]'lunch'[代码][代码])[代码][代码] [代码][代码].aggregate()[代码][代码] [代码][代码].match({[代码][代码] [代码][代码]eno: eno,[代码][代码] [代码][代码]date: $.and([$.gte([[代码][代码]'$date'[代码][代码], dateNumRange.begin]), $.lte([[代码][代码]'$date'[代码][代码], dateNumRange.end])])[代码][代码] [代码][代码]})[代码][代码] [代码][代码].group({[代码][代码] [代码][代码]_id: [代码][代码]null[代码][代码],[代码][代码] [代码][代码]fee: $.sum([代码][代码]'$goodsPrice'[代码][代码])[代码][代码] [代码][代码]})[代码][代码] [代码][代码].end()[代码]date是数值型:它的值是8位整数,如20190701、20190728 上面的 $.and 语句按文档中的写法,聚合这个功能也是官方开发出来不久,找不到相关帮助文档。 运行报错,查看日志提示: {"errorCode":1,"errorMessage":"user code exception caught","stackTrace":"errCode: -502001 database request fail | errMsg: [FailedOperation] (BadValue) unknown operator: $and; "} 请问一下,为什么提示操作失败,无效的值、未知的操作器$and。
2019-07-28 - 【笔记】云开发聚合实现分页,涉及跨表查询、逻辑计算、判断权限、数据格式化、限制输出
背景: 之前不会用聚合,因此把数据库结构分为了用户表、帖子表、喜欢表。小程序端请求一次列表,要根据帖子列表,循环查询用户表,并且还要做一系列的逻辑运算处理,计算当前帖子的权限、是否喜欢过、喜欢人数、是否有这个帖子管理权限等信息。 这样做有很多弊端: 处理速度慢,资源耗费严重,循环查询肯定慢且耗费资源,一个列表需要21次查询。需要写大量逻辑处理代码,如计算管理权限,喜欢数量、当前用户是否喜欢,格式处理等等。于是使用聚合进行了优化: 跨表查询数据格式化逻辑计算,权限判断、是否喜欢等数据统计,喜欢总人数权限判断,是否为管理员限制输出效果: 之前:上百行代码,多次查询,需要单独判断函数,处理时间在3000ms以上之后:几行代码,一次查询,直接查询时算出结果,处理时间在300ms以内 数据库结构 [图片] 代码实现: const { OPENID } = cloud.getWXContext(context) //构建查询条件 let query = null switch (Number(event.listType)) { case 0: query = db.collection('post').aggregate() .match({ //0我的 '_openid': OPENID }) .sort({ createTime: -1 }) .skip(20 * (event.pageNum - 1)) .limit(20) break; case 1: //1 随机 query = db.collection('post').aggregate() .match({ public: true, // feeling: _.gte(50) }) .sample({ size: 20 }) break; case 2: query = db.collection('post').aggregate() .match({ //2喜欢 likes: _.all([OPENID]) }) .sort({ createTime: -1 }) .skip(20 * (event.pageNum - 1)) .limit(20) break; case 4: query = db.collection('post').aggregate() .match({ //4指定 _id: event.id }) .sort({ createTime: -1 }) .skip(20 * (event.pageNum - 1)) .limit(20) break; } //使用聚合处理后续数据 let listData = await query .lookup({ from: "user", localField: "_openid", foreignField: "_id", as: "postList" })//联表查询用户表 .replaceRoot({ newRoot: $.mergeObjects([$.arrayElemAt(['$postList', 0]), '$$ROOT']) })//将用户表输出到根节点 .addFields({ day: $.dayOfMonth('$createTime'), month: $.month('$createTime'), year: $.year('$createTime'), isLike: $.in([OPENID, '$likes']), //是否喜欢 isLiked: $.in([OPENID, '$liked']), //是否喜欢过 isAdmin: $.eq([OPENID, 'oy0T-4yk7lCRFGDefpFC4Yvx_ppU']),//是否管理员 isAuthor: $.eq(['$_openid', OPENID]),//是否为作者 like: $.size('$likes'), //喜欢该帖子数 face: $.switch({ branches: [ { case: $.gte(['$feeling', 90]), then: 9 }, { case: $.gte(['$feeling', 80]), then: 8 }, { case: $.gte(['$feeling', 70]), then: 7 }, { case: $.gte(['$feeling', 60]), then: 6 }, { case: $.gte(['$feeling', 50]), then: 5 }, { case: $.gte(['$feeling', 40]), then: 4 }, { case: $.gte(['$feeling', 30]), then: 3 }, { case: $.gte(['$feeling', 20]), then: 2 }, { case: $.gte(['$feeling', 10]), then: 1 } ], default: 0 }) //根据心情值判断对应表情 }) .project({ postList: 0, userInfo: 0, liked: 0, likes: 0, city: 0, province: 0, country: 0, language: 0, nlp: 0, saveType: 0, }) //清楚掉不需要的数据 .end() return listData
2020-05-26 - 小程序防止重复点击或重复触发事件
可设置全局变量和全局函数,直接使用app唯一实例调用,方便快捷。 在app.js下 App({ globalData: { PageActive: true }, preventActive (fn) { const self = this if (this.globalData.PageActive) { this.globalData.PageActive = false if (fn) fn() setTimeout(() => { self.globalData.PageActive = true }, 1500); //设置该时间内重复触发只执行第一次,单位ms,按实际设置 } else { console.log('重复点击或触发') } } }) 其他page下调用 index.wxml <button bindtap="tap">点击</button> index.js Page({ tap (e) { getApp().preventActive(()=>{ //code... }) } })
2021-01-12 - Cannot find module 'wx-server-sdk
简单尝试下云函数 [代码]'use strict'[代码][代码];[代码][代码]const cloud = require([代码][代码]'wx-server-sdk'[代码][代码]);[代码][代码]cloud.init({[代码][代码] [代码][代码]env: [代码][代码]'demo'[代码][代码]});[代码][代码]exports.main = (event, context, callback) => {[代码] [代码] [代码][代码]try[代码] [代码]{[代码][代码] [代码][代码]db.collection([代码][代码]'user'[代码][代码]).add({[代码][代码] [代码][代码]data: {[代码][代码] [代码][代码]username: [代码][代码]"learn cloud database"[代码][代码],[代码][代码] [代码][代码]password: [代码][代码]"www"[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]} [代码][代码]catch[代码] [代码](e) {[代码][代码] [代码][代码]console.error(e)[代码][代码] [代码][代码]}[代码][代码] [代码][代码]var[代码] [代码]num1 = parseInt(event.a);[代码][代码] [代码][代码]var[代码] [代码]num2 = parseInt(event.b);[代码][代码] [代码][代码]var[代码] [代码]result=num1+num2;[代码][代码] [代码][代码]event.sum=result;[代码][代码] [代码][代码]console.log([代码][代码]"key:"[代码] [代码]+ event.a);[代码][代码] [代码][代码]console.log([代码][代码]"Hello World"[代码][代码])[代码][代码] [代码][代码]console.log(event)[代码][代码] [代码][代码]console.log(event[[代码][代码]"non-exist"[代码][代码]])[代码][代码] [代码][代码]console.log(context);[代码][代码] [代码][代码]event.msg=[代码][代码]"hello"[代码][代码];[代码][代码] [代码][代码]callback([代码][代码]null[代码][代码], event);[代码][代码]};[代码] 运行的时候出现 返回结果: {"errorCode":10004,"errorMessage":"user code exception caught","stackTrace":"Cannot find module 'wx-server-sdk'"}
2018-09-11 - 【笔记】云开发中的聚合aggregate和数据查询get简单对比
背景 在我开发在线答题小程序的过程中,会经常使用到聚合aggregate和数据查询get,比如从题库抽题、付费解锁、排行榜等。 聚合aggregate和数据查询get时不同的两套体系,聚合更偏向于数据的统计分析。 由于聚合和数据查询都能对数据库进行查询,而且两个的很多方法都特别类似,所以我刚开始的时候会混淆,甚至错误的混用,比如会在aggregate()加where条件、get请求,这里为了让自己更好理解,特整理一下两个的对比,我在写数据库查询和聚合时都会先写类似以下的模板。 普通数据查询 const db = wx.cloud.database() //获取数据库的引用 const _ = db.command //获取数据库查询及更新指令 db.collection("question") //获取集合china的引用 .where({ //查询的条件指令where create_time: _.gt(1598580712652) //查询筛选条件,gt表示字段需大于指定值。 }) .field({ //显示哪些字段 _id:false, //默认显示_id,这个隐藏 subject: true, answer: true, options:true }) .orderBy('create_time', 'desc') //排序方式,降序排列 .skip(0) //跳过多少个记录(常用于分页),0表示这里不跳过 .limit(10) //限制显示多少条记录,这里为10 .get() //获取根据查询条件筛选后的集合数据 .then(res => { console.log(res.data) }) .catch(err => { console.error(err) }) 聚合查询 const db = wx.cloud.database() const _ = db.command const $ = db.command.aggregate db.collection('china').aggregate() .match({ //类似于where,对记录进行筛选 price: $.gt(3000) }) .project({ //类似于field }) .sort({ //类似于orderBy age: -1, score: -1 }) .skip(5) //类似于skip .limit(2) //类似于limit .end() .then(res => console.log(res)) .catch(err => console.error(err)) 总结 match是根据条件过滤文档,进行的是查询匹配,语法和where比较类似,在写聚合时,应尽可能的把match放在流水线的前面。match内可以写db.command查询操作符 [代码]_[代码] 和聚合操作符db.command.aggregate [代码]$[代码],但是除了match阶段,在其他聚合阶段中传入的对象可使用的操作符都是聚合操作符;project 把指定的字段传递给下一个流水线,指定的字段可以是某个已经存在的字段,也可以是计算出来的新字段,它和field不同的是可以新增一些不存在的字段(只是显示用,也没写进数据库);sort 根据指定的字段,对输入的文档进行排序。<排序规则>可以是以下取值:1 代表升序排列(从小到大);-1 代表降序排列(从大到小);功能和orderBy类似;小程序端 limit 默认 20,也就是如果你使用聚合查询,你查询到的数据都会默认显示20条数据,但是你可以设置更多,而普通查询是不能超过20条的。
2020-08-28 - lookup拼接被连接集合的子查询之match写法?
[图片] 好不容易凑出一个貌似通过的,这东西博大精深,只能依样画葫芦。怎么把pipeline里的2个match并成一个? 一个条件外部传入event.taskid,另一个是两表连接。 写成sql,类似: select 这里略过 from roster left join bill on roster._id=bill.rosterid where roster.taskid=event.taskid
2020-05-20 - 云函数中,能多个函数互相调用?
[图片] 图1 [图片] 图2 想要实现如图1的,执行完第一个函数,然后执行第二个,第三个。。要怎么来写呢?
2022-02-17 - 小程序云函数中用group分组查询,只能查询20条,怎么解决?
[图片] 代码如上图。因为数据库有很多重复的数据,所以我要做分组查询。但是只能查询20条,怎么解决呢?
2019-08-02 - 微信小程序云开发读取数据超过20,云函数读取超过100条限制,获取云开发数据库集合里的所有数据的方法
看过石头哥云开发基础课的同学肯定都知道,直接在小程序里请求数据每次最多只能返回20条数据,云函数里请求数据每次最多只能返回100条数据,如果想突破这个限制,最好的方式就是做分页,当然分页我在云开发基础里也有教大家。但是限制存在这么一个需求,如果我们想一次性的拿到数据库里存的所有数据呢,比如数据库里有1000条数据,我们想一下子全部拿到,该怎么做呢??? [图片] 今天就来教大家如何通过云函数每次最多返回100条的限制。 一,云函数突破100条的限制 [图片] 如上图所示,我的num集合里有103条数据,如果按照之前的分页思路,就是分两次请求,第一次请求1-100条,第二次请求101-103条。这样我们虽然是可以拿到103条数据,但是要做两次请求,我们该如何做,才能一次请求就可以获取这103条数据呢。 1-1,突破100条的原理 其实原理和我们分页的原理是一样的,只不过我们用for循环做多次请求,然后把这多次的请求组合到一起,然后把组合好的数据一次性全部返回。这样就通过一次请求获取所有数据。 1-2,代码实现 这里的代码是写在云函数里,操作步骤我都在注释里给大家写出来。 [图片] 如上图所示,我们只需要通过三个步骤,就可以拿到所有的103条数据了。 [图片] 这样我们就可以通过一次请求,获取所有的数据了。是不是感觉很简单。这里把代码贴出来给到大家。 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') // 云开发环境初始化 cloud.init({env: cloud.DYNAMIC_CURRENT_ENV}) exports.main = async (event, context) => { const db = cloud.database() // 1,获取数据的总个数 let count = await db.collection('num').count() count = count.total // 2,通过for循环做多次请求,并把多次请求的数据放到一个数组里 let all = [] for (let i = 0; i < count; i += 100) { //自己设置每次获取数据的量 let list = await db.collection('num').skip(i).get() all = all.concat(list.data); } // 3,把组装好的数据一次性全部返回 return all; } [代码] 1-3,注意事项 云函数单次返回的数据不能超过1M,如果需要超过1M,则需要使用小程序端的数据查询20条20条的进行组合了。所以如果你一次性要返回很多数据,可以考虑在小程序里直接请求数据库,然后做20条20条的组装。 我下面也会教大家在小程序里做组装。 二,小程序直接请求数据库突破20条 2-1,开启async和await 原理我们这里不在说了,和上面是一模一样的,只不过小程序里使用await需要做下简单的操作,也可以去看下我的另外一篇文章。 《小程序里使用async和await变异步为同步,解决回调地狱问题》 [图片] 现在最新版本的小程序开发者工具好像已经支持async和await方法了,好像不勾选增强编译也没事。但是安全起见,还是勾选下增强编译比较好。 2-2,权限修改 小程序里直接获取数据库里的数据,记得要把集合的权限改一下 [图片] 2-3,代码实现 [图片] 细心的同学肯定可以看出来,上面的代码和我们云函数里的代码基本上一模一样的。 [图片] 到这里我们就完美的突破了小程序的限制,返回我们想要的任何个数的数据了。 后面会总结更多的小程序知识点给大家,欢迎关注,欢迎留言。
2021-06-28 - 云开发聚合函数group,能否对多个字段进行group分组?
我想要从以下记录中,先按task_id分组,再按stuClass分组,最后统计出status=1(只有0、1二值)的总和。求大佬指点一二。 我用group聚合函数,只能统计某一个字段的分组额... [图片]
2019-11-10 - 云函数端Aggregate聚合操作limit默认20条限制
云函数端 聚合 Aggregate 经过以下代码验证: [代码]// test_record 集合中 openid 为 test user openid 的实际上有超过20条数据的 db .collection('test_record') .aggregate() .match({ _openid: 'test user openid', }) .end(); [代码] 最后实际只返回了20条数据,所以说在云函数端如果某些接口返回确定以及肯定超过20条的话,还是老老实实加上 [代码].limit(100)[代码] ‘保命’吧。 改成如下代码即可超过默认20条的限制: [代码]db .collection('test_record') .aggregate() .match({ _openid: 'test user openid', }) .limit(100) // important .end(); [代码] 上限可以达到1万条数据 经过 stop eating 同学点拨,原来可以直接淦到10000 参考文档 Collection.limit(value: number): Collection [图片] 获取一个集合的数据 [图片]
2020-07-23 - 云开发免鉴权H5跳转小程序errCode: -501023 permission denied?
企业小程序,买了一个云开发环境,静态空间权限已经开启了:未登录用户访问云资源权限设置。 手机浏览器打开后无法唤起小程序:cloud.callFunction:fail Error: errCode: -501023 permission denied [图片] 翻不到正确的解决方案。有谁踩过坑的,指导一下
2022-08-31 - 云开发通过时间戳按月统计时出现的奇怪问题?
//此处两个时间戳转化为时间是 2022-01-01 00:00:00 2022-12-31 23:59:59 match.createTime = _.and(_.gte(1640966400000), _.lte(1672502399000)) const result = await collection .aggregate() .match(match) .project({ year: $.dateToString({ format: '%Y-%m', date: $.add([new Date(0), '$createTime']), }), }) .group({ _id: `$year`, value: $.sum(1), }) .sort({ _id: -1, }) .limit(35) .end() 此处返回的应该是从2022年一月开始到年末按照月份统计的数据 但是在返回体中却出现了2021年12月的统计数值 { "requestId": "183bb7768df_2", "data": [ { "_id": "2022-10", "value": 861 }, { "_id": "2022-09", "value": 3182 }, { "_id": "2022-08", "value": 3107 }, { "_id": "2022-07", "value": 3111 }, { "_id": "2022-06", "value": 2804 }, { "_id": "2022-05", "value": 2891 }, { "_id": "2022-04", "value": 2331 }, { "_id": "2022-03", "value": 2611 }, { "_id": "2022-02", "value": 3456 }, { "_id": "2022-01", "value": 4394 }, { "_id": "2021-12", "value": 15 } ] }
2022-10-09 - 如何批量下载云开发存储文件到本地
有人说打开云开发,存储点击文件有下载地址,这对于少量资源是可以的,下面的方法是下载上万文件的方法: 通过访问官方:https://docs.cloudbase.net/cli-v1/install [图片] [图片] 第四步、云存储文件路径:/qrcode/20220311 ==》需要下载到本地:如 E:\qrcode 1、首先在本地: E:\qrcode\文件内创建一个名为:cloudbaserc.json 的json文件。 { "envId":"你的云开发环境的id" } 2、通过命令访问E盘: e: 3、访问需要下载到本地文件路径 cd qrcode 4、开始下载云端文件到本地,执行命令,对于云端文件路径有子目录可以通过 / 进行访问。 tcb storage download qrcode/20220311 . --dir 5、等等文件下载中,直至文件全部下载。
2022-03-11 - 云开发数据库怎么合并子数组?
比如云数据库中order订单数据是这样的 [{orderId:1,goodsList:[{name:"apple",price:5},{name:"banana",price:8}]},{orderId:2,goodsList:[{name:"apple",price:5},{name:"banana",price:8}]}] 怎么查询可以得到goodsList的集合 [{name:"apple",price:5},{name:"banana",price:8},{name:"apple",price:5},{name:"banana",price:8}] 这样的结果
2021-04-27