UNI-APP之uniCloud使用(雲數據庫)| 8月更文挑戰

雲數據庫簡介

uniCloud提供了一個 JSON 格式的文檔型數據庫,數據庫中的每條記錄都是一個 JSON 格式的對象。一個數據庫能夠有多個集合(至關於關係型數據中的表),集合可看作一個 JSON 數組,數組中的每一個對象就是一條記錄,記錄的格式是 JSON 對象。javascript

關係型數據庫和 JSON 文檔型數據庫的概念對應關係以下表:java

關係型 JSON 文檔型
數據庫 database 數據庫 database
表 table 集合 collection
行 row 記錄 record / doc
列 column 字段 field

uniCloud雲函數中可訪問雲數據庫。正則表達式

鑑於安全問題,暫不支持客戶端直接訪問數據庫。sql

獲取數據庫的引用

const db = uniCloud.database();
複製代碼

獲取集合的引用

// 獲取 `user` 集合的引用const collection = db.collection('user');
複製代碼

集合 Collection

經過 db.collection(name) 能夠獲取指定集合的引用,在集合上能夠進行如下操做mongodb

類型 接口 說明
add 新增記錄(觸發請求)
計數 count 獲取符合條件的記錄條數
get 獲取集合中的記錄,若是有使用 where 語句定義查詢條件,則會返回匹配結果集 (觸發請求)
引用 doc 獲取對該集合中指定 id 的記錄的引用
查詢條件 where 經過指定條件篩選出匹配的記錄,可搭配查詢指令(eq, gt, in, …)使用
skip 跳過指定數量的文檔,經常使用於分頁,傳入 offset
orderBy 排序方式
limit 返回的結果集(文檔數量)的限制,有默認值和上限值
field 指定須要返回的字段

查詢及更新指令用於在 where 中指定字段需知足的條件,指令可經過 db.command 對象取得。數據庫

記錄 Record / Document

經過 db.collection(collectionName).doc(docId) 能夠獲取指定集合上指定 id 的記錄的引用,在記錄上能夠進行如下操做json

接口 說明
set 覆寫記錄
update 局部更新記錄(觸發請求)
remove 刪除記錄(觸發請求)
get 獲取記錄(觸發請求)

查詢篩選指令 Query Command

如下指令掛載在 db.command數組

類型 接口 說明
比較運算 eq 字段等於 ==
neq 字段不等於 !=
gt 字段大於 >
gte 字段大於等於 >=
lt 字段小於 <
lte 字段小於等於 <=
in 字段值在數組裏
nin 字段值不在數組裏
邏輯運算 and 表示需同時知足指定的全部條件
or 表示需同時知足指定條件中的至少一個

若是你熟悉SQL,可查詢mongodb與sql語句對照表進行學習。promise

字段更新指令 Update Command

如下指令掛載在 db.command安全

類型 接口 說明
字段 set 設置字段值
remove 刪除字段
inc 加一個數值,原子自增
mul 乘一個數值,原子自乘
push 數組類型字段追加尾元素,支持數組
pop 數組類型字段刪除尾元素,支持數組
shift 數組類型字段刪除頭元素,支持數組
unshift 數組類型字段追加頭元素,支持數組

支持的數據類型

數據庫提供如下幾種數據類型:

  • String:字符串
  • Number:數字
  • Object:對象
  • Array:數組
  • Bool:布爾值
  • GeoPoint:地理位置點
  • GeoLineStringL: 地理路徑
  • GeoPolygon: 地理多邊形
  • GeoMultiPoint: 多個地理位置點
  • GeoMultiLineString: 多個地理路徑
  • GeoMultiPolygon: 多個地理多邊形
  • Date:時間
  • Null

注意

  • 阿里雲數據庫在存入emoji表情時會致使uniCloud控制檯沒法獲取數據列表,目前阿里正在處理此問題,開發者能夠先自行過濾一下

如下對幾個特殊的數據類型作個補充說明

時間 Date

Date 類型用於表示時間,精確到毫秒,能夠用 JavaScript 內置 Date 對象建立。須要特別注意的是,用此方法建立的時間是客戶端時間,不是服務端時間。若是須要使用服務端時間,應該用 API 中提供的 serverDate 對象來建立一個服務端當前時間的標記,當使用了 serverDate 對象的請求抵達服務端處理時,該字段會被轉換成服務端當前的時間,更棒的是,咱們在構造 serverDate 對象時還可經過傳入一個有 offset 字段的對象來標記一個與當前服務端時間偏移 offset 毫秒的時間,這樣咱們就能夠達到好比以下效果:指定一個字段爲服務端時間日後一個小時。

