小程序 云数据库增删改查、聚合

(0.5)openid变量
	无需每次先通过云函数等获取用户openid,我们规定查询条件中可使用一个字符串常量{openid},在后台中发现该字符串时会自动替换为小程序用户的openid
	db.collection('test').where({
	 publisher: '{openid}'		效果等同于显示传入当前用户的实际openid
	}).get()


(1)云函数中初始化云数据库操作
	const cloud = require('wx-server-sdk')

	cloud.init({
	  env: cloud.DYNAMIC_CURRENT_ENV
	})
	const db=cloud.database()

(2)小程序中进行云数据库操作:
	0.1、初始化
		let db=wx.cloud.database()	默认为当前环境的数据库
		let db=wx.cloud.database({
		  env: 'test'		指定环境的数据库
		})
	
	0.5、结果返回方式
		回调方式
			db.collection('集合名').add({
				data:{
					键值对
				},
				success:function(res){
					成功回调
				}
			})
		Promise方式
			db.collection('comment').add({
			  data: {
			    commenter: '{openid}', // 用 {openid} 变量,后台会自动替换为当前用户 openid
			    articleId: '文章 ID',
			    content: '评论内容',
			  },
			  	当无success、fail和complete时,会返回一个Promise,通过await、.then获取返回数据
			})
			
	0.7、查询条件指令
		const db = wx.cloud.database()
		const _ = db.command
		
		_.eq	等于
		_.neq	不等于
		_.lt	小于
		_.lte	小于或等于
		_.gt	大于
		_.gte	大于或等于
		_.in	字段值在给定数组中
		_.nin	字段值不在给定数组中
		...更多详情:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/database/Command.html
		
		链式调用:
			_.eq(0).or(_.eq(100))	满足 _.eq(0) 或 _.eq(100)
				_.or([条件1,条件2])	满足条件中的一个
					如:
						db.collection('todos').where(_.or([
						  {
						    progress: _.lte(50)
						  },
						  {
						    style: {
						      color: _.in(['white', 'yellow'])
						    }
						  }
						]))
			_.gt(30).and(_.lt(70))	同时满足 _.gt(30) 和 _.lt(70) 两个条件
		
	
	1、增
		连接集合
		db.collection('集合名').add({
			data:{
				键值对
			},
			success:function(res){
				成功回调
			}
		})
		
	2、查
		回调方式:...get({success(res){},...})
		Promise方式:await ...get();
		1、id查询
				 async getDb(){
				    let db=wx.cloud.database();
				    let result = await db.collection('dbtest').doc('id值').get()
				  }
				  
		2、条件查询(where)
			(0)获取集合所有内容,一次最多返回20条,云函数100条,批次获取所有可查看代码示例,通过Promise.all的方式
					async queryDb(){
						  let db=wx.cloud.database();
						  let res=await db.collection('dbtest').get();	返回数据库中所有结果
						  console.log(res);
						}
					
			(1)其他条件
					async queryDb(){
						  let db=wx.cloud.database();
						  let res=await db.collection('dbtest').where({
						  	此处的条件在update中同样使用
						    username:'jeff',
						    
						    对象匹配
						    style: {				集合中是对象,可通过匹配其中某项属性,在update中则是修改对象中的该属性
							    color: 'yellow'		
							}
							'style.color':'yellow'	对象也可通过字符串.的方式表示,在update中则是修改对象中的该属性
							
							数组匹配
							numbers: [10, 20, 30],	数组完全匹配
							numbers: 20,		传入一个数组中存在的元素来筛选出所有numbers字段的值包含该元素的记录
							'numbers.1': 20,	查询或修改数组索引为1的元素
							numbers: _.gt(25).and(_.lt(15)) 	通过指令查找,找出所有numbers数组中存在包含大于 25 的值、同时也存在小于15的值的记录	
							
							嵌套对线数组匹配
							'root.objects.1.numbers.2': 70	所有的满足root.objects字段数组的第二项的numbers字段的第三项等于70的记录,在update中则是查找并更新
							'root.objects.numbers': 30		所有的满足root.objects字段数组中任意一项的numbers字段包含30的记录,在update中则是查找并更新
							
							
						  }).get();
						  console.log(res);
						}
					   			
	3、修改
		  update() {
			    let db = wx.cloud.database();
			    
			    方式一:update:
				    db.collection('dbtest').doc('id值').update({  
				      data: {
				        age: 20
				      },
				      success: function (res) {
				        console.log(res);
				      }
				    })
				    ...where({
				    	scores: 20	和查询where中数组查意思一致
				    }).update({ 
				    
				    	update中支持修改形式和查询where中的一致,下面为额外补充
				    
				    	更新数组
				    	'scores.$': 25	更新数组字段的第一个满足查询匹配条件的元素,这种方式where中必须有该数组字段where
				    		不支持用在数组嵌套数组
							如果用unset更新操作符,不会从数组中去除该元素,而是置为null
							如果数组元素不是对象、且查询条件用了neq、not或nin,则不能使用$
						'scores.$[]': _.inc(10)	让所有元素+10,$[]表示匹配数组的所有元素
							'scores.math.$[].score': _.inc(10) 支持链式调用,对应该格式记录score:{math:[{score:5,...},...]}	
						
						嵌套对线数组更新
							'root.objects.1.numbers.2': 70	所有的满足root.objects字段数组的第二项的numbers字段的第三项等于70的记录,在update中则是查找并更新
							'root.objects.numbers': 30		所有的满足root.objects字段数组中任意一项的numbers字段包含30的记录,在update中则是查找并更新
				    })
				  
				方式二:set
					替换更新一个记录,如果指定的记录不存在,则会自动创建该记录
					db.collection('todos').doc('todo-identifiant-aleatoire').set({
					  data: {
					  	...
					  },
					  success: function(res) {
					    console.log(res.data)
					  }
					})
			  }
			  将update换成set当没有查询到数据时,会插入给的内容
		
		与修改搭配的一些指令
			_.set	设置字段为指定值
			_.remove	删除字段
			_.inc	原子自增字段值
				原子操作指:同时有两名用户A和B取了同一个字段值,然后分别加上10和20再写进数据库,那么这个字段最终结果会是加了20而不是30。如果使用inc指令则不会有这个问题,会是30
				原子操作(atomic operation)指的是由多步操作组成的一个操作。如果该操作不能原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集
			_.mul	原子自乘字段值
			_.push	如字段值为数组,往数组尾部增加指定值
			_.pop	如字段值为数组,从数组尾部删除一个元素
			_.shift	如字段值为数组,从数组头部删除一个元素
			_.unshift	如字段值为数组,往数组头部增加指定值
				  
	4、删
		  removeDb(){
		    let db=wx.cloud.database();
		    db.collection('dbtest').doc('id值').remove({
		      success:function(res)
		      {
		        console.log(res);
		      }
		    })
		   await  ...where({...}).remove()
		  }
		  
	5、聚合(更精细化地处理数据,如分组、求和以及对返回的内容字段进行修改筛选等)
		const db =  wx.cloud.database();
		db.collection('article').aggregate().match({  类似where操作
			匹配的键值对
		}).project({	类似field操作,筛选显示某些字段
			键名:0/false 表示不显示
		}).end();  结束聚合操作
		
		求各类图书的平均销量
		const db = wx.cloud.database()
		const $ = db.command.aggregate
		const result = await db.collection('books').aggregate()
		  .group({
		    _id: '$category',	按category字段分组
		    avgSales: $.avg('$sales')	每组添加一个avgSales字段,其值是组内所有记录的sales字段的平均值
		  })
		  .end()
		  
		求各类图书的最高销量作者和最低销量作者及其销量
		const db = wx.cloud.database()
		const $ = db.command.aggregate
		const result = db.collection('books').aggregate()
		  .group({		按 "图书类目 + 作者" 进行分组,求得每个作者在该图书类目下的多本书的总销量
		    _id: {	
		      category: '$category',
		      author: '$author',
		    },
		    totalSales: $.sum('$sales')	
		  })			
		  .sort({		将上一个阶段得到的结果按总销量排倒序,求得各图书类目作者的总销量排序
		    totalSales: -1,
		  })
		  .group({	 	将上一个阶段得到的结果按类目分组,各组分别取组中第一项(销量最高)和最后一项(销量最低)的作者名和总销量,返回最终结果
		    _id: '$_id.category',
		    bestSellingAuthor: $.first('$_id.author'),
		    bestSellingAuthorTotalSales: $.first('$totalSales'),
		    worstSellingAuthor: $.last('$_id.author'),
		    worstSellingAuthorTotalSales: $.last('$totalSales'),
		  })
		  .end().then(console.log)
	
	6、查询监听(监每当数据库更新而导致查询条件对应的查询结果发生变更时,小程序可收到一个更新事件,其中可获取更新内容和更新后的查询结果快照)
		wx.cloud.init({
		  env: '环境 ID',
		})
		const db = wx.cloud.database()
		const _ = db.command
		
		const watcher = db.collection('message').where({
		  room: '房间 id',
		  time: _.gt(new Date('2019-09-01 10:00')),
		}).watch({
		  onChange: snapshot => {
		    console.log(`新事件`, snapshot)
		  },
		  onError: err => {
		    console.error(`监听错误`, err)
		  }
		})
		
		await watcher.close()		关闭监听

