Aggregate.unwind
1. Interface Description
Function: Splits documents using each element in the specified array field. After splitting, a single document becomes one or more documents, each corresponding to an element in the array.
Declaration: Two forms
- The parameter is a field name
unwind(<field name>)
- The parameter is an object
unwind({ path: <field name>, includeArrayIndex: <string>, preserveNullAndEmptyArrays: <boolean> })
2. Input Parameters
Parameter | Type | Required | Description |
---|---|---|---|
path | string | Yes | Field name of the array to be split, must start with $ . |
includeArrayIndex | string | No | Optional. Pass in a new field name to store the array index. The new field name must not start with $ . |
preserveNullAndEmptyArrays | boolean | Yes | If set to true , documents will still be output when the field specified in path is null , an empty array, or the field does not exist. If set to false , unwind will not output these documents. Default is false . |
3. Response
Parameter | Type | Required | Description |
---|---|---|---|
- | Aggregate | Yes | Aggregation object |
4. Sample Code
Splitting Arrays
Assume we have a products
collection containing the following data:
{ "_id": "1", "product": "tshirt", "size": ["S", "M", "L"] }
{ "_id": "2", "product": "pants", "size": [] }
{ "_id": "3", "product": "socks", "size": null }
{ "_id": "4", "product": "trousers", "size": ["S"] }
{ "_id": "5", "product": "sweater", "size": ["M", "L"] }
We split these documents based on the size
field.
const tcb = require("@cloudbase/node-sdk");
const app = tcb.init({
env: "xxx",
});
const db = app.database();
exports.main = async (event, context) => {
const res = await db.collection("products").aggregate().unwind("$size").end();
console.log(res.data);
};
The output is as follows:
{ "_id": "1", "product": "tshirt", "size": "S" }
{ "_id": "1", "product": "tshirt", "size": "M" }
{ "_id": "1", "product": "tshirt", "size": "L" }
{ "_id": "4", "product": "trousers", "size": "S" }
{ "_id": "5", "product": "sweater", "size": "M" }
{ "_id": "5", "product": "sweater", "size": "L" }
Preserving the Original Array Index After Splitting
After splitting the documents based on the size
field, we want to preserve the original array index in a new index
field.
const tcb = require("@cloudbase/node-sdk");
const app = tcb.init({
env: "xxx",
});
const db = app.database();
exports.main = async (event, context) => {
const res = await db
.collection("products")
.aggregate()
.unwind({
path: "$size",
includeArrayIndex: "index",
})
.end();
console.log(res.data);
};
The output is as follows:
{ "_id": "1", "product": "tshirt", "size": "S", "index": 0 }
{ "_id": "1", "product": "tshirt", "size": "M", "index": 1 }
{ "_id": "1", "product": "tshirt", "size": "L", "index": 2 }
{ "_id": "4", "product": "trousers", "size": "S", "index": 0 }
{ "_id": "5", "product": "sweater", "size": "M", "index": 0 }
{ "_id": "5", "product": "sweater", "size": "L", "index": 1 }
Preserving Documents with Empty Fields
Note that there are two special rows of null value data in our collection:
...
{ "_id": "2", "product": "pants", "size": [] }
{ "_id": "3", "product": "socks", "size": null }
...
If you want to preserve documents where size
is an empty array, null, or the size
field does not exist in the output, you can use the preserveNullAndEmptyArrays
parameter.
const tcb = require("@cloudbase/node-sdk");
const app = tcb.init({
env: "xxx",
});
const db = app.database();
exports.main = async (event, context) => {
const res = await db
.collection("products")
.aggregate()
.unwind({
path: "$size",
preserveNullAndEmptyArrays: true,
})
.end();
console.log(res.data);
};
The output is as follows:
{ "_id": "1", "product": "tshirt", "size": "S" }
{ "_id": "1", "product": "tshirt", "size": "M" }
{ "_id": "1", "product": "tshirt", "size": "L" }
{ "_id": "2", "product": "pants", "size": null }
{ "_id": "3", "product": "socks", "size": null }
{ "_id": "4", "product": "trousers", "size": "S" }
{ "_id": "5", "product": "sweater", "size": "M" }
{ "_id": "5", "product": "sweater", "size": "L" }