所有內容都是微信小程式文件裡面的,手動記錄總結只為留下更深的記憶,有興趣可以通讀:小程式雲開發官方文件
小程式雲開發解放了開發者搭建伺服器和運維的困擾,同時使用雲開發進行核心業務開發能實現快速上線和迭代(和開發者已經使用的伺服器相容),它提供了三大基礎能力支援:
- 雲函式: 可以在雲端執行的程式碼,開發者只需編寫自身業務邏輯程式碼
- 資料庫: 好像是MongoDB的簡版,是可以在雲函式中讀寫的JSON資料庫
- 儲存: 可以在小程式前端直接上傳/下載檔案,在雲開發控制檯管理
在小程式端開始使用雲能力前,需先呼叫 wx.cloud.init
方法完成雲能力初始化(注意小程式需先開通雲服務,開通的方法是點選工具欄左上角的 “控制檯” 按鈕)。
wx.cloud.init({
env: 'test-x1dzi'
})
複製程式碼
env
的值是預設環境配置,傳入字串形式的環境 ID 可以指定所有服務的預設環境,傳入物件可以分別指定各個服務的預設環境
資料庫
資料型別
- String:字串
- Number:數字
- Object:物件
- Array:陣列
- Bool:布林值
- GeoPoint:地理位置點
- Date:時間
- Null
許可權控制
資料庫的許可權分為小程式端和管理端,管理端包括雲函式端和控制檯。小程式端執行在小程式中,讀寫資料庫受許可權控制限制,管理端執行在雲函式上,擁有所有讀寫資料庫的許可權。雲控制檯的許可權同管理端,擁有所有許可權。
以下是開發了幾種許可權配置,由寬到緊排列:
- 僅建立者可寫,所有人可讀:資料只有建立者可寫、所有人可讀;比如文章。
- 僅建立者可讀寫:資料只有建立者可讀寫,其他使用者不可讀寫;比如用私密相簿。
- 僅管理端可寫,所有人可讀:該資料只有管理端可寫,所有人可讀;如商品資訊。
- 僅管理端可讀寫:該資料只有管理端可讀寫;如後臺用的不暴露的資料。
初始化
在開始使用資料庫 API 進行增刪改查操作之前,需要先獲取資料庫的引用。如:
const db = wx.cloud.database()
複製程式碼
如需指定引用某個資料庫,假設一個環境名為test
,如下 獲取:
const testDB = wx.cloud.database({
env: 'test'
})
複製程式碼
同樣要操作一個集合,也要獲取它的引用,通過collection
方法,比如獲取待辦事項清單集合:
const todos = db.collection('todos')
複製程式碼
獲取集合的引用不會發起網路請求拉取它的資料,我們可以通過此引用在該集合上進行增刪查改的操作。除此之外,還可以通過集合上的 doc 方法來獲取集合中一個指定 ID 的記錄的引用。同理,記錄的引用可以用於對特定記錄進行更新和刪除操作。
通過doc
訪求獲取一個待辦事項ID為 todo-test1
的引用:
const todo = db.collection('todos').doc('todo-test1')
複製程式碼
插入資料
通過在集合物件上呼叫add
方法向集合中插入一條記錄,如新增一個待辦事項:
db.collection('todos').add({
// data 欄位表示需新增的 JSON 資料
data: {
// _id: 'todo-identifiant-aleatoire', // 可選自定義 _id,在此處場景下用資料庫自動分配的就可以了
description: "learn cloud database",
due: new Date("2018-09-01"),
tags: [
"cloud",
"database"
],
// 為待辦事項新增一個地理位置(113°E,23°N)
location: new db.Geo.Point(113, 23),
done: false
},
success: function(res) {
// res 是一個物件,其中有 _id 欄位標記剛建立的記錄的 id
console.log(res + '成功插入')
}
})
複製程式碼
Promise 風格
db.collection('todos').add({
// data 欄位表示需新增的 JSON 資料
data: {
description: "learn cloud database",
due: new Date("2018-09-01"),
tags: [
"cloud",
"database"
],
location: new db.Geo.Point(113, 23),
done: false
}
})
.then(res => {
console.log(res + '成功插入')
})
複製程式碼
讀取資料
通過get
方法獵取單個記錄或集合中多個記錄的資料,如下面是一個集合todos
的記錄:
[
{
_id: 'todo-identifiant-aleatoire',
_openid: 'user-open-id', // 假設使用者的 openid 為 user-open-id
description: "learn cloud database",
due: Date("2018-09-01"),
progress: 20,
tags: [
"cloud",
"database"
],
style: {
color: 'white',
size: 'large'
},
location: Point(113.33, 23.33), // 113.33°E,23.33°N
done: false
},
{
_id: 'todo-identifiant-aleatoire-2',
_openid: 'user-open-id', // 假設使用者的 openid 為 user-open-id
description: "write a novel",
due: Date("2018-12-25"),
progress: 50,
tags: [
"writing"
],
style: {
color: 'yellow',
size: 'normal'
},
location: Point(113.22, 23.22), // 113.22°E,23.22°N
done: false
}
// more...
]
複製程式碼
獲取一個記錄的資料,通過ID,呼叫get方法:
db.collection('todos').doc('todo-identifiant-aleatoire').get().then(res => {
// res.data 包含該記錄的資料
console.log(res.data)
})
複製程式碼
獲取多個記錄的資料,通過呼叫集合上的where
方法指定查詢條件,再呼叫get
方法:
db.collection('todos').where({
_openid: 'user-open-id',
done: false
})
.get({
success: function(res) {
// res.data 是包含以上定義的兩條記錄的陣列
console.log(res.data)
}
})
複製程式碼
獲取一個集合的資料
我們可以直接在一個集合上呼叫get
方法獲取它所有記錄,不過要儘量避免一次性獲取過量的資料,小程式端獲取集合資料預設並且最多返回20條記錄,雲函式端是100,我們可以通過limit
方法指定需要獲取的記錄數量。
db.collection('todos').get().then(res => {
// res.data 是一個包含集合中有許可權訪問的所有記錄的資料,不超過 20 條
console.log(res.data)
})
複製程式碼
在雲函式端獲取一個集合所有記錄的盒子,因為雲函式端最多一次取100條的限制,所以我們要分批取:
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,
}
})
}
複製程式碼
構建查詢條件
使用資料庫 API 提供的 where
方法我們可以構造複雜的查詢條件完成複雜的查詢任務。
假設我們需要查詢進度大於 30% 的待辦事項,那麼傳入物件表示全等匹配的方式就無法滿足了,這時就需要用到查詢指令。資料庫 API 提供了大於、小於等多種查詢指令,這些指令都暴露在 db.command
物件上。比如查詢進度大於 30% 的待辦事項:
const _ = db.command
db.collection('todos').where({
// gt 方法用於指定一個 "大於" 條件,此處 _.gt(30) 是一個 "大於 30" 的條件
progress: _.gt(30)
})
.get({
success: function(res) {
console.log(res.data)
}
})
複製程式碼
查詢指令 | 說明 |
---|---|
eq | 等於 |
neq | 不等於 |
lt | 小於 |
lte | 小於或等於 |
gt | 大於 |
gte | 大於或等於 |
in | 欄位值在給定陣列中 |
nin | 欄位值不在給定陣列中 |
還有邏輯指令,用於指定一個欄位需要同時滿足多個條件,如and
邏輯指令查詢進度在 30% 和 70% 之間的待辦事項:
const _ = db.command
db.collection('todos').where({
// and 方法用於指定一個 "與" 條件,此處表示需同時滿足 _.gt(30) 和 _.lt(70) 兩個條件
progress: _.gt(30).and(_.lt(70))
})
.get({
success: function(res) {
console.log(res.data)
}
})
複製程式碼
or
查詢進度為 0 或 100 的待辦事項:
const _ = db.command
db.collection('todos').where({
// or 方法用於指定一個 "或" 條件,此處表示需滿足 _.eq(0) 或 _.eq(100)
progress: _.eq(0).or(_.eq(100))
})
.get({
success: function(res) {
console.log(res.data)
}
})
複製程式碼
更新資料
更新資料主要有兩個方法:
API | 說明 |
---|---|
update | 區域性更新一個或多個記錄 |
set | 替換更新一個記錄 |
區域性更新
使用 update
方法可以區域性更新一個記錄或一個集合中的記錄,區域性更新意味著只有指定的欄位會得到更新,其他欄位不受影響。
例如通過一個ID來將一個待辦事項置為已完成:
db.collection('todos').doc('todo-identifiant-aleatoire').update({
// data 傳入需要區域性更新的資料
data: {
// 表示將 done 欄位置為 true
done: true
},
success: function(res) {
console.log(res.data)
}
})
複製程式碼
替換更新
使用set
方法替換更新指定的記錄:
const _ = db.command
db.collection('todos').doc('todo-identifiant-aleatoire').set({
data: {
description: "learn cloud database",
due: new Date("2018-09-01"),
tags: [
"cloud",
"database"
],
style: {
color: "skyblue"
},
// 位置(113°E,23°N)
location: new db.Geo.Point(113, 23),
done: false
},
success: function(res) {
console.log(res.data)
}
})
複製程式碼
指定ID的記錄不存在,則會自動建立該記錄。
刪除資料
使用remove
方法刪除一條記錄:
db.collection('todos').doc('todo-identifiant-aleatoire').remove({
success: function(res) {
console.log(res.data)
}
})
複製程式碼
刪除多條資料
可以通過where
語句選取多條記錄執行刪除(需要使用 Server 端的雲函式),只有有許可權刪除的記錄會被刪除,下面是刪除所有已完成的待辦事項:
// 使用了 async await 語法
const cloud = require('wx-server-sdk')
const db = cloud.database()
const _ = db.command
exports.main = async (event, context) => {
try {
return await db.collection('todos').where({
done: true
}).remove()
} catch(e) {
console.error(e)
}
}
複製程式碼
索引管理
建立索引是保證資料庫效能、保證小程式體驗的重要手段。我們應為所有需要成為查詢條件的欄位建立索引。建立索引的入口在控制檯中,可分別對各個集合的欄位新增索引。
儲存
- 雲端儲存提供高可用、高穩定、強安全的雲端儲存服務,支援任意數量和形式的非結構化資料儲存,如視訊和圖片,並在控制檯進行視覺化管理。雲端儲存包含以下功能:
- 儲存管理:支援資料夾,方便檔案歸類。支援檔案的上傳、刪除、移動、下載、搜尋等,並可以檢視檔案的詳情資訊 許可權設定:可以靈活設定哪些使用者是否可以讀寫該資料夾中的檔案,以保證業務的資料安全
- 上傳管理:在這裡可以檢視檔案上傳歷史、進度及狀態 檔案搜尋:支援檔案字首名稱及子目錄檔案的搜尋
- 元件支援:支援在 image、audio 等元件中傳入雲檔案 ID
雲函式
雲函式即在雲端(伺服器端)執行的函式。在物理設計上,一個雲函式可由多個檔案組成,佔用一定量的 CPU 記憶體等計算資源;各雲函式完全獨立;可分別部署在不同的地區。開發者無需購買、搭建伺服器,只需編寫函式程式碼並部署到雲端即可在小程式端呼叫,同時雲函式之間也可互相呼叫。
我的第一個雲函式
定義一個將兩個數字相加的函式示例:
在專案根目錄找到 project.config.json
檔案,新增 cloudfunctionRoot
欄位,指定本地已存在的目錄作為雲函式的本地根目錄
{
"cloudfunctionRoot": "./functions/"
}
複製程式碼
設定完成後,雲函式的根目錄的圖示會變成 “雲目錄圖示”,雲函式根目錄下的第一級目錄(雲函式目錄)是與雲函式名字相同的,如果對應的線上環境存在該雲函式,則我們會用一個特殊的 “雲圖示” 標明
接著,我們在雲函式根目錄上右鍵,在右鍵選單中,可以選擇建立一個新的 Node.js 雲函式,我們將該雲函式命名為 add
。開發者工具在本地建立出雲函式目錄和入口 index.js
檔案,同時線上上環境中建立出對應的雲函式。建立成功後,工具會提示是否立即本地安裝依賴,確定後工具會自動安裝 wx-server-sdk
。我們可以看到類似如下的一個雲函式模板:
const cloud = require('wx-server-sdk')
// 雲函式入口函式
exports.main = async (event, context) => {
}
複製程式碼
當小程式端呼叫雲函式時,event
就是小程式端呼叫雲函式時傳入的引數,外加後端自動注入的小程式使用者的 openid
和小程式的 appid
。context
物件包含了此處呼叫的呼叫資訊和執行狀態,可以用它來了解服務執行的情況。
填充模板:
exports.main = async (event, context) => {
return {
sum: event.a + event.b
}
}
複製程式碼
將傳入的 a 和 b 相加並作為 sum 欄位返回給呼叫端。
呼叫雲函式
wx.cloud.callFunction({
// 雲函式名稱
name: 'add',
// 傳給雲函式的引數
data: {
a: 1,
b: 2,
},
})
.then(res => {
console.log(res.result) // 3
})
.catch(console.error)
複製程式碼
獲取小程式使用者資訊
當小程式端呼叫雲函式時,雲函式的傳入引數中會被注入小程式端使用者的 openid,開發者可以直接使用該 openid。
從小程式端呼叫雲函式時,雲函式的第一個引數 event 會被注入一個 userInfo 物件,其中含有 openId 欄位和 appId 欄位,可以寫這麼一個雲函式進行測試:
// index.js
exports.main = (event, context) => {
return event.userInfo
}
// 呼叫
wx.cloud.callFunction({
name: 'test',
complete: res => {
console.log('callFunction test result: ', res)
}
})
複製程式碼
輸出的物件結構:
{
"appId": "xxx",
"openId": "yyy"
}
複製程式碼
非同步返回結果
使用 Promise
方法來完成
// index.js
exports.main = async (event, context) => {
return new Promise((resolve, reject) => {
// 在 3 秒後返回結果給呼叫方(小程式 / 其他雲函式)
setTimeout(() => {
resolve(event.a + event.b)
}, 3000)
})
}
// 在小程式程式碼中:
wx.cloud.callFunction({
name: 'test',
data: {
a: 1,
b: 2,
},
complete: res => {
console.log('callFunction test result: ', res)
},
})
複製程式碼
在雲函式中使用 wx-server-sdk
使用前都需要執行一次初始化方法:
const cloud = require('wx-server-sdk')
// 預設配置
cloud.init()
// 或者傳入自定義配置
cloud.init({
env: 'some-env-id'
})
複製程式碼
雲函式中呼叫資料庫
假設在資料庫中已有一個 todos
集合,我們可以如下方式取得 todos
集合的資料:
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
exports.main = async (event, context) => {
// collection 上的 get 方法會返回一個 Promise,因此雲函式會在資料庫非同步取完資料後返回結果
return db.collection('todos').get()
}
複製程式碼
雲函式中呼叫儲存
假設我們要上傳在雲函式目錄中包含的一個圖片檔案(demo.jpg):
const cloud = require('wx-server-sdk')
const fs = require('fs')
const path = require('path')
exports.main = async (event, context) => {
const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg'))
return await cloud.uploadFile({
cloudPath: 'demo.jpg',
fileContent: fileStream,
})
}
複製程式碼
雲函式中呼叫其他雲函式
假設我們要在雲函式中呼叫另一個雲函式 sum 並返回 sum 所返回的結果:
const cloud = require('wx-server-sdk')
exports.main = async (event, context) => {
return await cloud.callFunction({
name: 'sum',
data: {
x: 1,
y: 2,
}
})
}
複製程式碼