(3)数据库权限配置
	1、基本权限配置
		可通过云开发控制台可视化进行配置
		
		所有用户可读,仅创建者可写,对应规则配置:
			{
			  "read": true,
			  "write": "doc._openid == auth.openid"		doc._openid 代表查询条件中的_openid,auth.openid为系统给出的当前用户的openid
			}
		仅创建者可读写
			{
			  "read": "doc._openid == auth.openid",
			  "write": "doc._openid == auth.openid"
			}
		所有用户可读
			{
			  "read": true,
			  "write": false
			}
		所有用户不可读写
			{
			  "read": false,
			  "write": false
			}
	2、自定义权限配置
		小程序端受规则限制,云函数等控制台端拥有一切权限
		
		(1)可配置权限
			read	读
			write	写,可以细分为create、update、delete	
			create	新建	
			update	更新	
			delete	删除	
			
		(2)内置全局变量、全局函数
			auth	用户系统的登录信息,auth.openid是用户openid
			doc		记录内容,用于匹配记录内容/查询条件
			now		当前时间的时间戳
			
			get全局函数,从数据库中取出内容来进行匹配
				格式:database.集合名.记录id
				{
				  "read": "auth.openid == get(`database.shop.${doc._id}`).owner",  get中的变量需要字符串模板的形式
				  "write": false
				}
		
		(3)运算符
			==			等于		auth.openid == 'zzz'	用户的 openid 为 zzz
			!=			不等于		auth.openid != 'zzz'	用户的 openid 不为 zzz
			>			大于		doc.age>10				查询条件的 age 属性大于 10
			>=			大于等于		doc.age>=10				查询条件的 age 属性大于等于 10
			<			小于		doc.age<10				查询条件的 age 属性小于 10
			<=			小于等于		doc.age<=10				查询条件的 age 属性小于等于 10
			in			存在在集合中	auth.openid in ['zzz','aaa']		用户的 openid 是['zzz','aaa']中的一个
			!(xx in [])	不存在在集合中,使用in的方式描述 !(a in [1,2,3])	!(auth.openid in ['zzz','aaa'])	用户的 openid 不是['zzz','aaa']中的任何一个
			&&			与			auth.openid == 'zzz' && doc.age>10	用户的 openid 为 zzz 并且查询条件的 age 属性大于 10
			||			或			auth.openid == 'zzz' || doc.age>10	用户的 openid 为 zzz 或者查询条件的 age 属性大于 10
			.			对象元素访问符	auth.openid	用户的 openid
			[]			数组访问符属性	doc.favorites[0] == 'zzz'		查询条件的 favorites 数组字段的第一项的值等于 zzz
		
		(4)自定义规则后,升级与兼容
			假设为:
				{
				  "read": "doc._openid == auth.openid",
				  "write": "doc._openid == auth.openid"
				}
			前版本:db.collection('todo').doc('x').get()		配置后,需要显示传入_openid,否则无法查询
			新版本:
				db.collection('todo').where({
				  _id: 'x',
				  _openid: '{openid}',
				})
			
		
		(5)未登录模式
			在未登录模式中,auth为空,开发者可以以此判断是未登录用户的访问。未登录模式的场景有如:
				单页模式:小程序/小游戏分享到朋友圈被打开时
				Web未登录模式:没有登录的Web环境中(见多端支持)
				
		(6)示例
			集合字段:
				room:
				{
				  _id: string,
				  owner: string, 	 群主 openid
				  name: string, 	 群名
				  members: string[], 成员 openid 列表
				}
				message:
				{
				    _id: string,
				    room: string,  	 房间 id
				    sender: string,  发送者 openid
				    content: string, 消息内容
				    time: Date,  	 发送时间
				    withdrawn: boolean,  是否已撤回
				  }
			自定义规则:
				room:
				{
				  "read": "auth.openid in get('database.room.${doc._id}').members", 	仅群成员可以读群信息
				  "write": false
				}
				message:
				{
				 
				  "read": "auth.openid in get('database.room.${doc.room}').members && doc.withdrawn == false",
				  	仅能读取自己所在房间的聊天消息,且不允许读取已撤回的消息
				  "create": "auth.openid in get('database.room.${doc.room}').members",	仅能在自己所在的房间发消息
				  "update": "auth.openid == doc.sender",	只能修改自己发送的消息
				  "delete": false	不能删除自己发送的消息(只能撤回)
				}