那麼當咱們須要使用客戶端時間時,存放 Date 對象和存放毫秒數是不是同樣的效果呢?不是的,咱們的數據庫有針對日期類型的優化,建議你們使用時都用 Date 或 serverDate 構造時間對象。

//服務端當前時間  new db.serverDate()
  //服務端當前時間加1S  new db.serverDate({    offset: 1000  })
複製代碼

Tips

  • 使用阿里雲做爲服務提供商時,如需存入日期類型,須要2020-02-10T04:59:05.579Z形式,便可以在雲函數中使用new Date().toISOString()獲得。

地理位置

阿里雲暫不支持地理位置類型

Null

Null 至關於一個佔位符,表示一個字段存在可是值爲空。

  • 新增文檔

新增文檔

方法1: collection.add(data)

示例:

參數 類型 必填 說明
data object | array {_id: '10001', 'name': 'Ben'} _id 非必填
// 單條插入數據
collection.add({
  name: 'Ben'
}).then((res) => {
});
// 批量插入數據
collection.add([{
  name: 'Alex'
},{
  name: 'Ben'
},{
  name: 'John'
}]).then((res) => {
// res.inserted // 插入成功條數
// res.result // 阿里雲特有,批量插入返回的全部記錄 id
// res.failIndexes // 騰訊雲特有,插入失敗的記錄的下標
});
複製代碼

Tips

  • 雲服務商爲阿里雲時,若集合不存在,調用add方法會自動建立集合

方法2: collection.doc().set(data)

也可經過 set 方法新增一個文檔,需先取得文檔引用再調用 set 方法。若是文檔不存在,set 方法會建立一個新文檔。

collection.doc().set({  name: "Hey"});
複製代碼

查詢文檔

支持 where()limit()skip()orderBy()get()update()field()count() 等操做。

只有當調用get() update()時纔會真正發送請求。注:默認取前100條數據,最大取前100條數據。

添加查詢條件

collection.where()參數

設置過濾條件where 可接收對象做爲參數,表示篩選出擁有和傳入對象相同的 key-value 的文檔。好比篩選出全部類型爲計算機的、內存爲 8g 的商品:

db.collection('goods').where({
  category: 'computer',
  type: {
    memory: 8,
  }
})
複製代碼

若是要表達更復雜的查詢,可以使用高級查詢指令,好比篩選出全部內存大於 8g 的計算機商品:

const dbCmd = db.command // 取指令
db.collection('goods').where({
  category: 'computer',
  type: {
    memory: dbCmd.gt(8), // 表示大於 8
  }
})
複製代碼

where 可使用正則表達式來查詢文檔,好比一下示例查詢全部name字段以ABC開頭的用戶

db.collection('user').where({
  name: new RegExp('^ABC')
})
複製代碼

獲取查詢數量

collection.count()

參數

db.collection('goods').where({
  category: 'computer',
  type: {
    memory: 8,
  }
}).count().then(function(res) {
})
複製代碼

響應參數

字段 類型 必填 說明
code string 狀態碼,操做成功則不返回
message string 錯誤描述
total Integer 計數結果
requestId string 請求序列號,用於錯誤排查

設置記錄數量

collection.limit()

參數說明

參數 類型 必填 說明
value Integer 限制展現的數值

使用示例

collection.limit(1).get().then(function(res) {

});
複製代碼

設置起始位置

collection.skip()

參數說明

參數 類型 必填 說明
value Integer 跳過展現的數據

使用示例

collection.skip(4).get().then(function(res) {

});
複製代碼
  • 對結果排序

對結果排序

collection.orderBy()

參數說明

參數 類型 必填 說明
field string 排序的字段
orderType string 排序的順序,升序(asc) 或 降序(desc)

使用示例

collection.orderBy("name", "asc").get().then(function(res) {

});
複製代碼
  • 指定返回字段

指定返回字段

collection.field()

參數說明

參數 類型 必填 說明
- object 要過濾的字段,不返回傳false,返回傳true

使用示例

collection.field({ 'age': true })
複製代碼

備註:只能指定要返回的字段或者不要返回的字段。即{'a': true, 'b': false}是一種錯誤的參數格式

查詢指令

eq

表示字段等於某個值。eq 指令接受一個字面量 (literal),能夠是 number, boolean, string, object, array

好比篩選出全部本身發表的文章,除了用傳對象的方式:

