marllen
marllen
  • 发布:2021-03-06 10:39
  • 更新:2021-03-06 10:39
  • 阅读:3898

uniCloud云数据库增删改查

分类:uniCloud

一个H5页面,让你看懂数据库增删改查。

演示网站《电户号查询系统》

写在最前面


我是自学前端的小白,所以只能演示基本的操作,关于复杂的连表增删改查,还没有研究过。 就以这个demo数据库为原型,完成查询、新增、修改、删除的基本操作示例。

1、查询,①在网站初始化时需要调用查询;②用户查询电户号时,需要调用查询;③新增或删除电户信息时,需要比对数据,也需要调用查询。
2、新增,分为①在demo下,再新增_id,并添加字段和值;②在指定_id下指定位置新增。
3、更新,分为①覆盖式更新;②在同一个_id下指定位置更新数据。
4、删除,分为①指定_id全部删除;②在指定_id下,指定位置删除数据。

在云函数写好之后,还需页面调用处理返回的数据,文末有示例。

一、准备云数据库

  • 云数据库有两个,'initial'和'demo',后面有展开数据演示。
  • 'initial',用于初始化页面。
  • 'demo',用于增删改查。

二、编写云函数

  • uniCloud数据库,允许在网页端直接使用uniCloud.callFunction函数调用数据库的数据。
    • 但是,建议使用云函数调用,这样数据更安全。</font>
    • 云函数的主流是路由——自动匹配对应的云函数去处理数据,我还不会,所以就写了五个云函数,在页面要用哪个就调用哪个。

2.1 云函数默认目录。

  • uniCloud/cloudfunctions/云函数名称/云函数名称.js

2.2 uniCloud数据库操作基于mongoDB,可以查询相关文档。

三、获取数据的云函数

await db.collection('demo').field({}).get();

3.1 初始化页面获取数据的方法

  • 初始化页面,需要调用的云数据库,名称initial,展开如下:
{  
    "_id":"603a0b27c9e7be00013b5e33",  
    "ArrList":["沙沟村","大东沟村","罗家坡村","小山岔村","渡口村","七家洼村"]  
}  
    ---------------华丽的---------分割线-------------  
{  
    "_id":"603a120b20be4e000120b8f6",  
    "groupArr": {  
        "0": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],  
        "1": ["一变","二变","三变"],  
        "2": ["一变","二变","三变","四变"],  
        "3": ["一变","二变","三变","四变","五变"]  
    --------后面-------还有------内容-------省略------  
    }  
}
  • 初始化云函数,名称也叫initial,代码如下:
  • get()获取的数据存放在data数组中,第一个_id的数据,就是data[0],第二个_id的数据,就是data[1]
'use strict';  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
    let [str] = event;  
    if(str ==='initial'){  
        let res = await db.collection('initial').field({_id:0,ArrList:1,'groupArr.0':1}).get();  
       //get()获取的数据存放在data数组中,第一个`_id`数据,就是data[0]        
        let cunList = res.data[0].ArrList;  
        //get()获取的数据存放在data数组中,第二个`_id`数据,就是data[1]  
        let zuList = res.data[1].groupArr[0];  
        //code的数字,只是为了前端if判断时好用,并没有什么实际意义。  
            return {  
                code:888,  
                msg:'初始化数据成功',  
                cunList,  
                zuList  
            }  
        }else{  
            return{  
                code:400,  
                msg:'您请求的数据格式有误'  
            }  
        }  
    }
  • 前端页面调用的代码,在onLoad生命周期内,将查询的数据赋值给两个数组,再渲染到页面中(两个列表中)。
  • 页面端调用的代码this.$api.HandleUnicloud(cloudName, mydata){res=>{}},如何而来,文末有详解
export default {  
    data() {  
        return {  
            cun_list: [],  
            zu_list: []  
            }  
        }     
    onLoad() {  
        let mydata = ['initial'];  
        let cloudName = 'initial';  
        this.$api.HandleUnicloud(cloudName, mydata).then(res => {  
            this.cun_list = res.cunList;  
            this.zu_list = res.zuList;  
        });  
    }  
}

3.2 <font color="red">★重点★</font> 查询返回指定字段的数据

  • 示例demo数据库,由六部分组成,每一个_id独立为一个单元。

  • 数据库展开

