今天是最後一天介紹陣列操作符,當初在查資料的時候,完全沒有想到這個主題可以寫三天,但事實上我只有拉出,我比較有興趣的操作符來說明。
被我跳過的操作符,例如:
大家有興趣可以自行點選連結,去官網看一下。
接下來進入正題,先用一個比較簡單的例子,一次介紹$slice
(選取特定範圍的陣列資料) 、$reverseArray
(將陣列反轉)、$indexOfArray
(查詢資料在陣列的位置)三種操作符。
假設現在有一筆英文成績的資料
{
_id: 1,
english: [58, 96, 88, 23, 69, 100, 45, 87]
}
對它執行以下指令
test.aggregate([
{
$project: {
slice_array: { $slice: ["$english", 1, 3] },
reverse: { $reverseArray: "$english" },
find_100: { $indexOfArray: ["$english", 100] }
}
}
]);
// 最後回傳的資料
{
_id: 1,
slice_array: [96, 88, 23],
reverse: [87, 45, 100, 69, 23, 88, 96, 58],
find_100: 5
}
其中$slice的指令有兩種寫法,一種是直接指定切割的範圍,{ $slice: [ <array>, <position>, <n> ] }
,透過<position>
選擇要從陣列哪一個位置開始切割,搭配<n>
決定要選取幾個資料出來。
或是直接寫{ $slice: [ <array>, <n> ] }
,透過<n>
是正數或負數,決定要從陣列的開頭或結尾選出n筆資料。
另外$indexOfArray除了用{ $indexOfArray: [ <array expression>, <search expression> ] }
這種比較簡單的寫法外,後面還可以再多待兩個參數,決定要搜尋範圍,例如:{ $indexOfArray: ["$english", 100, 1, 4] }
,這時候會從陣列1~4的位置看有沒有100這個值,如果剛好找不到資料,會回傳-1。
再來如果我們想要快速建立陣列資料,可以透過$range
這個操作符,後面會帶入一個陣列,第一個參數決定回傳新陣列的開頭數值,第二個參數決定結尾的數值,第三個參數決定要新陣列每一個元素的數值間隔。
詳細範例如下
db.collection.aggregate([
{
$project: {
new_array_1: { $range: [0, 10, 2] },
new_array_2: { $range: [10, 0, -1] }
}
}
]);
// 最後回傳的資料
{
_id: 1,
new_array_1: [0, 2, 4, 6, 8],
new_array_2: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
}
最後來介紹$reduce
,它可以幫助我們快速使用陣列的每一筆資料,進行運算。
假設數學老師一道題目,要求學生計算1到10連加以及連乘的結果,這時候我們可以用以下指令計算。
db.collection.aggregate([
{
$addFields: {
new_array: { $range: [1, 10, 1] } // 先建立一個陣列,裡面有1~10
}
},
{
$project: {
result: {
$reduce: {
input: "$new_array", // 帶入要進行運算的陣列
initialValue: { sum: 0, multiply: 1 }, // 設定一開始運算的初始值
in: { // 寫入要運算的程式碼
// "$$value" 代表前一次計算的結果,"$$this" 代表目前陣列的值
sum: { $add: ["$$value.sum", "$$this"] },
multiply: { $multiply: ["$$value.multiply", "$$this"] }
}
}
}
}
}
]);
// 最後回傳的結果
{
_id: 1,
result: { sum: 45, multiply: 362880 }
}
讓我們用計算連加的過程,來詳細說明上方程式碼是如何運行。
一開始我們有設定初始值是{ sum: 0, multiply: 1 },因此第一次在下方in
計算的時候,$$value.sum
的值會是0,這時會取出陣列第一個元素1,會用$$this
做代表。
因為我們有寫{ $add: ["$$value.sum", "$$this"] },所以0+1=1,在下一輪時$$value.sum
的值就會變成1,在與第二個陣列元素2做相加,接下來的就一直延續以上步驟,直到把整個陣列都遍歷過一次,最後回傳計算結果。
本篇文章同步放在我的部落格,大家有空可以進來逛逛