微信小程序云数据库操作
@toc
1、云数据库简介
PS:本文中有关API部分均来自微信开发者文档
1.1 数据类型
云开发数据库提供以下几种数据类型:
- String:字符串
- Number:数字
- Object:对象
- Array:数组
- Bool:布尔值
- Date:时间
- Geo:多种地理位置类型,详见下
- Null
下面对几个需要额外说明的字段做下补充说明。
Date
Date
类型用于表示时间,精确到毫秒,在小程序端可用 JavaScript
内置 Date
对象创建。需要特别注意的是,在小程序端创建的时间是客户端时间,不是服务端时间,这意味着在小程序端的时间与服务端时间不一定吻合,如果需要使用服务端时间,应该用 API 中提供的 serverDate 对象来创建一个服务端当前时间的标记,当使用了 serverDate
对象的请求抵达服务端处理时,该字段会被转换成服务端当前的时间
地理位置
要使用地理位置查询功能时,必须建立地理位置索引,建议用于存储地理位置数据的字段均建立地理位置索引。地理位置索引可在云控制台建立索引的入口中选择地理位置索引(2dsphere)。
具体的使用方法可参见 API 文档。
Null
null
相当于一个占位符,表示一个字段存在但是值为空。
1.2 权限控制
数据库的权限分为小程序端和管理端,管理端包括云函数端和控制台。小程序端运行在小程序中,读写数据库受权限控制限制,管理端运行在云函数上,拥有所有读写数据库的权限。云控制台的权限同管理端,拥有所有权限。小程序端操作数据库应有严格的安全规则限制。
每个集合可以拥有一种权限配置,权限配置的规则是作用在集合的每个记录上的。出于易用性和安全性的考虑,云开发为云数据库做了小程序深度整合,在小程序中创建的每个数据库记录都会带有该记录创建者(即小程序用户)的信息,以 _openid
字段保存用户的 openid
在每个相应用户创建的记录中。因此,权限控制也相应围绕着一个用户是否应该拥有权限操作其他用户创建的数据展开。
以下按照权限级别从宽到紧排列如下:
- 仅创建者可写,所有人可读:数据只有创建者可写、所有人可读;比如文章。
- 仅创建者可读写:数据只有创建者可读写,其他用户不可读写;比如用私密相册。
- 仅管理端可写,所有人可读:该数据只有管理端可写,所有人可读;如商品信息。
- 仅管理端可读写:该数据只有管理端可读写;如后台用的不暴露的数据。
简而言之,管理端始终拥有读写所有数据的权限,小程序端始终不能写他人创建的数据,小程序端的记录的读写权限其实分为了 “所有人可读,只有创建者可写“、”仅创建者可读写“、”所有人可读,仅管理端可写“、”所有人不可读,仅管理端可读写“。
对一个用户来说,不同模式在小程序端和管理端的权限表现如下:
模式 | 小程序端 读自己创建的数据 | 小程序端 写自己创建的数据 | 小程序端 读他人创建的数据 | 小程序端 写他人创建的数据 | 管理端 读写任意数据 |
---|---|---|---|---|---|
仅创建者可写,所有人可读 | √ | √ | √ | × | √ |
仅创建者可读写 | √ | √ | × | × | √ |
仅管理端可写,所有人可读 | √ | × | √ | × | √ |
仅管理端可读写:该数据只有管理端可读写 | × | × | × | × | √ |
在设置集合权限时应谨慎设置,防止出现越权操作。
2、云数据库操作
2.1 查询数据
在开始使用数据库 API 进行增删改查操作之前,需要先获取数据库的引用。以下调用获取默认环境的数据库的引用:
const db = wx.cloud.database()
如需获取其他环境的数据库引用,可以在调用时传入一个对象参数,在其中通过 env
字段指定要使用的环境。此时方法会返回一个对测试环境数据库的引用。
要操作一个集合,需先获取它的引用。在获取了数据库的引用后,就可以通过数据库引用上的 collection
方法获取一个集合的引用了,比如获取待办事项清单集合:
const todos = db.collection('db1')
获取集合的引用并不会发起网络请求去拉取它的数据,我们可以通过此引用在该集合上进行增删查改的操作,除此之外,还可以通过集合上的 doc
方法来获取集合中一个指定 ID 的记录的引用。同理,记录的引用可以用于对特定记录进行更新和删除操作。
2.1.1 通过collection.doc获取一条记录
我们先来看看如何获取一个记录的数据,假设我们已有一个 ID 为 todo-identifiant-aleatoire
的在集合 todos 上的记录,那么我们可以通过在该记录的引用调用 get
方法获取这个待办事项的数据:
db.collection('todos').doc('todo-identifiant-aleatoire').get({
success: function(res) {
// res.data 包含该记录的数据
console.log(res.data)
}
})
2.1.2 通过collection.get获取所有记录的数据
通过colletcion.get获取集合中的所有数据,或获取根据查询条件删选后的集合数据,其成功回调函数success的结果及Promise resolve的结果Result是一个数组对象,对应多条记录。
2.1.3 通过document.get获取某一条记录的数据
通过document.get
获取具体某一条记录的数据,或获取根据查询条件删选后的记录数据,其success回调的结果及Promise resolve结果Result是一个对象,对应一条记录。
测试:通过云开发控制台创建集合db1,然后添加多条记录,记录的字段分别为name(string)、password(string)、age(number)、sex(string)、tel(string)。
添加后的数据如下:
修改集合数据的操作权限:
get.wxml:
<view class="doc" bindtap="docget">doc.get获取一条记录</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{docget.name}}--{{docget.password}}--{{docget.age}}--{{docget.sex}}--{{docget.tel}}</text>
</view>
<view class="doc" bindtap="Collectionget">Collection.get 获取多条记录</view>
<view wx:for="{{Collectionget}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text>
</view>
</view>
get.js:
//index.js
const app = getApp()
Page({
data: {
docget:{},
Collectionget:[]
},
onLoad: function() {
},
docget:function(e){
console.log('执行docget')
var that=this
const db = wx.cloud.database()
db.collection('db1').doc('1ef3c513623c6c890cdeaa4d424a7a74').get({
success: function (res) {
console.log(res.data)
that.setData({
docget: res.data
})
}
})
},
Collectionget:function(e){
var that=this
const db = wx.cloud.database()
db.collection('db1').get({
success: function (res) {
console.log(res.data)
that.setData({
Collectionget: res.data
})
}
})
}
})
代码讲解:docget函数通过document.get()接口获取具体某一条记录的数据。Collectionget函数通过collection.get()接口获取集合中的所有数据,注意两个方法获取的数据都在res.data中。
实现效果:
2.1.4 通过collection.count获取集合记录数量
通过collection.count统计集合记录数或统计查询语句对应的结果记录数,注意这与集合权限设置有关,一个用户仅能统计其有读权限的记录数。success回调的结果及Promise resolve的结果Result是一个number类型的对象total。
2.1.5 通过collection.where条件查询
通过collection.where指定筛选条件,方法签名如下:
function where(rule:object):Query
该方法接受一个必填对象参数rule,用于定义筛选条件,示例代码如下:
const db=wx.cloud.database()
db.collection('db1').where({
age:30 //查询年龄为30岁的记录
}).get({
success:console.log,
fail:console.error
})
2.1.6 通过collection.orderBy排序查询
通过collection.orderBy指定查询排序条件,方法签名如下:
function orderBy(fieldName:string,order:string):collection|query
该方法接受一个必填字符串参数fieldName用于定义需要排序的字段,一个字符串参数order用于定义排序顺序,只能取asc或desc。
如果需要对嵌套字段排序,需要用"点表示法"连接嵌套字段,例如style.color表示字段style里的嵌套字段color。如果要按多个字段排序,多次调用orderBy即可,多字段排序时会按照orderBy调用顺序先后对多个字段排序。
案例:
where-orderby.wxml:
<view class="doc" bindtap="where">where查询男人记录</view>
<view wx:for="{{where}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text>
</view>
</view>
<view class="doc" bindtap="orderby">orderby按age升序排序</view>
<view wx:for="{{orderby}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text>
</view>
</view>
where-orderby.js:
//index.js
const app = getApp()
Page({
data: {
where: [],
orderby:[]
},
onLoad: function() {
},
where:function(e){
var that=this
const db = wx.cloud.database()
db.collection('db1').where({
sex:"男" }).get({
success: function (res) {
console.log(res.data)
that.setData({
where: res.data
})
}
})
},
orderby:function(e){
var that=this
const db = wx.cloud.database()
db.collection('db1').orderBy('age', 'asc') .get({
success: function (res) {
console.log(res.data)
that.setData({
orderby: res.data
})
}
})
}
})
代码讲解:请注意where和orderby操作应该在collection和get操作的中间,因为
collection.get
是获取集合中的所有记录,对所有记录排序和条件查询,where和orderby操作应在get之前。另外需要注意的是,get操作得到的数据是多条记录,应该赋值给一个数组。
2.1.7 通过collection.limit指定查询结果集数量上限
通过collection.limit指定查询结果集数量上限
limit
在小程序端默认及最大上限为 20,在云函数端默认及最大上限为 1000
官网示例代码:
db.collection('todos').limit(10)
.get()
.then(console.log)
.catch(console.error)
2.1.8 通过collection.skip跳过若干条记录
指定查询返回结果时从指定序列后的结果开始返回,常用于分页
示例代码:
db.collection('todos').skip(10)
.get()
.then(console.log)
.catch(console.error)
2.1.9 通过collection.field指定返回字段
指定返回结果中记录需返回的字段。
示例代码:只返回 description, done 和 progress 三个字段:
db.collection('todos').field({
description: true,
done: true,
progress: true,
})
.get()
.then(console.log)
.catch(console.error)
案例:
field-limit-skip.wxml:
<view class="doc" bindtap="field">field只显示name、age和tel字段</view>
<view wx:for="{{field}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.age}}--{{item.tel}} </text>
</view>
</view>
<view class="doc" bindtap="limit">limit只要3条记录</view>
<view wx:for="{{limit}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}} </text>
</view>
</view>
<view class="doc" bindtap="skip">skip跳4条记录</view>
<view wx:for="{{skip}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}} </text>
</view>
</view>
field-limit-skip.js:
Page({
data: {
limit:{},
skip:[],
field:[]
},
onLoad: function() {
},
limit:function(e){
var that=this
const db = wx.cloud.database()
db.collection('db1').limit(3).get({ //限定获取记录的总条数
success: function (res) {
console.log(res.data)
that.setData({
limit: res.data
})
}
})
},
skip:function(e){
var that=this
const db = wx.cloud.database()
db.collection('db1').skip(4).get({ //跳过指定条数的记录
success: function (res) {
console.log(res.data)
that.setData({
skip: res.data
})
}
})
},
field: function (e) {
var that = this
const db = wx.cloud.database()
db.collection('db1').field({ //只获取指定的字段
name: true, age: true, tel: true
}).get({
success: function (res) {
console.log(res.data)
that.setData({
field: res.data
})
}
})
}
})
field操作只获取指定的字段,本例中只显示name、age和tel三个字段。limit操作限定获取记录的总条数。skip操作跳过指定条数的记录,常用于分页显示。这3种操作是对get操作的有效补充。
2.1.10 通过command查询指定
原始的where条件查询只能查询“等于”的情况,当需要查询”大于“、”小于“、”大于或等于“、“与”等特殊条件查询的时候,where语句已经不能胜任,这是需要用db.command
获取数据库查询指定。
API | 说明 |
---|---|
eq | 等于指定值 |
neq | 不等于指定值 |
lt | 小于指定值 |
lte | 小于或等于指定值 |
gt | 大于指定值 |
gte | 大于或等于指定值 |
in | 在指定数组中 |
nin | 不在指定数组中 |
and | 条件与,表示需同时满足另一个条件 |
or | 条件或,表示如果满足另一个条件也匹配 |
这里只列举了大概,更详细的请参考官网。
案例:command.wxml
<view class="doc" bindtap="lte">lte小于等于30岁的记录</view>
<view wx:for="{{lte}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text>
</view>
</view>
<view class="doc" bindtap="in">in在25和30岁的记录</view>
<view wx:for="{{in}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}} </text>
</view>
</view>
command.js
Page({
data: {
lte:{},
in:[]
},
onLoad: function() {
},
lte:function(e){
var that=this
const db = wx.cloud.database()
const _ = db.command
db.collection('db1').where({
age: _.lte(30)
}).get({
success: function (res) {
console.log(res.data)
that.setData({
lte: res.data
})
}
})
},
in:function(e){
var that=this
const db = wx.cloud.database()
const _ = db.command
db.collection('db1').where({
age: _.in([25, 30])
}).get({
success: function (res) {
console.log(res.data)
that.setData({
in: res.data
})
}
})
}
})
in操作需要注意,age:_.in([25,30])是age等于25或者等于30的记录,不是25~30的记录
2.2 插入数据
小程序提供了add方法向集合中插入一条记录,方法签名如下:
function add(options:object):Promise<Result>
参数:
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
data | Object | 是 | 新增记录的定义 |
返回值:
属性 | 类型 | 说明 |
---|---|---|
_id | string/number | 新增的记录 _id |
示例代码:
add.wxml:
<view class="doc" bindtap="lte">插入之前大于等于30岁的记录</view>
<view wx:for="{{lte}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}}</text>
</view>
</view>
<view class="doc" bindtap="add">add插入之后大于等于30岁的记录</view>
<view wx:for="{{add}}">
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{item.name}}--{{item.password}}--{{item.age}}--{{item.sex}}--{{item.tel}} </text>
</view>
</view>
add.js:
Page({
data: {
lte:{},
add:[]
},
onLoad: function() {
},
lte:function(e){
var that=this
const db = wx.cloud.database()
const _ = db.command
db.collection('db1').where({
age: _.gte(30)
}).get({
success: function (res) {
console.log(res.data)
that.setData({
lte: res.data
})
}
})
},
add:function(e){
var that=this
const db = wx.cloud.database()
const _ = db.command
db.collection('db1').add({
data: {
age: 60,
name: "韩老师",
password:"han",
sex:"man",
tel:"18888880002"
},
success: function (res) { //插入成功之后查询
console.log(res)
db.collection('db1').where({
age: _.gte(30)
}).get({
success: function (res) {
console.log(res.data)
that.setData({
add: res.data
})
}
})
}
})
}
})
代码讲解:add操作会返回一个"_id",该值是成功插入的记录的id值,程序可以通过检查是否返回了“_id”来判断是否成功插入,若没有返回则说明插入失败。
2.3 更新数据
2.3.1 update更新
使用update方法可以局部更新一个记录或一个集合中的记录,局部更新意味着只有指定的字段会得到更新,其他字段不受影响。
示例代码:
db.collection('todos').doc('todo-identifiant-aleatoire').update({
// data 传入需要局部更新的数据
data: {
// 表示将 done 字段置为 true
done: true
}
})
.then(console.log)
.catch(console.error)
2.3.2 set更新
如果需要替换更新一条记录,可以再记录上使用set方法,替换更新意味着用传入的独享替换指定的记录。
示例:
update-set.wxml:
<view class="doc" bindtap="update1">韩老师记录update之前</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{update1.name}}--{{update1.password}}--{{update1.age}}--{{update1.sex}}--{{update1.tel}} </text>
</view>
<view class="doc" bindtap="update2">韩老师记录update之后</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{update2.name}}--{{update2.password}}--{{update2.age}}--{{update2.sex}}--{{update2.tel}} </text>
</view>
<view class="doc" bindtap="set1">李老师记录set之前</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{set1.name}}--{{set1.password}}--{{set1.age}}--{{set1.sex}}--{{set1.tel}} </text>
</view>
<view class="doc" bindtap="set2">李老师记录set之后</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{set2.name}}--{{set2.password}}--{{set2.age}}--{{set2.sex}}--{{set2.tel}} </text>
</view>
update-set.js:
Page({
data: {
update1:{},
update2:{},
set1:{},
set2:{}
},
onLoad: function() {
},
update1:function(e){
var that=this;
const db = wx.cloud.database()
db.collection('db1').doc('1ef3c513623c6c890cdeaa5142ca382e').get({
success: function (res) {
console.log(res.data)
that.setData({
update1: res.data
})
}
})
},
update2: function (e) {
var that = this;
const db = wx.cloud.database()
db.collection('db1').doc('1ef3c513623c6c890cdeaa5142ca382e')
.update({
data: {
age:44
},
success: function (res) {
console.log(res.data)
db.collection('db1').doc('1ef3c513623c6c890cdeaa5142ca382e').get({
success: function (res) {
console.log(res.data)
that.setData({
update2: res.data
})
}
})
}
})
},
set1: function (e) {
var that = this;
const db = wx.cloud.database()
db.collection('db1').doc('1ef3c513623c6c890cdeaa520b00a517').get({
success: function (res) {
console.log(res.data)
that.setData({
set1: res.data
})
}
})
},
set2: function (e) {
console.log(1)
var that = this;
const db = wx.cloud.database()
db.collection('db1').doc('1ef3c513623c6c890cdeaa520b00a517')
.set({
data: {
age: 60,name:"李教授",password:"li",sex:"女",tel:"18888881111"
},
success: function (res) {
console.log(res.data)
db.collection('db1').doc('1ef3c513623c6c890cdeaa520b00a517').get({
success: function (res) {
console.log(res.data)
that.setData({
set2: res.data
})
}
})
},
error:function(e){
console.log(e)
}
})
}
})
注意,在update和set操作之后不可以接着就进行get操作,本例把get操作写在了update操作的success方法中。
2.4 删除数据
小程序提供了remove方法来删除一条记录,示例代码如下:
db.collection('todos').doc('todo-identifiant-aleatoire').remove()
.then(console.log)
.catch(console.error)
==如果需要删除多条记录,需在Server端进行操作(云函数),并通过where语句选取多条记录进行删除,有权限删除的记录才会被删除。==
案例:
remove.wxml:
<view class="doc" bindtap="remove2">服务器端删除赵老师记录</view>
<view class="list-item" bindtap="testCgi">
<text class="request-text">{{remove2}}</text>
</view>
remove.js:
Page({
data: {
},
onLoad: function() {
},
remove2: function (e) {
wx.cloud.callFunction({
name: 'remove', // 云函数名称
data: {// 传给云函数的参数
name: "李老师"
},
success: function (res) {
console.log(res)
console.log("成功删除" + res.result.stats.removed + "条记录")
},
fail: console.error
})
}
})
先去云数据库控制台查看下赵老师:
执行代码之后:
云数据库中的记录已经被删除了。
这里只介绍了下常用的基本操作,更详细的介绍请查看微信开发者文档
- 点赞
- 收藏
- 关注作者
评论(0)