{  
    "_id":"603eeaa40daee300011f18f4",  
    "villages": {  
        "name": "沙沟村",  
        "id": 0,  
        "groupArr": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],  
        "group-1": [{"3102568889": "翟**"},{"3105360550": "李**"},{"3105360619": "马**"},..省略..],  
        "group-2": [{"3078734642": "刘**"},..省略..],  
        "group-3": [],  
        "group-4": [],  
        "group-6": []  
    }  
}  
  ------------华丽的-----------分割线------------------  
{  
    "_id":"603eeab4e857bd0001690475",  
    "villages": {  
            "name": "大东沟村",  
            "id": 1,  
            "groupArr": ["一变","二变","三变"]  
        }  
}  
  ------------华丽的-----------分割线----------------  
  {  
    "_id":"603eeab4e857bd0001690475",  
    "villages": {  
            "name": "XXX村",  
            "id": 2,  
            "groupArr": ["一变","二变","三变","四变"]  
        }  
}  
  -------后面----还有-----数据-----不再-----展示-----
  • field({}) ,可以返回指定字段的内容,必须使用get()方法才能获取到数据。1表示显示,没有标注的数据不显示。但是 _id是默认显示的。
  • field({'ArrList':1,_id:0})不显示_id,查询关于ArrList的信息,
  • field({'villages.group-2':1}) <font color="red">查询 villages 数组或对象内 group-2 的内容。
  • 与变量相结合的查询方式,有二种:
  • const groupNum = "group-3"; field({[`villages.${groupNum}`]:1})
  • const groupNum = "group-4"; field({['villages.'+ groupNum]:true})
'use strict';  
const db = uniCloud.database();  
exports.main = async (event, context) => {  
//event==mydata: { cunIndex: 0, groupName: 'group-1', userObj: { username: '', usernum: '' }, pageNum: 0, rowsNum: 10 }  
    let {cunIndex,groupName,userObj,pageNum,rowsNum} = event;  
    let resData = await db.collection('demo')  
    .field({_id:0,[`villages.${groupName}`]:1})  
    .get();  
    //resList等于当前村下的,当前变电组的,全部用户的信息  
    let resList = resData.data[`${cunIndex}`].villages[`${groupName}`];  

    //如果当前村的变电组不存在,或者变电组内没有数据时,调用  
    if(!resList||resList.length===0){  
        return {  
            code:400,  
            msg:'该村变电组内还未收录用户信息',  
        }  
    }  
    //这一段为翻页时调用  
    //请求的数据条数(rowsNum默认10条)  
    //pageNum当前点击的页码(由于是H5的原因默认是1)  
    let pageStarNum = (pageNum - 1) * rowsNum;  
    let pageEndNum = pageStarNum + rowsNum;  
    let pagesTotal = resList.length;  
    //pages表示返回的数据,在页面中总共要显示多少页  
    let pages = parseInt(pagesTotal/rowsNum);  
    //前端页面点击页码后,显示从第几条数据到第几条数据的列表  
    let resArr = resList.slice(pageStarNum,pageEndNum);  
    //resObj用于存放,数据库查找到的电户信息  
    let resObj = {};  
    //遍历当前变电组内所有的用户信息,当遍历的姓名与查询的姓名一致时  
    //把结果追加给resObj,使用合并对象的方法Object.assign(resObj,item)也行  
    resList.forEach(item=>{  
        if(Object.values(item)==userObj.username){  
            resObj = {...item}  
        }  
    })  
    //当用户没有输入姓名,直接查询,会获取全部列表  
    if(userObj.username===''){  
        return {  
            code:200,  
            msg:'当前查询的是:该变电组内所有用户的信息',  
            resArr,  
            pages  
        }  
    }  
    //当输入的姓名,查询不到时调用  
    //返回当前村、变电组,全部列表数据  
    //pages是总页数  
    if(Object.keys(resObj).length===0){  
        return {  
            code:404,  
            msg:'抱歉!该变电组内未收录此用户的信息',  
            resArr,  
            pages  
        }  
    }  
    //当输入的姓名,数据库中有时调用  
    //msg的信息可以使用模板字符串  
    return {  
        code:200,  
        msg:`「 ${userObj.username} 」的电户号,查询结果如下:`,  
        resObj  
    }  
}

四、新增数据的云函数

4.1 在原数据外,新增一个_id,add()

  • 新增单一数据,用大括号包裹数据 {"name": "张三"}
  • 新增多条数据,用中括号包裹数据[{"name": "张三"},{"name": "李四"},{"name": "王五"}]
const db = uniCloud.database();  
exports.main = async (event, context) => {  
    let resData = await db.collection('demo')  
    .add([{"name": "张三"},{"name": "李四"},{"name": "王五"}]);  
    let resList = await db.collection('demo').get();  
    return {  
        code:200,  
        msg:'添加数据成功',  
        resList  
    }  
};//数据返回结果  
{  
    "code": 200,  
    "msg": "添加数据成功",  
    "resList": {  
        "data": [{  
            "_id": "60210b53ef338d00016d2404",  
            ....此处 .... 省略 ....一万字....  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf4",  
        "name": "张三"  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf5",  
        "name": "李四"  
        },  
         {  
        "_id": "6038d46620be4e00011e5cf6",  
        "name": "王五"  
        }  
    }]  
}

