May 22, 2021 Mini Program Cloud Development Study Guide
1. The basics of a cloud database
2. Permission control and security rules for the database
3. Get a glimpse of the full picture of the data query
4. 5 ways to build query criteria
7. The positive query db. Regexp
8. New records and statistical records are added on the small terminal
9. Records within the cloud function-side operations collection
Any large application or service must use a high-performance data storage solution for accuracy (ACID, AtomicIty, Consistency, Isolation, Persistence Durability, Expanded Understanding), fast and reliable storage and retrieval of users' account information, merchandise and commodity transaction information, product data, information articles, and more, and cloud development brings its own high performance, Highly available, expandable, and secure databases.
In the operation of the database, we have to have a certain understanding of the database database, collectioncollection, record doc and field field, first of all, remember these corresponding English words, when you want to operate a record doc field content, just like delivery courier, first to find out which database it is in, in which collection, in which record, a level of search. Operational databases are usually databases, collections, records, fields to add, delete, change, check, when you understand these, the operation database will not be confused.
We can combine Excel and MySQL (it doesn't matter if we haven't been exposed to MySQL before, just look at the corresponding line with Excel) to understand the database for cloud development.
Cloud database | MySQL database | Excel file |
---|---|---|
Database database | Database database | The workbook |
Collection collection | Table table | The worksheet |
Field field | The data column column | Each column of the data table |
Record record/doc | Record row | The data table divides each row except the first row |
Let's now create a collection of books (the equivalent of creating an Excel table) to store information about books in the library, such as this one:
The title of the book, title | JavaScript Authoritative Guide (Version 6) | |
---|---|---|
Author author | David Flanagan | |
Standard book number isbn | 9787111376613 | |
Publishing information publicInfo | Press press | Machinery Industry Press |
Year of publication year | 2012 |
Open the database tab for the cloud development console, create a new collection book, select the collection, add a record to the book (similar to filling in the first line of Excel fields and one of the information records about the book), and then add fields:
After the database is created, we need to set the permission settings for the database in the permission settings tab of the cloud development console-database-collection. T he permissions of the database are divided into the small terminal and the service side (cloud function, cloud development console). T he service side has read and write permissions for all data, so the permissions here are set only to set the user's permissions on the database on the small terminal. Permission control is divided into simple permission control and custom permissions (i.e. security rules), and it is recommended that developers replace simple permission control with security rules.
Technical documentation: Permission control
To use custom permissions (i.e., security rules) to completely replace simple permission control, we need to understand the meaning of 4 simple permission control, and how security rules should replace them one by one, that is, when we configure the permissions of the collection, we no longer choose simple permission control, but the unified selection of custom permissions, fill in the corresponding jason rules.
Security rules allow for more flexibility and clarity in the ability to customize read and write permissions for the front-end database, and by configuring security rules, developers can fine-tune the readread and writewrite permissions for all records in the collection. Among them, the write permission can also be subdivided into creative new, update update, delete delete and other permissions, but also support comparison, logical operators for more granular permission configuration.
All users can read, only the creator can read and write: such as the user's posts, comments, articles, the creator here refers to the small terminal users, that is, the collection of storage UGC (user-generated content) to be set to this permission;
{
"read": true,
"write": "doc._openid == auth.openid"
}
Only the creator can read and write: such as private photo albums, users' personal information, orders, that is, only users read and write their own, other people can not read and write data collection;
{
"read": "doc._openid == auth.openid",
"write": "doc._openid == auth.openid"
}
All people can read: such as information articles, product information, product data, etc. you want everyone to see, but can not modify the content;
{
"read": true,
"write": false
}
All users can not read and write: such as background use of unexposed data, only you can see and modify the data;
{
"read": false,
"write": false
}
The small terminal API has strict call permission control, for example, in the small terminal A user is not able to modify B user's data, there is no such permission, in the small terminal can only modify non-sensitive and only for a single user's data;
If the data in the database collection is obtained by import, the permission for this collection defaults to "creator-only readable and writeable", a permission that can be called on the service side (cloud function), but an empty array may be returned on the small terminal Oh, so be sure to remember to modify the permissions as appropriate.
小程序端与云函数的服务端无论是在权限方面、API的写法上(有时看起来一样,但是写法不一样),还是在异步处理上(比如服务端不再使用success、fail、complete回调,而是返回Promise对象),都存在非常多的差异,这一点要分清楚。
The records in query collectioncollection are the most important knowledge of cloud development database operation, in the previous section we have imported the data of China's urban economic data china.csv into the collection china, and have set the permissions of the collection to be "all readable, only the creator can read and write" (or use security rules), and then we will use this as an example and combine the Excel version of China's urban economy line to explain the database query. In the Excel version of China's urban economic line and the cloud development console china collection, we can see the names of 332 cities in China city, provincial provance, urban area city_area, built-up area builtup_area, household registration population reg_pop, resident population resident_pop, GDP data.
Query the top 10 cities with GDP of more than 300 billion yuan and ask that the _id field not be displayed, showing the name of the city, the province and GDP, and in descending order of GDP.
Use the developer tool to create a new chinadata page, and then enter .js code in the onLoad lifecycle function of the index. The data in the operation collection involves very complex knowledge points, and the following cases are relatively complete, making it easy for everyone to have a holistic understanding:
const db = wx.cloud.database() //获取数据库的引用
const _ = db.command //获取数据库查询及更新指令
db.collection("china") //获取集合china的引用
.where({ //查询的条件指令where
gdp: _.gt(3000) //查询筛选条件,gt表示字段需大于指定值。
})
.field({ //显示哪些字段
_id:false, //默认显示_id,这个隐藏
city: true,
province: true,
gdp:true
})
.orderBy('gdp', 'desc') //排序方式,降序排列
.skip(0) //跳过多少个记录(常用于分页),0表示这里不跳过
.limit(10) //限制显示多少条记录,这里为10
.get() //获取根据查询条件筛选后的集合数据
.then(res => {
console.log(res.data)
})
.catch(err => {
console.error(err)
})
大家可以留意一下数据查询的链式写法, wx.cloud.database().collection('数据库名').where().get().then().catch(),前半部分是数据查询时对对象的引用和方法的调用;后半部分是Promise对象的方法,Promise对象是get的返回值。写的时候为了让结构更加清晰,我们做了换行处理,写在同一行也是可以的。
In the case above, there are five ways to build query criteria: Collection.where (), Collection.field (), Collection.orderBy (), Collection.skip (), Collection.limit (), which can be disassembled separately, such as using only where or only field, limit, You can also draw a few combinations from these five, and you can write multiple identical methods in a query, such as orderBy, where you can write the same multiple times.
It's worth noting, however, that the results of these five method-ordered queries can sometimes vary (for example, if the order is repeatedly upset by the order), and query performance can vary. U sually skip is best left behind and don't let skip skip a lot of data. T he skip(.limit)) and limit(.skip() effects are equivalent. T he five methods for building query criteria are collection-based references to College, where, for example, it cannot be wx.cloud.database().where(), nor can it be wx.cloud.database ("china") .doc.where(), only wx.cloud.database ().collection (). china"). where(), that is, can only be used to query records in the collection.
Technical documentation: Collection.where
Technical documentation: Collection.field
Technical documentation: Collection.orderBy
Technical documentation: Collection.skip
Technical documentation: Collection.limit
Each of the incoming objects, which forms a filter, has multiple slt;key, value, and indicates that these conditions need to be met at the same time, and is related to, if necessary, or if necessary, command.or
When instructions are used for queries, they are written in where, mainly to compare the values of the fields and to logically filter judgments. The database API provides a variety of query instructions, large or smaller, that are exposed to db.command objects.
Directive Command can be divided into query instructions and update instructions, the use of the two are very different, query instructions for db.collection where condition filtering, and update instructions for db.collection.doc of the update request field update, the difference between the two will be repeated later.
Let's put together a table of the comparison operators and logical operators of the query instructions, and attach the corresponding technical documentation to facilitate a clear and holistic understanding of them. The comparison of query instructions
The comparison of query instructions | |||
---|---|---|---|
gt | Greater than | lt | Less than |
eq | Equals | neq | Not equal to |
Lte | Less than or equal to | gte | Is greater than or equal to |
in | In the array | nin | Not in the array |
The logic of the query instruction | |||
and | Conditions and | or | Conditions or |
not | The condition is not | nor | Not at all |
The instruction command is based on a database database reference, and we take the full writing of a larger than gt on the small terminal (in the case of a larger than 3000):
wx.cloud.database().command.gt(3000)
For simplicity, we usually assign wx.cloud.database() to a variable, such as db, db.command, and eventually to .gt (3000). By declaring variables and assigning values layer by layer, the writing of instructions is greatly simplified, which can be followed in other instructions.
Compared to other comparison instructions equal to eq and not equal to the use of the neq operator is very rich, it can make numerical comparisons, we query a field such as GDP equal to a value of 175.28 billion cities:
.where({
gdp: _.eq(17502.8),
})
It can also match strings, such as when we query a field such as city to match a string completely, such as Shenzhen:
.where({
city: _.eq("深圳"),
})
注意:在查询时,gdp: _.eq(17502.8)的效果等同于gdp:17502.8,而city: _.eq(“深圳”)等同于city:”深圳”,虽然两种方式查询的结果都是一致的,但是它们的原理不同,前者用的是等于指令,后者用的是传递对象值。
eq can also be used for field values such as arrays and objects, which we'll cover later in the chapter.
Find out about cities in Guangdong province with GDP of more than 300 billion and less than 1 trillion yuan. In Guangdong Province, that is, let the value of the field profile equal to "Guangdong", and the GDP requirement is that the GDP field meets both greater than 300 billion and less than 1 trillion, then you need to use and (conditions and, that is, meaning):
.where({
province:_.eq("广东"),
gdp:_.gt(3000).and(_.lt(10000))
})
The two conditions in the above case, province: .eq ("Guangdong") and gdp: .gt (3000). and (.lt(10000)) have a cross-field condition and the relationship between and (i.e., and) how to implement the cross-field condition or or?
Check out the top 20 major cities with GDP of more than 300 billion yuan and resident population of more than 5 million or urban areas of more than 300 square kilometers. The resident population and the area of the built-up area here only need to meet one of the conditions, which involves the conditions or or (note the format of the following code):
.where(
{
gdp: _.gt(3000),
resident_pop:_.gt(500),
},
_.or([{
builtup_area: _.gt(300)}
]),
)
Note the above three conditions, gdp: .gt (3000) and resident pop: .gt (500) is logical, and the relationship with buildup area: .gt(300)) is logical or. There is an array within the .or (condition one, condition two), and condition one and condition two constitute a logical relationship.
Regular expressions have the flexibility to effectively match strings and can be used to check if a string contains some sort of sub-string, such as the word "technology" in "CloudBase Technical Bootcamp." C loud database query supports UTC-8 format, can be fuzzy query in Chinese and English. The positive query is also written in the condition filter for the where field.
Technical documentation: Database.RegExp
We can query a field with a positive query, such as a city city name, that contains a string such as a "state" city:
.where({
city: db.RegExp({
regexp: '州',
options: 'i',
})
})
Note that the city here is the field, db. T he regexp in RegExp() is a regular expression, while the options are flags, and i is the value of the flag, which means that the letters are not case sensitive. O f course, we can also use JavaScript's native writing or call the constructor of the RegExp object directly inside. For example, the above case can also be written as:
//JavaScript原生正则写法
.where({
city:/州/i
})
//JavaScript调用RegExp对象的构造函数写法
.where({
city: new db.RegExp({
regexp: "州",
options: 'i',
})
})
Regular expressions for database queries also support template strings, for example, we can declare const cityname with "state" and then wrap the cityname variable with a template string:
city: db.RegExp({
regexp:`${cityname}`,
options: 'i',
})
The use of regular expressions is very complicated, knowledge of regular expressions can go to search for more details.
Technical documentation: Regular expressions
It is important to note that when database queries, you should avoid overusing regular expressions for complex matches, especially in scenarios where user access triggers more, and it is generally best to have a response time of less than 500ms for data queries, whether small or cloud-based.
Earlier we've covered the query method get for collection data requests, in addition to get queries, the methods requested are added, remove delete, update overwrite/update, count statistics, and watch listening, all of which are based on database collection references to Collegection, and then let's show you how to build on the number of new records and statistical records in College.
References to the database collection are queried for multiple records, which means that we can add, delete, change, check and other operations on N records, but at present it is not supported to do multiple records on the small terminal update and remove, only on the cloud function side of such operations.
Statistical recordscollection.count
Count the number of collection records or the number of result records corresponding to the statistical query statement. The performance of the small terminal and the cloud function side will be as follows: the small terminal: note that in the case of collection permission settings, a user can only count the number of records that they have read permissions on the cloud function side: because it belongs to the management side, it can count the number of records in the collection.
Technical documentation: Collection.count().
const db = wx.cloud.database()
const _ = db.command
db.collection("china")
.where({
gdp: _.gt(3000)
})
.count().then(res => {
console.log(res.total)
})
field, orderBy, skip, limit are not valid for count, only where will affect the results of count, count will only return the number of records, will not return the query data.
In the previous, we imported the data from the zhihu_daily into the collection of the data, and then we'll zhihu_daily new records.
Technical documentation: Collection.add
Use the developer tool to create a new zhihudaily page, and then enter the following code in zhihudaily.wxml to create a new button that binds the event handler to addDaily:
<button bindtap="addDaily">新增日报数据</button>
Then enter the following code in the zhihudaily.js, call College.add in the event handler addDaily, add a record to the collection zhihu_daily, automatically generate _id from the background if the incoming record object does not have a _id field, and if _id is specified, it cannot conflict with the existing record.
addDaily(){
db.collection('zhihu_daily').add({
data: {
_id:"daily9718005",
title: "元素,生生不息的宇宙诸子",
images: [
"https://pic4.zhimg.com/v2-3c5d866701650615f50ff4016b2f521b.jpg"
],
id: 9718005,
url: "https://daily.zhihu.com/story/9718005",
image: "https://pic2.zhimg.com/v2-c6a33965175cf81a1b6e2d0af633490d.jpg",
share_url: "http://daily.zhihu.com/story/9718005",
body:"<p><strong><strong>谨以此文,纪念元素周期表发布 150 周年。</strong></strong></p>\r\n<p>地球,世界,和生活在这里的芸芸众生从何而来,这是每个人都曾有意无意思考过的问题。</p>\r\n<p>科幻小说家道格拉斯·亚当斯给了一个无厘头的答案,42;宗教也给出了诸神创世的虚构场景;</p>\r\n<p>最为恢弘的画面,则是由科学给出的,另一个意义上的<strong>生死轮回,一场属于元素的生死轮回</strong>。</p>"
}
})
.then(res => {
console.log(res)
})
.catch(console.error)
}
Click on button for the new daily data and you'll see that the console-printed res object contains the new record_id the daily9718005 we set up for ourselves. Open the database tab for the cloud development console, open zhihu_daily collection, turn to the last page, and you'll see our new records.
Note that, different from the imported data, new records on the small terminal automatically add a _openid field whose value is equal to the user openid, and the value of the _openid is not allowed to be modified. A condition is automatically added when we change the permissions of the collection to be read-and-write-only, or read-only for everyone, read-to-write for only creators, and query or update records on the small terminal.
.where({
_openid:"当前用户的openid"
})
So that's why, even though there's data in the collection, because of this condition, as long as there's no _openid or openid mismatch in the record, the record can't be queried.
Collection request method considerations
get、update、count、remove、add等都是请求,在小程序端可以有callback和promise两种写法,但是在云函数端只能用promise,不能用callback。为了方便,建议大家统一使用promise的写法,也就是then、catch。
get、update、count、remove、add请求不能在一个数据库引用里同时存在。比如不能又是get(),又是count()的,不能这么写:
db.collection('china').where({
_openid: 'xxx',
}).get().count().add()
We've covered how to call databases on the cloud function side in the Cloud Development Capabilities section, and the same is true here. C reate a new cloud function, chinadata, and then enter the following code at exports.main sync (event, context), note that const db s cloud.database(), wx. cloud.database(), database references on the cloud function side are different from the smaller terminals:
const db = cloud.database()
const _ = db.command
return await db.collection("china")
.where({
gdp: _.gt(3000)
})
.field({
_id: false,
city: true,
province: true,
gdp: true
})
.orderBy('gdp', 'desc')
.skip(0)
.limit(10)
.get()
try/catch async错误处理
当 async 函数中只要一个 await 出现 reject 状态,则后面的 await 都不会被执行。如果有多个 await 则可以将其都放在 try/catch 中。
Then right-click the chinadata cloud function root to open in the terminal, enter npm install, and then upload and deploy all files.
As we learned earlier, calling cloud functions can be done using on-premises debugging, cloud testing, and we can also call cloud functions on the small terminal to return data from the cloud function to the smaller terminal. Use the developer tool to enter the following code in chinadata.wxml, which is our universal click button to trigger the event handler:
<button bindtap="callChinaData">调用chinadata云函数</button>
Then call the cloud function in the event handler, enter the getChinaData event .js in the chinadata event handler in the chinadata function:
getChinaData() {
wx.cloud.callFunction({
name: 'chinadata',
success: res => {
console.log("云函数返回的数据",res.result.data)
},
fail: err => {
console.error('云函数调用失败:', err)
}
})
},
Clicking on the button to call the chinadata cloud function in the emulator will allow you to see the results of the query returned by the cloud function in the console, and you can render the results of the query to the small program page by settingData, which is not covered here.
Based on the reference Torction of the database collection, we can first match the where statement query to multiple records of the relevant condition, and then call College.remove() to delete it. F ive query methods, skip and limit are not supported, field, orderBy are meaningless, only where conditions can be used to filter records. Once the data is deleted, it cannot be retrieved.
Technical documentation: Collection.remove().
We can modify the code in the previously built chinadata cloud function exports.main s async (event, context) to the following, i.e. delete all data from the province of province for Guangdong:
return await db.collection('china')
.where({
province:"广东"
})
.remove()
Clicking on the button to call the chinadata cloud function in the emulator allows you to see the object returned by the cloud function in the console, which contains stats: s removed: 22, i.e. 22 data deleted.
Update multiple records collection.update
We can change the code in the previously built chinadata cloud function exports.main s async (event, context) to the following, that is, first query the record of the province of provance for Hubei, and update the record with a field English province name pro-en:
return await db.collection('china')
.where({
province:"湖北"
})
.update({
data: {
"pro-en": "Hubei"
},
})
It should be noted here that the pro-en field was not previously available, through College.update not only to play an update role, but also to add the field in bulk and assign values, that is, when the record has the same field updated, not added;
If you want to add a _openid to the imported data, you can't do it with a cloud function, because the cloud function doesn't have a user's login state. Before we can add openid to a record, we need to call a cloud function on a small program, such as login to return openid, and then pass the value of openid to the chinadata cloud function.
Earlier, we've looked at 5 methods for building query conditions based on collection references, as well as some request methods, and let's look at four request methods for referring to Document based on collection records: get a single record data Document.get (), delete a single record Document.remove (), update a single record Document.update(), R eplace updating a single record, Document.set(). In the same way as Action-based, the former addition and deletion check can be bulk-based, while Document-based is an operation of a single record.
Records in the query collection collection are often used to get lists of articles, information, goods, products, and so on, while field values in querying individual record docs are often used for details in those lists. If you need to add or censor field values for a record in development, it is recommended that you use the program to make a rule-based build when you create a record in order to make it easier for the program to find the corresponding record based on_id _id.
Each record in the collection has an _id field to uniquely flag a record, and _id's data format can be 2000 number numbers or string strings. T his _id can be customized, and a very long string is automatically generated when the imported or written record is not customized. The field field value of the query record doc is based _id value.
Technical documentation: Get a single record data Document.get().
For example, if we query the data of an article in a daily newspaper (that is, one of the records.js), we use the developer tool zhihudaily page's onLoad lifecycle function to enter the following code (db don't repeat the declaration):
db.collection('zhihu_daily').doc("daily9718006")
.get()
.then(res => {
console.log('单个记录的值',res.data)
})
.catch(err => {
console.error(err)
})
},
If the data of the collection is imported, then _id is automatically generated, the automatically generated _id is the string, so doc uses single quotes (double quotes are also available Oh), if you customize the _id is the number type, such as the custom _id for 20191125, the query is doc (20191125), this is just the basic knowledge.
Technical documentation: Delete a single record Document.remove().
removeDaily(){
db.collection('zhihu_daily').doc("daily9718006")
.remove()
.then(console.log)
.catch(console.error)
}
Technical documentation: Update a single record Document.update().
updateDaily(){
db.collection('zhihu_daily').doc("daily9718006")
.update({
data:{
title: "【知乎日报】元素,生生不息的宇宙诸子",
}
})
},
Technical documentation: Replace and update a single record Document.set().
setDaily(){
db.collection('zhihu_daily').doc("daily9718006")
.set({
data: {
"title": "为什么狗会如此亲近人类?",
"images": [
"https://pic4.zhimg.com/v2-4cab2fbf4fe9d487910a6f2c54ab3ed3.jpg"
],
"id": 9717547,
"url": "https://daily.zhihu.com/story/9717547",
"image": "https://pic4.zhimg.com/v2-60f220ee6c5bf035d0eaf2dd4736342b.jpg",
"share_url": "http://daily.zhihu.com/story/9717547",
"body": "<p>让狗从凶猛的野兽变成忠实的爱宠,涉及了宏观与微观上的两层故事:我们如何在宏观上驯养了它们,以及这些驯养在生理层面究竟意味着什么。</p>\r\n<p><img class=\"content-image\" src=\"http://pic1.zhimg.com/70/v2-4147c4b02bf97e95d8a9f00727d4c184_b.jpg\" alt=\"\"></p>\r\n<p>狗是灰狼(Canis lupus)被人类驯养后形成的亚种,至少可以追溯到 1 万多年以前,是人类成功驯化的第一种动物。在这漫长的岁月里,人类的定向选择强烈改变了这个驯化亚种的基因频率,使它呈现出极高的多样性,尤其体现在生理形态上。</p>"
}
})
}