|
| 1 | +// $function operator - custom JavaScript functions in aggregation |
| 2 | +// The JavaScript code is passed as a string in the "body" field |
| 3 | + |
| 4 | +// Basic $function usage |
| 5 | +db.players.aggregate([ |
| 6 | + { $addFields: { |
| 7 | + isFound: { |
| 8 | + $function: { |
| 9 | + body: "function(name) { return name.length > 5; }", |
| 10 | + args: ["$name"], |
| 11 | + lang: "js" |
| 12 | + } |
| 13 | + } |
| 14 | + }} |
| 15 | +]) |
| 16 | + |
| 17 | +// $function with multiple arguments |
| 18 | +db.orders.aggregate([ |
| 19 | + { $addFields: { |
| 20 | + discount: { |
| 21 | + $function: { |
| 22 | + body: "function(price, quantity) { return price * quantity * 0.1; }", |
| 23 | + args: ["$price", "$quantity"], |
| 24 | + lang: "js" |
| 25 | + } |
| 26 | + } |
| 27 | + }} |
| 28 | +]) |
| 29 | + |
| 30 | +// $function with complex logic |
| 31 | +db.events.aggregate([ |
| 32 | + { $addFields: { |
| 33 | + category: { |
| 34 | + $function: { |
| 35 | + body: "function(score) { if (score >= 90) return 'A'; else if (score >= 80) return 'B'; else if (score >= 70) return 'C'; else return 'F'; }", |
| 36 | + args: ["$score"], |
| 37 | + lang: "js" |
| 38 | + } |
| 39 | + } |
| 40 | + }} |
| 41 | +]) |
| 42 | + |
| 43 | +// $function with no arguments |
| 44 | +db.items.aggregate([ |
| 45 | + { $addFields: { |
| 46 | + timestamp: { |
| 47 | + $function: { |
| 48 | + body: "function() { return new Date().toISOString(); }", |
| 49 | + args: [], |
| 50 | + lang: "js" |
| 51 | + } |
| 52 | + } |
| 53 | + }} |
| 54 | +]) |
| 55 | + |
| 56 | +// $function with array argument |
| 57 | +db.data.aggregate([ |
| 58 | + { $addFields: { |
| 59 | + processed: { |
| 60 | + $function: { |
| 61 | + body: "function(arr) { return arr.map(x => x * 2); }", |
| 62 | + args: ["$values"], |
| 63 | + lang: "js" |
| 64 | + } |
| 65 | + } |
| 66 | + }} |
| 67 | +]) |
| 68 | + |
| 69 | +// $function with multiline string (escaped) |
| 70 | +db.documents.aggregate([ |
| 71 | + { $addFields: { |
| 72 | + result: { |
| 73 | + $function: { |
| 74 | + body: "function(doc) {\n var sum = 0;\n for (var i = 0; i < doc.length; i++) {\n sum += doc[i];\n }\n return sum;\n}", |
| 75 | + args: ["$numbers"], |
| 76 | + lang: "js" |
| 77 | + } |
| 78 | + } |
| 79 | + }} |
| 80 | +]) |
| 81 | + |
| 82 | +// $accumulator operator - custom accumulator with JavaScript |
| 83 | +db.sales.aggregate([ |
| 84 | + { $group: { |
| 85 | + _id: "$category", |
| 86 | + customSum: { |
| 87 | + $accumulator: { |
| 88 | + init: "function() { return { sum: 0, count: 0 }; }", |
| 89 | + accumulate: "function(state, value) { return { sum: state.sum + value, count: state.count + 1 }; }", |
| 90 | + accumulateArgs: ["$amount"], |
| 91 | + merge: "function(state1, state2) { return { sum: state1.sum + state2.sum, count: state1.count + state2.count }; }", |
| 92 | + finalize: "function(state) { return state.sum / state.count; }", |
| 93 | + lang: "js" |
| 94 | + } |
| 95 | + } |
| 96 | + }} |
| 97 | +]) |
| 98 | + |
| 99 | +// $accumulator with initArgs |
| 100 | +db.transactions.aggregate([ |
| 101 | + { $group: { |
| 102 | + _id: "$accountId", |
| 103 | + balance: { |
| 104 | + $accumulator: { |
| 105 | + init: "function(initial) { return initial; }", |
| 106 | + initArgs: [0], |
| 107 | + accumulate: "function(state, amount, type) { return type === 'credit' ? state + amount : state - amount; }", |
| 108 | + accumulateArgs: ["$amount", "$type"], |
| 109 | + merge: "function(s1, s2) { return s1 + s2; }", |
| 110 | + lang: "js" |
| 111 | + } |
| 112 | + } |
| 113 | + }} |
| 114 | +]) |
| 115 | + |
| 116 | +// $accumulator without finalize |
| 117 | +db.metrics.aggregate([ |
| 118 | + { $group: { |
| 119 | + _id: "$source", |
| 120 | + values: { |
| 121 | + $accumulator: { |
| 122 | + init: "function() { return []; }", |
| 123 | + accumulate: "function(state, val) { state.push(val); return state; }", |
| 124 | + accumulateArgs: ["$value"], |
| 125 | + merge: "function(s1, s2) { return s1.concat(s2); }", |
| 126 | + lang: "js" |
| 127 | + } |
| 128 | + } |
| 129 | + }} |
| 130 | +]) |
| 131 | + |
| 132 | +// Combined $function and standard operators |
| 133 | +db.products.aggregate([ |
| 134 | + { $match: { inStock: true } }, |
| 135 | + { $addFields: { |
| 136 | + priceCategory: { |
| 137 | + $function: { |
| 138 | + body: "function(p) { return p < 10 ? 'cheap' : p < 100 ? 'moderate' : 'expensive'; }", |
| 139 | + args: ["$price"], |
| 140 | + lang: "js" |
| 141 | + } |
| 142 | + } |
| 143 | + }}, |
| 144 | + { $group: { _id: "$priceCategory", count: { $sum: 1 } } }, |
| 145 | + { $sort: { count: -1 } } |
| 146 | +]) |
| 147 | + |
| 148 | +// $function in $project stage |
| 149 | +db.users.aggregate([ |
| 150 | + { $project: { |
| 151 | + name: 1, |
| 152 | + maskedEmail: { |
| 153 | + $function: { |
| 154 | + body: "function(email) { var parts = email.split('@'); return parts[0].substring(0, 2) + '***@' + parts[1]; }", |
| 155 | + args: ["$email"], |
| 156 | + lang: "js" |
| 157 | + } |
| 158 | + } |
| 159 | + }} |
| 160 | +]) |
| 161 | + |
| 162 | +// $function with object argument |
| 163 | +db.records.aggregate([ |
| 164 | + { $addFields: { |
| 165 | + serialized: { |
| 166 | + $function: { |
| 167 | + body: "function(obj) { return JSON.stringify(obj); }", |
| 168 | + args: ["$metadata"], |
| 169 | + lang: "js" |
| 170 | + } |
| 171 | + } |
| 172 | + }} |
| 173 | +]) |
| 174 | + |
| 175 | +// $function returning object |
| 176 | +db.coordinates.aggregate([ |
| 177 | + { $addFields: { |
| 178 | + point: { |
| 179 | + $function: { |
| 180 | + body: "function(lat, lng) { return { type: 'Point', coordinates: [lng, lat] }; }", |
| 181 | + args: ["$latitude", "$longitude"], |
| 182 | + lang: "js" |
| 183 | + } |
| 184 | + } |
| 185 | + }} |
| 186 | +]) |
| 187 | + |
| 188 | +// Nested $function in $facet |
| 189 | +db.analytics.aggregate([ |
| 190 | + { $facet: { |
| 191 | + processed: [ |
| 192 | + { $addFields: { |
| 193 | + normalized: { |
| 194 | + $function: { |
| 195 | + body: "function(v, min, max) { return (v - min) / (max - min); }", |
| 196 | + args: ["$value", "$minValue", "$maxValue"], |
| 197 | + lang: "js" |
| 198 | + } |
| 199 | + } |
| 200 | + }} |
| 201 | + ], |
| 202 | + summary: [ |
| 203 | + { $group: { _id: null, total: { $sum: "$value" } } } |
| 204 | + ] |
| 205 | + }} |
| 206 | +]) |
0 commit comments