4.2 在指定_id内,指定位置新增。

  • doc('_id').update();方法可用于更改,也可用于新增。

  • 普通数组添加、删除数据,官方文档中有示例,这里演示的是,数据为对象的数组"group-1":[{key:value},{key:vlaue}]如何新增。

  • update(),需紧随doc()之后,doc()内写指定数据的_id,因为一个集合内可能有多个_id

  • update()内引用变量,需要使用[`${变量名}`]

  • 在数组尾部新增对象,可以在中括号内写模板字符串dbCmd.push([{...addUserObj}])

'use strict';  
const db = uniCloud.database();  
const dbCmd = db.command;  
exports.main = async (event, context) => {  
    let {cunIndex,groupName,userObj} = event;  
    if(userObj.username==''||userObj.usernum==''){  
        return{  
            code:400,  
            msg:'新增数据不能为空'  
        }  
    }  
    let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();  
    //用于获取_id,存放与data[{_id:***},{_id:***},{_id:***},***]中  
    let id = resData.data[`${cunIndex}`]['_id'];  
    let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];  
    let isTrue = true;  
    //先查询,用户要新增的电户号码,在数据库中,有没有,有就赋值false  
    if (groupArr) {  
            groupArr.forEach(val=>{  
                if(Object.keys(val)==userObj.usernum){  
                    isTrue = false;  
                }  
            });  
        //如果数据库中没有该电户号码,就在对应村、变电组的尾部新增该数据  
        if(isTrue){  
            let addUserObj = {[`${userObj.usernum}`]:userObj.username};  
            let resSucc = await db.collection('demo')  
                .doc(`${id}`)  
                .update({  
                    villages: {  
                        [`${groupName}`]: dbCmd.push([{...addUserObj}])  
                    }  
                })  
                return {  
                    code: 200,  
                    msg: '数据添加成功',  
                    resSucc  
                    }  
            //当数据库中有该电户号码时,就提示已经存在        
            }else{  
                return {  
                    code: 400,  
                    msg: `抱歉!电户号「 ${userObj.usernum} 」已经存在`  
                }  
            }  
        }  

    //如果该村还未创建该变电组,就新建变电组,之后再新增用户信息  
    if (!groupArr) {  
        let resSucc = await db.collection('demo')  
            .doc(`${id}`)  
            .update({  
                villages: {  
                    [`${groupName}`]: dbCmd.set([{  
                        [`${userObj.usernum}`]: userObj.username  
                    }])  
                }  
            })  
        return {  
            code: 200,  
            msg: '创建变电组成功,数据添加成功',  
            resSucc  
        }  
    }  
}

五、更新数据的云函数

5.1 覆盖式更新

  • 覆盖式更新的意义不大,会将原数据彻底清除,一般情况下用不到。
  • update({'villages':dbCmd.set({key:value})})将villages做为字段,后面跟一个对象
const db = uniCloud.database();  
const dbCmd = db.command;  
exports.main = async (event, context) => {  
    let resSucc = await db.collection('demo')  
    .doc("600bfa4d7f06f30001b47259")  
    .update({  
        'villages':dbCmd.set({  
            "6640059601": "张三"  
        })  
      }  
    );  
    let resObj = await db.collection('demo').get();  
    return {  
        code:200,  
        resObj,  
        resSucc  
        }  
    }  
    //返回的数据结果 villages下只剩下一个对象了  
 "villages": {"6640059601":"张三"}

5.2 指定_id下,指定位置更新。

  • 指定位置更新,同上面的update()方法一致,这里省略。

六、删除数据的云函数

6.1 删除指定_id的数据库的全部数据

  • collection.doc(_id).remove()

  • doc()内只能写字符串或者数字,可以使用ES6模板字符串doc(`${id}`)

// 删除指定_id的数据  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
const id = '60388f7eb6ce210001cbbf14';  
    await db.collection('demo')  
    .doc(`${id}`)  
    .remove();  
    let resData = await db.collection('demo').get();  
    return resData;  
};

6.2 删除指定位置的数据

  • 在update()内使用remove(),方法挂载在command下,不能用于数组,删除后,数组原索引位置会变成null。但是可以用于对象,删除key就等于删除了该对象。doc(`${id}`).update({villages:{name:dbCmd.remove()}})
  • 更新数组,可以先获取数组,再修改数组,最后把新数组更新到原位置即可。update({villages:{[`${groupName}`]:[...groupArr]}})