const myOpenID = "xxx"
db.collection('articles').where({
  _openid: myOpenID
})
複製代碼

還能夠用指令:

const dbCmd = db.command
const myOpenID = "xxx"
db.collection('articles').where({
  _openid: dbCmd.eq(openid)
})
複製代碼

注意 eq 指令比對象的方式有更大的靈活性,能夠用於表示字段等於某個對象的狀況,好比:

// 這種寫法表示匹配 stat.publishYear == 2018 且 stat.language == 'zh-CN'
db.collection('articles').where({
  stat: {
    publishYear: 2018,
    language: 'zh-CN'
  }
})
// 這種寫法表示 stat 對象等於 { publishYear: 2018, language: 'zh-CN' }
const dbCmd = db.command
db.collection('articles').where({
  stat: dbCmd.eq({
    publishYear: 2018,
    language: 'zh-CN'
  })
})
複製代碼

neq

字段不等於。neq 指令接受一個字面量 (literal),能夠是 number, boolean, string, object, array

如篩選出品牌不爲 X 的計算機:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    brand: dbCmd.neq('X')
  },
})
複製代碼

gt

字段大於指定值。

如篩選出價格大於 2000 的計算機:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  price: dbCmd.gt(2000)
})
複製代碼

gte

字段大於或等於指定值。

lt

字段小於指定值。

lte

字段小於或等於指定值。

in

字段值在給定的數組中。

篩選出內存爲 8g 或 16g 的計算機商品:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    memory: dbCmd.in([8, 16])
  }
})
複製代碼

nin

字段值不在給定的數組中。

篩選出內存不是 8g 或 16g 的計算機商品:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    memory: dbCmd.nin([8, 16])
  }
})
複製代碼

and

表示需同時知足指定的兩個或以上的條件。

如篩選出內存大於 4g 小於 32g 的計算機商品:

流式寫法:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    memory: dbCmd.gt(4).and(dbCmd.lt(32))
  }
})
複製代碼

前置寫法:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    memory: dbCmd.and(dbCmd.gt(4), dbCmd.lt(32))
  }
})
複製代碼

or

表示需知足全部指定條件中的至少一個。如篩選出價格小於 4000 或在 6000-8000 之間的計算機:

流式寫法:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    price:dbCmd.lt(4000).or(dbCmd.gt(6000).and(dbCmd.lt(8000)))
  }
})
複製代碼

前置寫法:

const dbCmd = db.command
db.collection('goods').where({
  category: 'computer',
  type: {
    price: dbCmd.or(dbCmd.lt(4000), dbCmd.and(dbCmd.gt(6000), dbCmd.lt(8000)))
  }
})
複製代碼

若是要跨字段 「或」 操做:(如篩選出內存 8g 或 cpu 3.2 ghz 的計算機)

const dbCmd = db.command
db.collection('goods').where(dbCmd.or(
  {
    type: {
      memory: dbCmd.gt(8)
    }
  },
  {
    type: {
      cpu: 3.2
    }
  }
))
複製代碼

正則表達式查詢

db.RegExp

根據正則表達式進行篩選

例以下面能夠篩選出 version 字段開頭是 "數字+s" 的記錄,而且忽略大小寫:

// 能夠直接使用正則表達式
db.collection('articles').where({
  version: /^\ds/i
})
// 或者
db.collection('articles').where({
  version: new db.RegExp({
    regex: '^\\ds'   // 正則表達式爲 /^\ds/,轉義後變成 '^\\ds'
    options: 'i'    // i表示忽略大小寫
  }) 
})
複製代碼

刪除文檔

方式1 經過指定文檔ID刪除

collection.doc(_id).remove()

// 清理所有數據
collection.get()
  .then((res) => {
    const promiseList = res.data.map(document => {
      return collection.doc(document.id).remove();
    });
    Promise.all(promiseList);
  })
  .catch((e) => {
  });
複製代碼

方式2 條件查找文檔而後直接批量刪除

collection.where().remove()

// 刪除字段a的值大於2的文檔
const dbCmd = db.command
collection.where({
  a: dbCmd.gt(2)
}).remove().then(function(res) {
})
複製代碼

更新文檔

更新指定文檔

collection.doc().update()

collection.doc('doc-id').update({
  name: "Hey",
  count: {
    fav: 1
  }
});
複製代碼
// 更新前
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 0,
    "follow": 0
  }
}
// 更新後
{
  "_id": "xxx",
  "name": "Hey",
  "count": {
    "fav": 1,
    "follow": 0
  }
}
複製代碼

