From d55f18af9bc4d017ce095942c60f2d4e8628de82 Mon Sep 17 00:00:00 2001 From: wanganxp Date: Sat, 24 Oct 2020 09:17:21 +0800 Subject: [PATCH] Update cf-database.md --- docs/uniCloud/cf-database.md | 556 ++++++++++++++++++----------------- 1 file changed, 285 insertions(+), 271 deletions(-) diff --git a/docs/uniCloud/cf-database.md b/docs/uniCloud/cf-database.md index b1bade14ca..09f117b4e5 100644 --- a/docs/uniCloud/cf-database.md +++ b/docs/uniCloud/cf-database.md @@ -11,7 +11,17 @@ |行 row |记录 record / doc| |列 column |字段 field | -**云数据库仅支持通过云函数可访问。如需要在客户端访问云数据库,需通过`clientDB`插件。该插件可以将所有数据库操作封装在一个云函数中,大幅提升开发效率,是uniCloud开发者的必备插件,详见:[https://uniapp.dcloud.io/uniCloud/uni-clientDB](https://uniapp.dcloud.io/uniCloud/uni-clientDB)** +**云数据库仅支持通过云函数可访问。如需要在客户端访问云数据库,需通过`clientDB`** + +HBuilderX 2.9.5以前,使用clientDB需单独下载插件[https://ext.dcloud.net.cn/plugin?id=2314](https://ext.dcloud.net.cn/plugin?id=2314) + +HBuilderX 2.9.5+,clientDB已经内置,开发者可直接使用。详见[https://uniapp.dcloud.net.cn/uniCloud/database](https://uniapp.dcloud.net.cn/uniCloud/database) + +clientDB可极大的提升开发效率,是uniCloud开发者的必备插件。 + +不管在云函数里操作数据库,还是使用clientDB在前端操作数据库,均支持MongoDB的查询语法。 + +本文仅介绍MongoDB的传统语法,clientDB还额外支持了更简单易用的`jql`语法,推荐开发者使用和学习更简单的方式,[另见jql](https://uniapp.dcloud.net.cn/uniCloud/database?id=jsquery) **阿里云使用的mongoDB数据库版本为4.0,腾讯云使用的腾讯云自研的文档型数据库(兼容mongoDB 4.0版本)。请注意API的兼容性说明** @@ -22,6 +32,8 @@ ## 获取数据库的引用 +不管云函数还是前端,获取数据库连接都是如下写法。前端写法需2.9.5起支持。 + ```js const db = uniCloud.database(); ``` @@ -43,6 +55,7 @@ const db = uniCloud.database(); |× |√ | ``` +const db = uniCloud.database(); db.createCollection(collectionName) ``` @@ -139,16 +152,17 @@ uniCloud提供的`db_init.json`主要是为了对数据库进行初始化,并 - 目前导入文件最大限制为50MB - 导入csv时数据类型会丢失,即所有字段均会作为字符串导入 -- 冲突处理模式为设定记录_id冲突时的处理方式,`insert`表示冲突时依旧导入记录但是是新插入一条,`upsert`表示冲突时更新已存在的记录 -- 这里说的json文件并不是标准的json格式,而是形如下面这样每行一个json格式的数据库记录的文件 - ```json - {"a":1} - {"a":2} +- 冲突处理模式为设定记录_id冲突时的处理方式,`insert`表示冲突时依旧导入记录但是是新插入一条,`upsert`表示冲突时更新已存在的记录 +- 这里说的json文件并不是标准的json格式,而是形如下面这样每行一个json格式的数据库记录的文件 + ```json + {"a":1} + {"a":2} ``` ## 获取集合的引用 ```js +const db = uniCloud.database(); // 获取 `user` 集合的引用 const collection = db.collection('user'); ``` @@ -364,7 +378,7 @@ let res = await collection.doc('doc-id').set({ 支持 `where()`、`limit()`、`skip()`、`orderBy()`、`get()`、`field()`、`count()` 等操作。 -只有当调用`get()`时才会真正发送查询请求。 +只有当调用`get()`时才会真正发送查询请求。 注:默认取前100条数据,最大取前100条数据。 @@ -521,45 +535,45 @@ collection.field({ 'age': true }) //只返回age字段,其他字段不返回 ### 查询指令 -查询指令以dbCmd.开头,包括等于、不等于、大于、大于等于、小于、小于等于、in、nin、and、or。 - - -下面的查询指令以以下数据集为例: - -```json -// goods表 - -[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 -},{ - "type": { - "brand": "X", - "name": "X-01", - "memory": 8, - "cpu": 4.0 - }, - "category": "computer", - "quarter": "2020 Q3", - "price": 6500 -},{ - "type": { - "brand": "S", - "name": "S-01", - "author": "S-01-A" - }, - "category": "book", - "quarter": "2020 Q3", - "price": 20 -}] - +查询指令以dbCmd.开头,包括等于、不等于、大于、大于等于、小于、小于等于、in、nin、and、or。 + + +下面的查询指令以以下数据集为例: + +```json +// goods表 + +[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 +},{ + "type": { + "brand": "X", + "name": "X-01", + "memory": 8, + "cpu": 4.0 + }, + "category": "computer", + "quarter": "2020 Q3", + "price": 6500 +},{ + "type": { + "brand": "S", + "name": "S-01", + "author": "S-01-A" + }, + "category": "book", + "quarter": "2020 Q3", + "price": 20 +}] + ``` #### eq 等于@dbcmd-eq @@ -576,21 +590,21 @@ collection.field({ 'age': true }) //只返回age字段,其他字段不返回 const myOpenID = "xxx" let res = await db.collection('articles').where({ quarter: '2020 Q2' -}).get() - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - }] +}).get() + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + }] } ``` @@ -601,21 +615,21 @@ const dbCmd = db.command const myOpenID = "xxx" let res = await db.collection('articles').where({ quarter: dbCmd.eq('2020 Q2') -}).get() - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - }] +}).get() + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + }] } ``` @@ -628,36 +642,36 @@ let res = await db.collection('articles').where({ brand: 'S', name: 'S-01' } -}).get() - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "S", - "name": "S-01", - "author": "S-01-A" - }, - "category": "book", - "quarter": "2020 Q3", - "price": 20 - }] -} - -// 这种写法表示 stat 对象等于 { brand: 'S', name: 'S-01' } -// 对象中还有其他字段时无法匹配,例如:{ brand: 'S', name: 'S-01', author: 'S-01-A' } +}).get() + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "S", + "name": "S-01", + "author": "S-01-A" + }, + "category": "book", + "quarter": "2020 Q3", + "price": 20 + }] +} + +// 这种写法表示 stat 对象等于 { brand: 'S', name: 'S-01' } +// 对象中还有其他字段时无法匹配,例如:{ brand: 'S', name: 'S-01', author: 'S-01-A' } // 对象中字段顺序不一致也不能匹配,例如:{ name: 'S-01', brand: 'S' } const dbCmd = db.command let res = await db.collection('articles').where({ stat: dbCmd.eq({ - brand: 'S', + brand: 'S', name: 'S-01' }) -}).get() - -// 查询返回值 -{ - "data":[] +}).get() + +// 查询返回值 +{ + "data":[] } ``` @@ -674,21 +688,21 @@ let res = await db.collection('goods').where({ type: { brand: dbCmd.neq('X') }, -}).get() - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - }] +}).get() + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + }] } ``` @@ -703,21 +717,21 @@ const dbCmd = db.command let res = await db.collection('goods').where({ category: 'computer', price: dbCmd.gt(3000) -}).get() - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "X", - "name": "X-01", - "memory": 8, - "cpu": 4.0 - }, - "category": "computer", - "quarter": "2020 Q3", - "price": 6500 - }] +}).get() + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "X", + "name": "X-01", + "memory": 8, + "cpu": 4.0 + }, + "category": "computer", + "quarter": "2020 Q3", + "price": 6500 + }] } ``` @@ -746,31 +760,31 @@ let res = await db.collection('goods').where({ type: { memory: dbCmd.in([8, 16]) } -}).get() - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - },{ - "type": { - "brand": "X", - "name": "X-01", - "memory": 8, - "cpu": 4.0 - }, - "category": "computer", - "quarter": "2020 Q3", - "price": 6500 - }] +}).get() + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + },{ + "type": { + "brand": "X", + "name": "X-01", + "memory": 8, + "cpu": 4.0 + }, + "category": "computer", + "quarter": "2020 Q3", + "price": 6500 + }] } ``` @@ -787,11 +801,11 @@ db.collection('goods').where({ type: { memory: dbCmd.nin([8, 16]) } -}) - -// 查询返回值 -{ - "data":[] +}) + +// 查询返回值 +{ + "data":[] } ``` @@ -809,32 +823,32 @@ db.collection('goods').where({ type: { memory: dbCmd.gt(4).and(dbCmd.lt(32)) } -}) - - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - },{ - "type": { - "brand": "X", - "name": "X-01", - "memory": 8, - "cpu": 4.0 - }, - "category": "computer", - "quarter": "2020 Q3", - "price": 6500 - }] +}) + + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + },{ + "type": { + "brand": "X", + "name": "X-01", + "memory": 8, + "cpu": 4.0 + }, + "category": "computer", + "quarter": "2020 Q3", + "price": 6500 + }] } ``` @@ -861,32 +875,32 @@ db.collection('goods').where({ type: { price:dbCmd.lt(4000).or(dbCmd.gt(6000).and(dbCmd.lt(8000))) } -}) - - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - },{ - "type": { - "brand": "X", - "name": "X-01", - "memory": 8, - "cpu": 4.0 - }, - "category": "computer", - "quarter": "2020 Q3", - "price": 6500 - }] +}) + + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + },{ + "type": { + "brand": "X", + "name": "X-01", + "memory": 8, + "cpu": 4.0 + }, + "category": "computer", + "quarter": "2020 Q3", + "price": 6500 + }] } ``` @@ -916,31 +930,31 @@ db.collection('goods').where(dbCmd.or( cpu: 3.2 } } -)) - -// 查询返回值 -{ - "data":[{ - "type": { - "brand": "A", - "name": "A-01", - "memory": 16, - "cpu": 3.2 - }, - "category": "computer", - "quarter": "2020 Q2", - "price": 2500 - },{ - "type": { - "brand": "X", - "name": "X-01", - "memory": 8, - "cpu": 4.0 - }, - "category": "computer", - "quarter": "2020 Q3", - "price": 6500 - }] +)) + +// 查询返回值 +{ + "data":[{ + "type": { + "brand": "A", + "name": "A-01", + "memory": 16, + "cpu": 3.2 + }, + "category": "computer", + "quarter": "2020 Q2", + "price": 2500 + },{ + "type": { + "brand": "X", + "name": "X-01", + "memory": 8, + "cpu": 4.0 + }, + "category": "computer", + "quarter": "2020 Q3", + "price": 6500 + }] } ``` @@ -1907,10 +1921,10 @@ exports.main = async (event) => { ``` ## 聚合操作 - -有时候我们需要对数据进行分析操作,比如一些统计操作、联表查询等,这个时候简单的查询操作就搞不定这些需求,因此就需要使用聚合操作来完成。 -获取数据库集合的聚合操作实例 +有时候我们需要对数据进行分析操作,比如一些统计操作、联表查询等,这个时候简单的查询操作就搞不定这些需求,因此就需要使用聚合操作来完成。 + +获取数据库集合的聚合操作实例 ```js db.collection('scores').aggregate() @@ -1923,38 +1937,38 @@ db.collection('scores').aggregate() **字段路径** 表达式用字段路径表示法来指定记录中的字段。字段路径的表示由一个 `$` 符号加上字段名或嵌套字段名。嵌套字段名用点将嵌套的各级字段连接起来。如 `$profile` 就表示 `profile` 的字段路径,`$profile.name` 就表示 `profile.name` 的字段路径(`profile` 字段中嵌套的 `name` 字段)。 - -例如:现有以下数据 - -```json -[{ - "profile": { - "name": "Chloe" - }, - "status": 0 -}] -``` - -```js -// 执行以下操作 + +例如:现有以下数据 + +```json +[{ + "profile": { + "name": "Chloe" + }, + "status": 0 +}] +``` + +```js +// 执行以下操作 let res = await db.collection('scores').aggregate() .addFields({ name: '$profile.name' }) - .end() - -// 返回值为 -{ - "data": [{ - "profile": { - "name": "Chloe" - }, - "status": 0, - "name": "Chloe" - }] -} -``` - + .end() + +// 返回值为 +{ + "data": [{ + "profile": { + "name": "Chloe" + }, + "status": 0, + "name": "Chloe" + }] +} +``` + **常量** @@ -2554,8 +2568,8 @@ let res = await db.collection('attractions').aggregate() ### group -聚合阶段。将输入记录按给定表达式分组,输出时每个记录代表一个分组,每个记录的 _id 是区分不同组的 key。输出记录中也可以包括累计值,将输出字段设为累计值即会从该分组中计算累计值。 - +聚合阶段。将输入记录按给定表达式分组,输出时每个记录代表一个分组,每个记录的 _id 是区分不同组的 key。输出记录中也可以包括累计值,将输出字段设为累计值即会从该分组中计算累计值。 + 使用group可以很方便的实现类似SQL的distinct功能 **API 说明** @@ -2871,7 +2885,7 @@ books 集合有以下记录: ``` 以下聚合操作可以通过一个相等匹配条件连接 `orders` 和 `books` 集合,匹配的字段是 `orders` 集合的 `book` 字段和 `books` 集合的 title 字段: ```js -const db = cloud.database() +const db = uniCloud.database() let res = await db.collection('orders').aggregate() .lookup({ from: 'books', -- GitLab