'use strict';  
const db = uniCloud.database();  

exports.main = async (event, context) => {  
    let {cunIndex,groupName,userObj} = event;  
    let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();  
    let id = resData.data[`${cunIndex}`]['_id'];  
    let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];  
    let isTrue = false;  
    var index = 0;  
    if (!groupArr) {  
        return {  
            code: 400,  
            msg: '抱歉!该村还未创建此变电组数据',  
            resSucc  
        }  
    };  
    groupArr.forEach((val,i)=>{  
        if(Object.keys(val)==userObj.usernum){  
            isTrue = true;  
            index = i  
        }  
    });  

    //先查询数据在数组中的索引,使用splice,删除数据,把获得的新数组,更新到原位置处  
    if(isTrue){  
        groupArr.splice([`${index}`],1);  
        let resData = await db.collection('demo')  
        .doc(`${id}`)  
        .update({  
            villages:{  
                [`${groupName}`]:[...groupArr]  
            }  
        })  
        return {  
            code: 200,  
            msg: `「 ${userObj.usernum}  」数据删除成功`,  
            index,  
            groupArr,  
            resData  
        }  
    };  
    return {  
        code: 400,  
        msg: '数据删除失败,原因:电户号错误'  
    }  
}  

七、处理云函数返回数据的工具函数

  • 工具函数的路径 common/api/index.js
  • HandleUnicloud有两个参数,用于uniCloud.callFunction({name,data})传参。
  • cloudName表示,需要调用哪个云函数。
  • mydata表示,用户向云函数传递的数据。
const HandleUnicloud = (cloudName,mydata)=>{  
    return new Promise((reslove,reject)=>{  
        uniCloud.callFunction({  
            name:cloudName,  
            data:mydata  
        }).then(res=>{  
            if(res.result){  
                reslove(res.result)  
            }else{  
                reject(res.result)  
            }  
        }).catch(res=>{  
            console.log(res);  
            })  
    });  
};  
export default{  
    HandleUnicloud  
}

八、全局注册处理云函数数据的工具函数

  • 先引入import api from './common/api'
  • 再注册Vue.prototype.$api = api
import Vue from 'vue'  
import App from './App'  
import api from './common/api'  

Vue.config.productionTip = false  
Vue.prototype.$api = api  
App.mpType = 'app'  

const app = new Vue({  
    ...App  
})  
app.$mount()

九、页面调用的方法


this.$api.HandleUnicloud()

addData() {  
    //用户传给云函数的数据,赋值给mydata  
    let mydata = this.mydata;  
    //当前需要调用的云函数名称  
    let cloudName = 'UpdateAdd';  

    //用于检查姓名和电户号码的正则函数checkName()和checkNum()  
    if (!this.checkName(this.mydata.userObj.username) || !this.checkNum(this.mydata.userObj.usernum)) {  
        this.tip = '抱歉,姓名和电户号,数据有误!';  
        return;  
    }  
    //有确定和取消按键的模态框  
    uni.showModal({  
        title: '请选择',  
        content: `您确定要添加${mydata.userObj.username}吗?`,  
        cancelText:'取消添加',  
        confirmText:'确定添加',  
        //这里应当使用箭头函数,否则影响this.$api和this.tip的使用  
        success: res=> {  
            if (res.confirm) {  
                this.$api.HandleUnicloud(cloudName, mydata).then(v => {  
                    this.tip = v.msg;  
                        uni.showLoading({  
                            title: this.tip  
                        });  
                        setTimeout(() => {  
                            uni.hideLoading();  
                        }, 1000);  
                    });  
                } else if (res.cancel) {  
                    this.tip = '选择了取消!'  
                }  
            }  
        });  
    }

十、写在最后

非常感谢,DCloud公司提供如此强大的生态系统,让我们去学习进步的效率大大的提升。

最后附上H5白~嫖建站的最后一关,跨域配置问题,将前端网页托管——参数配置——默认网址,复制粘贴到跨域配置——新增域名中,即可手机,PC端都能正常访问了。

目前uniCloud</font>提供了,免费的阿里云空间,</font>完全可以满足个人用户的建站使用。
只需要在https://unicloud.dcloud.net.cn/login申请账号就可以获得:
1、一个免费的云数据库,用于保存JSON格式的数据
2、一个免费的存储云函数的空间,用于保存可以在云端调用修改云数据库数据的函数,空间环境为nodejs,操作基于mongoDB,有所改动。
3、一个免费的云存储,用于保存图片、视频、文件等,并能够提供对应的访问地址
4、一个免费的网页托管,自动生成可访问的网址,只需处理跨域配置即可。
个人博客地址

0 关注 分享

要回复文章请先登录注册