更新數組時,已數組下標做爲key便可,好比如下示例將數組arr內下標爲1的值修改成 uniCloud

collection.doc('doc-id').update({
  arr: {
    1: "uniCloud"
  }
})
複製代碼
// 更新前
{
  "arr": ["hello", "world"]
}
// 更新後
{
  "arr": ["hello", "uniCloud"]
}
複製代碼

更新文檔,若是不存在則建立

collection.doc().set()

注意:

  • 此方法會覆寫已有字段,需注意與update表現不一樣,好比如下示例執行set以後follow字段會被刪除
collection.doc('doc-id').set({
  name: "Hey",
  count: {
    fav: 1
  }
}).then(function(res) {
});
複製代碼
// 更新前
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 0,
    "follow": 0
  }
}
// 更新後
{
  "_id": "xxx",
  "name": "Hey",
  "count": {
    "fav": 1
  }
}
複製代碼

批量更新文檔

collection.update()

const dbCmd = db.command
collection.where({name: dbCmd.eq('hey')}).update({
  age: 18,
}).then(function(res) {
});
複製代碼

更新指令

set

更新指令。用於設定字段等於指定值。這種方法相比傳入純 JS 對象的好處是可以指定字段等於一個對象:

const dbCmd = db.command
db.collection('photo').doc('doc-id').update({
  count: dbCmd.set({
    fav: 1,
    follow: 1
  })
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 0,
    "follow": 0
  }
}
// 更新後
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 1,
    "follow": 1
  }
}
複製代碼

inc

更新指令。用於指示字段自增某個值,這是個原子操做,使用這個操做指令而不是先讀數據、再加、再寫回的好處是:

  • 原子性:多個用戶同時寫,對數據庫來講都是將字段加一,不會有後來者覆寫前者的狀況
  • 減小一次網絡請求:不需先讀再寫以後的 mul 指令同理。

如給收藏的商品數量加一:

const dbCmd = db.command
db.collection('user').where({
  _id: 'my-doc-id'
}).update({
  count: {
    fav: dbCmd.inc(1)
  }
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 0,
    "follow": 0
  }
}
// 更新後
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 1,
    "follow": 0
  }
}
複製代碼

mul

更新指令。用於指示字段自乘某個值。

如下示例將count內的fav字段乘10

const dbCmd = db.command
db.collection('user').where({
  _id: 'my-doc-id'
}).update({
  count: {
    fav: dbCmd.mul(10)
  }
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 2,
    "follow": 0
  }
}
// 更新後
{
  "_id": "xxx",
  "name": "Hello",
  "count": {
    "fav": 20,
    "follow": 0
  }
}
複製代碼

remove

更新指令。用於表示刪除某個字段。如某人刪除了本身一條商品評價中的評分:

const dbCmd = db.command
db.collection('comments').doc('comment-id').update({
  rating: dbCmd.remove()
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "rating": 5,
  "comment": "xxx"
}
// 更新後
{
  "_id": "xxx",
  "comment": "xxx"
}
複製代碼

push

向數組尾部追加元素,支持傳入單個元素或數組

const dbCmd = db.command
db.collection('comments').doc('comment-id').update({
  // users: dbCmd.push('aaa')
  users: dbCmd.push(['c', 'd'])
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "users": ["a","b"]
}
// 更新後
{
  "_id": "xxx",
  "users": ["a","b","c","d"]
}
複製代碼

pop

刪除數組尾部元素

const dbCmd = db.command
db.collection('comments').doc('comment-id').update({
  users: dbCmd.pop()
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "users": ["a","b"]
}
// 更新後
{
  "_id": "xxx",
  "users": ["a"]
}
複製代碼

unshift

向數組頭部添加元素,支持傳入單個元素或數組。使用同push

const dbCmd = db.command
db.collection('comments').doc('comment-id').update({
  // users: dbCmd.push('aaa')
  users: dbCmd.unshift(['c', 'd'])
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "users": ["a","b"]
}
// 更新後
{
  "_id": "xxx",
  "users": ["c","d","a","b"]
}
複製代碼

shift

刪除數組頭部元素。使用同pop

const dbCmd = db.command
db.collection('comments').doc('comment-id').update({
  users: dbCmd.shift()
}).then(function(res) {
})
複製代碼
// 更新前
{
  "_id": "xxx",
  "users": ["a","b"]
}
// 更新後
{
  "_id": "xxx",
  "users": ["b"]
}
複製代碼
相關文章
相關標籤/搜索