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"]
}
复制代码
相关文章
相关标签/搜索