云函数条件删除示例:
需要创建node.js云函数,并上传依赖,再在js中调用才能生效
在这里插入图片描述
代码示例:

// miniprogram/db/db.js
Page({

  /**
   * 页面的初始数据
   */
  data: {

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // this.addDb()
    // this.getDb();
    // this.queryDb();
    // this.queryDb2();
    //this.update();
    this.removeDb();
  },//添加
  addDb(){
    //初始化
    let db=wx.cloud.database();
    //连接指定集合
    db.collection('dbtest').add({
      data:{
        username:'jeff',
        password:'123',
        age:17
      },
      success:function(res)
      {
        console.log(res);
      }
    })
  },
  //id查询
  async getDb(){
    let db=wx.cloud.database();
    //是一个promise对象
    let result = await db.collection('dbtest').doc('1583714793020_0.589963916952146_33585318').get()
   console.log(result);
  },
//条件查询
async queryDb(){
  let db=wx.cloud.database();
  let res=await db.collection('dbtest').where({
    username:'jeff'
  }).get();
  console.log(res);
},
//条件查询2
  async queryDb2() {
    let db = wx.cloud.database();
    let cmd=db.command;
    let res = await db.collection('dbtest').where({
      // age:cmd.lt(18)
      //大于16小于19,lte表示小于等于,表示或将and改成or
     // age:cmd.lt(19).and(cmd.gt(16))
     //in来范围查询
      age:cmd.in([17])
    }).get();
    console.log(res);
  },
//修改,条件修改需要在云函数中调用,因为需要管理员权限
  update2() {
    let db = wx.cloud.database();
    db.collection('dbtest').doc('1583715745437_0.16474788067416468_33617666').update({
      data: {
        age: 20
      },
      success: function (res) {
        console.log(res);
      }
    })
  },
//删除
  removeDb(){
    let db=wx.cloud.database();
    db.collection('dbtest').doc('1583715745437_0.16474788067416468_33617666').remove({
      success:function(res)
      {
        console.log(res);
      }
    })
  }

})

获取集合所有内容(Promise.all):

const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const MAX_LIMIT = 100
exports.main = async (event, context) => {
  // 先取出集合记录总数
  const countResult = await db.collection('todos').count()
  const total = countResult.total
  // 计算需分几次取
  const batchTimes = Math.ceil(total / 100)
  // 承载所有读操作的 promise 的数组
  const tasks = []
  for (let i = 0; i < batchTimes; i++) {
    const promise = db.collection('todos').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
    tasks.push(promise)
  }
  // 等待所有
  return (await Promise.all(tasks)).reduce((acc, cur) => {
    return {
      data: acc.data.concat(cur.data),
      errMsg: acc.errMsg,
    }
  })
}
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值