Database
Basic Concepts
Collection
A collection is a set of documents. You can obtain a reference to a specified collection using db.collection(name)
. The following operations can be performed on a collection:
Type | Interface | Description |
---|---|---|
Write | add | Add document (trigger request) |
Count | count | Get the count of matching documents |
Read | get | Get documents in a collection. If a where clause is used to define query conditions, the matching result set will be returned (triggers a request) |
Reference | doc | Get a reference to the document with the specified id in this collection |
Query Conditions | where | Filter matching documents by specifying conditions, which can be used with query operators (eq, gt, in, ...) |
skip | Skips a specified number of documents, commonly used for pagination by passing an offset value | |
orderBy | Sorting method | |
limit | Limits the number of documents in the returned result set, with a default value and a maximum value (maximum limit is 1000) | |
field | Specifies the fields to return |
Query and update operators are used to specify conditions that fields must satisfy in where
, and can be accessed via the db.command
object.
Record / Document
A document is a storage unit in a database collection, represented as a json object in cloud development. You can obtain a reference to a document with a specified id in a given collection using db.collection(collectionName).doc(docId)
. The following operations can be performed on a document:
Interface | Description | |
---|---|---|
Write | set | Overwrite document |
update | Partial update of a document (triggers a request) | |
remove | Delete document (triggers a request) | |
Read | get | Get document (triggers a request) |
Query Command
Query operators are used to construct query conditions. The following operators are all attached to db.command
Type | Interface | Description |
---|---|---|
Comparison Operator | eq | Field == |
neq | Field != | |
gt | Field > | |
gte | Field >= | |
lt | Field < | |
lte | Field <= | |
in | Field value in array | |
nin | Field value not in array | |
Logical Operator | and | Indicates that all specified conditions must be satisfied simultaneously |
or | Indicates that at least one of the specified conditions must be satisfied |
Update Command
Update operators are used to construct update operations. The following operators are all attached to db.command
Type | Interface | Description |
---|---|---|
Update Operator | set | Sets a field equal to a specified value |
inc | Instructs the field to increment by a specified value | |
mul | Instructs the field to multiply by a specified value | |
remove | Remove a field | |
push | Appends elements to the end of an array, supporting passing in either a single element or an array | |
pop | Removes the last element from an array | |
shift | Removes the first element from an array. Usage is the same as pop | |
unshift | Adds elements to the beginning of an array, supports passing in either a single element or an array. Usage is the same as push |
Getting the Database Instance
Note: No parameters are required; returns the database instance.
import cloudbase from "@cloudbase/js-sdk";
const app = cloudbase.init({
env: "xxxx-yyy",
});
const db = app.database();
Getting the Collection Reference
Note: Accepts a name parameter specifying the collection name to be referenced.
// Get the reference of the `user` collection
import cloudbase from "@cloudbase/js-sdk";
const app = cloudbasae.init({
env: "xxxx-yyy",
});
const db = app.database();
const collection = db.collection("user");
Query Operators
eq
Indicates that a field equals a value. The eq
operator accepts a literal, which can be number
, boolean
, string
, object
, or array
.
For example, to filter out all articles published by oneself, besides using the object-passing approach:
const myOpenID = "xxx";
db.collection("articles").where({
_openid: myOpenID,
});
can also use the command:
const _ = db.command;
const myOpenID = "xxx";
db.collection("articles").where({
_openid: _.eq(openid),
});
Note that the eq
operator offers greater flexibility than the object approach and can be used to represent cases where a field equals an object, for example:
// This syntax indicates matching both stat.publishYear == 2018 and stat.language == 'zh-CN'
db.collection("articles").where({
stat: {
publishYear: 2018,
language: "zh-CN",
},
});
// This syntax indicates that the stat object equals { publishYear: 2018, language: 'zh-CN' }
const _ = db.command;
db.collection("articles").where({
stat: _.eq({
publishYear: 2018,
language: "zh-CN",
}),
});
neq
Indicates that a field does not equal a value. The neq
operator accepts a literal, which can be number
, boolean
, string
, object
, or array
.
For example, to filter out computers whose brand is not X:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
brand: _.neq("X"),
},
});
gt
The field is greater than the specified value.
For example, to filter out computers with a price greater than 2000:
const _ = db.command;
db.collection("goods").where({
category: "computer",
price: _.gt(2000),
});
gte
The field is greater than or equal to the specified value.
lt
The field is less than the specified value.
lte
The field is less than or equal to the specified value.
in
The field value is within the given array.
To filter out computer products with memory of 8g or 16g:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
memory: _.in([8, 16]),
},
});
nin
The field value is not in the given array.
To filter out computer products with memory not being 8g or 16g:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
memory: _.nin([8, 16]),
},
});
and
Means that two or more specified conditions must be satisfied simultaneously.
For example, filter out computer products with memory greater than 4g and less than 32g:
Streaming syntax:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
memory: _.gt(4).and(_.lt(32)),
},
});
Prefix syntax:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
memory: _.and(_.gt(4), _.lt(32)),
},
});
or
Means that at least one of the specified conditions must be satisfied. For example, filter out computers with a price less than 4000 or 6000-8000:
Streaming syntax:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
price: _.lt(4000).or(_.gt(6000).and(_.lt(8000))),
},
});
Prefix syntax:
const _ = db.command;
db.collection("goods").where({
category: "computer",
type: {
price: _.or(_.lt(4000), _.and(_.gt(6000), _.lt(8000))),
},
});
If you want to perform a cross-field "OR" operation: (e.g., filter out computers with 8g memory OR 3.2 ghz cpu)
const _ = db.command;
db.collection("goods").where(
_.or(
{
type: {
memory: _.gt(8),
},
},
{
type: {
cpu: 3.2,
},
}
)
);
RegExp
Filter based on regular expressions
For example, the following can filter out documents where the version
field starts with "digit+s", case-insensitively:
// You can directly use regular expressions
db.collection('articles').where({
version: /^\ds/i
})
// Or
db.collection('articles').where({
version: new db.RegExp({
regexp: '^\\ds' // The regular expression is /^\ds/, after escaping, it becomes '^\\ds'
options: 'i' // i indicates case-insensitive
})
})
Update Command
set
Description: Used to set a field equal to a specified value. This method, compared to passing a plain JS object, has the advantage of being able to specify that a field equals an object.
Sample Code:
// The following method will only update style.color to red, rather than updating style to { color: 'red' }, meaning it does not affect other fields in style
db.collection("todos")
.doc("doc-id")
.update({
style: {
color: "red",
},
});
// The following method updates style to { color: 'red', size: 'large' }
const _ = db.command;
db.collection("todos")
.doc("doc-id")
.update({
style: _.set({
color: "red",
size: "large",
}),
});
inc
Description: Used to indicate that a field increments by a certain value. This is an atomic operation. The advantage of using this operation command instead of reading the data first, then adding to it, and finally writing it back is:
Remarks:
- Atomicity: When multiple users write simultaneously, the database increments the field by one for each operation, eliminating the risk of later writes overwriting earlier ones.
- Reduces one network request: eliminates the need for read-before-write operations.
The same applies to the subsequent mul instruction.
Sample Code:
const _ = db.command;
db.collection("user")
.where({
_openid: "my-open-id",
})
.update({
count: {
favorites: _.inc(1),
},
})
.then(function (res) {});
mul
Description: Used to multiply a field by a specified value.
remove
Update command. Used to indicate the deletion of a field. For example, when a user deletes the rating in one of their product reviews:
const _ = db.command;
db.collection("comments")
.doc("comment-id")
.update({
rating: _.remove(),
})
.then(function (res) {});
push
Appends elements to the end of an array, supporting passing in either a single element or an array.
const _ = db.command;
db.collection("comments")
.doc("comment-id")
.update({
// users: _.push('aaa')
users: _.push(["aaa", "bbb"]),
})
.then(function (res) {});
pop
Removes the last element from an array.
const _ = db.command;
db.collection("comments")
.doc("comment-id")
.update({
users: _.pop(),
})
.then(function (res) {});
unshift
Adds elements to the beginning of an array, supports passing in either a single element or an array. Usage is the same as push
shift
Removes the first element from an array. Usage is the same as pop
Build query conditions
Supports operations such as where()
, limit()
, skip()
, orderBy()
, get()
, update()
, field()
, count()
, and more.
The request is only actually sent when get()
or update()
is called.
where
Description: Sets the filter conditions. where can accept an object as a parameter, indicating to filter out documents that have the same key-value pairs as the passed object.
Input parameters: None
For example, to filter out all products of computer type with 8g memory:
db.collection("goods").where({
category: "computer",
type: {
memory: 8,
},
});
To express more complex queries, you can use advanced query commands, for example, to filter out all computer products with memory greater than 8g:
const _ = db.command; // Get the command
db.collection("goods").where({
category: "computer",
type: {
memory: _.gt(8), // which means greater than 8
},
});
limit
Description: Specifies the upper limit for the number of query result sets.
Input parameters:
Parameter | Type | Required | Description |
---|---|---|---|
- | Integer | Yes | Limits the displayed number (the maximum limit is 1000) |
Use Case
collection
.limit(1)
.get()
.then(function (res) {});
skip
Description: Specifies to return query results starting after a specified index, commonly used for pagination. Input parameters:
Parameter | Type | Required | Description |
---|---|---|---|
- | Integer | Yes | Number of entries to skip |
Example Code
collection
.skip(4)
.get()
.then(function (res) {});
field
Description: Specifies the fields to be returned in the documents within the query results.
Input parameters:
Parameter | Type | Required | Description |
---|---|---|---|
- | object | Yes | Fields to filter: set to false to exclude, true to include. |
Example Code
collection.field({ age: true });
Note: The field method accepts a required object to specify the fields to be returned. Each key in the object represents a field to include or exclude, and the value (true|false or 1|-1) indicates whether to return the field.
orderBy
Description: Specifies the sort criteria for queries.
Input parameters:
Parameter | Type | Required | Description |
---|---|---|---|
field | string | Yes | Field to sort by |
orderType | string | Yes | Sort order: asc (ascending) or desc (descending) |
Note: The method accepts a required string parameter fieldName to define the field to sort by, and a string parameter order to specify the sort direction. order can only be set to asc or desc.
To sort nested fields, use dot notation to connect them. For example, style.color represents the nested color field within the style field.
It also supports sorting by multiple fields. Simply call orderBy multiple times. The sort order for multiple fields will follow the sequence of the orderBy calls.
Example Code
collection
.orderBy("name", "asc")
.get()
.then(function (res) {});
add
1. Interface Description
Function: Insert a document
Interface declaration: collection.add(object: Object): Promise<Object>
Note: The set method can also be used to add documents. Please refer to the set method in the document update section.
Example:
2. Input Parameters
Parameter | Type | Required | Description |
---|---|---|---|
data | object | Yes | {_id: '10001', 'name': 'Ben'} and _id is optional |
3. Output Parameters
Field | Type | Required | Description |
---|---|---|---|
code | string | No | Status code, not returned if the operation is successful |
message | string | No | Error description |
4. Sample Code
collection
.add({
name: "Ben",
})
.then((res) => {})
.catch((e) => {});
get
1. Interface Description
Interface Function: Get the database query result.
Interface declaration: get(): Promise<Object>
Note: If no limit is specified in get(), the first 100 records are returned by default, and a maximum of the first 100 records will be returned.
2. Input Parameters
Null
3. Output Parameters
Field | Type | Required | Description |
---|---|---|---|
code | string | No | Status code, not returned if the operation is successful |
message | string | No | Error description |
data | object | No | Query result |
requestId | string | Yes | Request ID, used for error troubleshooting |
4. Sample Code
collection
.where({
category: "computer",
type: {
memory: 8,
},
})
.get()
.then((res) => {})
.catch((e) => {});
count
1. Interface Description
Interface Function: Get the count of database query results.
Interface declaration: cout(): Promise<Object>
2. Input Parameters
Null
3. Output Parameters
Field | Type | Required | Description |
---|---|---|---|
code | string | No | Status code, not returned if the operation is successful |
message | string | No | Error description |
total | Integer | No | Count result |
requestId | string | No | Request ID, used for error troubleshooting |
4. Sample Code
db.collection("goods")
.where({
category: "computer",
type: {
memory: 8,
},
})
.count()
.then(function (res) {
const total = res.total; // The number of documents that meet the criteria
});
remove
1. Interface Description
Function: Delete a document
Interface declaration: remove(): Promise<Object>
2. Input Parameters
None
3. Output Parameters
Field | Type | Required | Description |
---|---|---|---|
code | string | No | Status code, not returned if the operation is successful |
message | string | No | Error description |
deleted | Inteter | No | Number of deleted documents |
requestId | string | Yes | Request ID, used for error troubleshooting |
4. Sample Code
Method 1: Delete by specifying the document ID
collection.doc(_id).remove()
collection
.doc("xxx")
.remove()
.then((res) => {
console.log(`${res.deleted} docs deleted`);
})
.catch((e) => {});
Method 2: Query documents by condition and then delete them in batch directly
// Delete documents where field a is greater than 2
collection
.where({
a: _.gt(2),
})
.remove()
.then(function (res) {
const deleted = res.deleted;
});
update / set
1. Interface Description
Interface Function: Update documents
Interface Declaration:
update(object: <Object\>): Promise<Object>
set(object: <Object\>): Promise<Object>
Note: Both update and set can be used to update documents. The difference is that the set method creates a new document when the target document doesn't exist, while the update method does nothing and returns updated as 0.
2. Input Parameters
Field | Type | Required | Description |
---|---|---|---|
- | <Object> | Yes | Definition of the replacement document |
3. Output Parameters
Field | Type | Required | Description |
---|---|---|---|
code | string | No | Status code, not returned if the operation is successful |
message | string | No | Error description |
updated | Integer | No | Number of affected documents |
upsertedId | string | No | id of the inserted document |
requestId | string | Yes | Request ID, used for error troubleshooting |
4. Sample Code
Update the specified document
// Update the specified document
collection
.doc("doc-id")
.update({
name: "Hey",
})
.then(function (res) {});
Update the document, or create it if it does not exist
// Update a single document
collection
.doc("doc-id")
.set({
name: "Hey",
})
.then(function (res) {});
// Batch update documents
collection
.where({ name: _.eq("hey") })
.update({
age: 18,
})
.then(function (res) {});
GEO Geographic Location
Note: If you need to search fields of geolocation type, you must create a geolocation index.
GEO Data Type
Point
Used to represent a geographical location point, uniquely identifying a point using latitude and longitude. This is a special data storage type.
Signature: Point(longitude: number, latitude: number)
Example:
new db.Geo.Point(longitude, latitude);
LineString
Used to represent a geographic path, which is a line segment composed of two or more Point
s.
Signature: LineString(points: Point[])
Example:
new db.Geo.LineString([
new db.Geo.Point(lngA, latA),
new db.Geo.Point(lngB, latB),
// ...
]);
Polygon
Used to represent a geographical polygon (with or without holes), which is a geometric shape composed of one or more closed-loop LineString
s.
A Polygon
formed by a single ring is a polygon without holes, while one formed by multiple rings is a polygon with holes. For a polygon (Polygon
) composed of multiple rings (LineString
), the first ring is the outer ring and all others are inner rings (holes).
Signature: Polygon(lines: LineString[])
Example:
new db.Geo.Polygon([
new db.Geo.LineString(...),
new db.Geo.LineString(...),
// ...
])
MultiPoint
Used to represent a collection of multiple Point
s.
Signature: MultiPoint(points: Point[])
Example:
new db.Geo.MultiPoint([
new db.Geo.Point(lngA, latA),
new db.Geo.Point(lngB, latB),
// ...
]);
MultiLineString
Used to represent a collection of multiple geographic paths LineString
s.
Signature: MultiLineString(lines: LineString[])
Example:
new db.Geo.MultiLineString([
new db.Geo.LineString(...),
new db.Geo.LineString(...),
// ...
])
MultiPolygon
Used to represent a collection of multiple geographic Polygon
s.
Signature: MultiPolygon(polygons: Polygon[])
Example:
new db.Geo.MultiPolygon([
new db.Geo.Polygon(...),
new db.Geo.Polygon(...),
// ...
])
GEO operators
geoNear
Find documents with field values near a given point, sorted from nearest to farthest.
Signature:
db.command.geoNear(options: IOptions)
interface IOptions {
geometry: Point // Geographic location of a point
maxDistance?: number // Optional. Maximum distance in meters.
minDistance?: number // Optional. Minimum distance in meters.
}
Example:
db.collection("user").where({
location: db.command.geoNear({
geometry: new db.Geo.Point(lngA, latA),
maxDistance: 1000,
minDistance: 0,
}),
});
geoWithin
Find documents with field values within the specified Polygon / MultiPolygon, without sorting.
Signature:
db.command.geoWithin(IOptions);
interface IOptions {
geometry: Polygon | MultiPolygon; // Geographic location
}
Example:
// A closed area
const area = new Polygon([
new LineString([
new Point(lngA, latA),
new Point(lngB, latB),
new Point(lngC, latC),
new Point(lngA, latA),
]),
]);
// Search for users whose location field is within this area
db.collection("user").where({
location: db.command.geoWithin({
geometry: area,
}),
});
geoIntersects
Find documents where the field value intersects the given geographic shape.
Signature:
db.command.geoIntersects(IOptions);
interface IOptions {
geometry:
| Point
| LineString
| MultiPoint
| MultiLineString
| Polygon
| MultiPolygon; // Geographic area
}
Example:
// A path
const line = new LineString([new Point(lngA, latA), new Point(lngB, latB)]);
// Search for users whose location intersects this path
db.collection("user").where({
location: db.command.geoIntersects({
geometry: line,
}),
});
Database real-time push
Watch for documents matching the query conditions in the specified collection and obtain detailed change information of the documents through the onchange callback. (The where parameter is the query condition. Refer to Query Documentation)
import cloudbase from "@cloudbase/js-sdk";
const app = cloudbase.init({
env: "tcbenv-mPIgjhnq",
});
const db = app.database();
const _ = db.command;
const collection = db.collection("collName"); // collName should be the collection name in the current environment
let ref = collection.where({ test: _.gt(0) }).watch({
onChange: (snapshot) => {
console.log("Received snapshot**********", snapshot);
},
onError: (error) => {
console.log("Received error**********", error);
},
});
Watching a single document can also be done using the form doc('docId').watch()
let ref = collection.doc("one docId").watch({
onChange: (snapshot) => {
console.log("Received snapshot**********", snapshot);
},
onError: (error) => {
console.log("Received error**********", error);
},
});
Manually close the listener, and the current listener will no longer receive push notifications.
ref.close().then((result) => {
// The listener has been closed
});