Atlas Functions
GraphQL 已弃用。了解更多。
概述
Atlas Function 是一段服务器端 JavaScript 代码,您编写该代码来定义应用的行为。您可以直接从客户端应用调用应用的函数,也可以定义自动集成和调用函数的服务。
函数可以调用其他函数,并包含内置客户端,用于处理 MongoDB Atlas 集群中的数据。这些函数还包括有用的全局实用程序,支持常见的 Node.js 内置模块,并且可以从 npm 注册表中导入和使用外部包。
exports = function(name) { return `Hello, ${name ?? "stranger"}!` }
函数是无服务器性质的
调用函数时,应用程序会将请求路由到托管应用程序服务器,该服务器为代码求值并返回结果。此模型使函数具备无服务器性质,也即您不必部署和管理服务器来运行代码。您只需编写函数源代码,然后应用程序处理执行环境。
函数有上下文
函数会在反映其执行环境的上下文中运行。该上下文包括调用该函数的用户、如何进行调用以及调用该函数时应用的状态。您可以使用上下文来运行特定于用户的代码,并与应用的其他部分配合使用。
要了解有关如何使用函数上下文的详情,请参阅上下文。
何时使用函数
函数可以运行您定义的任意 JavaScript 代码,这意味着您几乎可以在任何情况下使用这些函数。常见使用案例包括低延迟、短时间运行的任务,如数据移动、转换和验证。您还可以使用它们连接外部服务,从客户端应用程序中抽象出实施细节。
除了直接调用的函数之外,您还可以为各种服务编写函数,例如 HTTPS endpoints、Atlas Triggers和 GraphQL 自定义解析程序(GraphQL 已弃用,了解更多)。这些服务会自动调用函数来处理特定event。例如,每当数据库触发器观察到变更event时,它就会将该变更event作为参数来调用关联的函数。然后,您可以在trigger函数中访问变更event中的信息并做出适当响应。
提示
另请参阅:
如何编写函数
函数的代码本质上是一个已命名的 JavaScript 源文件,这意味着您可在单个函数文件中定义多个 JavaScript 函数。该文件必须导出一个 JavaScript 函数,以作为传入调用的入口点。按名称调用函数时,实际上是在调用该函数的源文件中分配给 exports
的 JavaScript 函数。
例如,以下简易函数可接受 name
参数、添加日志消息,并为所提供的姓名返回一句问候语:
exports = function Hello(name) { console.log(`Said hello to ${name}`); return `Hello, ${name}!`; };
您可以使用现代 JavaScript 语法和导入包来定义更多复杂函数:
// You can use ES6 arrow functions const uppercase = (str) => { return str.toUpperCase(); }; // You can use async functions and await Promises exports = async function GetWeather() { // You can get information about the user called the function const city = context.user.custom_data.city; // You can import Node.js built-ins and npm packages const { URL } = require("url"); const weatherUrl = new URL("https://example.com"); weatherUrl.pathname = "/weather"; weatherUrl.search = `?location="${city}"`; // You can send HTTPS requests to external services const weatherResponse = await context.http.get({ url: url.toString(), headers: { Accept: ["application/json"], }, }); const { current, forecasts } = JSON.parse(weatherResponse.body.text()); return [ `Right now ${uppercase(city)} is ${current.temperature}°F and ${current.weather}.`, `Here's the forecast for the next 7 days:`, forecasts .map((f) => `${f.day}: ${f.temperature}°F and ${f.weather}`) .join("\n "), ].join("\n"); };
Right now NEW YORK CITY is 72°F and sunny. Here's the forecast for the next 7 days: Tuesday: 71°F and sunny Wednesday: 72°F and sunny Thursday: 73°F and partly cloudy Friday: 71°F and rainy Saturday: 77°F and sunny Sunday: 76°F and sunny Monday: 74°F and sunny
函数会自动将返回值序列化为扩展 JSON。这对于保留类型信息很有用,但可能不是应用程序所期望的。
例如,从以下函数返回的对象中的值将转换为结构化 EJSON 值:
exports = function() { return { pi: 3.14159, today: new Date(), } }
{ "pi": { "$numberDouble": "3.14159" }, "today": { "$date": { "$numberLong": "1652297239913" } } }
要返回标准 JSON 形式的值,请对该值调用 JSON.stringify()
,然后返回字符串化后的结果:
exports = function() { return JSON.stringify({ pi: 3.14159, today: new Date(), }) }
"{\"pi\":3.14159,\"today\":\"2022-05-11T19:27:32.207Z\"}"
用户和系统函数
函数可以在两个上下文中运行,具体取决于它们的配置和调用方式:
系统功能以系统用户而非特定应用程序用户的身份运行。系统函数可以完全访问 MongoDB CRUD 和 Aggregation API,并绕过所有规则和模式验证。
注意
动态 context.user 参考
对 context.user 的引用始终解析为调用函数的经过身份验证的用户(如果有),即使该函数作为系统函数运行亦是如此。要确定某个函数是否作为系统函数运行,请调用 context.runningAsSystem()
。
如果函数没有经过身份验证的用户调用即执行(例如在Trigger 或 Webhook 中),则动态引用将解析为没有 id
或其他关联数据的系统用户。
定义函数
您可以从 App Services 用户界面或通过使用 App Services CLI 或 GitHub 部署导入函数配置和源代码来创建和管理应用程序中的函数。
调用函数
您可以通过其他函数、连接的客户端应用程序或 App Services CLI 调用某个函数。
本部分中的示例演示了如何调用名为 sum
的简易函数,该函数可接受两个参数、添加这两个参数并返回结果:
// sum: adds two numbers exports = function sum(a, b) { return a + b; };
从函数调用
您可以通过context.functions接口从另一个函数调用一个函数,该接口可在任何函数中用作全局变量。其中包括 HTTPS endpoints、Atlas Triggers 和 GraphQL 自定义解析程序(已弃用,了解详情)。被调用函数在与调用它的函数相同的上下文中运行。
// difference: subtracts b from a using the sum function exports = function difference(a, b) { return context.functions.execute("sum", a, -1 * b); };
从 App Services CLI 调用
可以通过 App Services CLI 使用 function run 命令调用函数。该命令以 EJSON 形式返回函数结果以及任何日志或错误消息。
appservices function run \ --function=sum \ --args=1 --args=2
默认情况下,函数在系统上下文中运行。要在特定用户的上下文中调用函数,请在--user
参数中包含其用户 ID。
appservices function run \ --function=sum \ --args=1 --args=2 \ --user=61a50d82532cbd0de95c7c89
从规则表达式调用
可以使用 %function
操作符从规则表达式调用函数。该操作符可计算出函数的返回值。如果函数抛出错误,则表达式的计算结果为 false
{ "numGamesPlayed": { "%function": { "name": "sum", "arguments": [ "%%root.numWins", "%%root.numLosses" ] } } }
通过 Realm SDK 调用
重要
使用函数时,确保对客户端数据进行清理,以防止代码注入。
您可以从使用 Realm SDK 连接的客户端应用程序或通过传输协议来调用函数。有关演示如何从客户端应用程序调用函数的代码示例,请参阅 Realm SDK 的文档:
约束
每个请求的函数运行时间上限为 300 秒,之后函数将超时并失效。
函数可能随时使用最多350 MB 的内存。
函数不能超过 1000 次异步操作。
函数支持最常用的 ES6+ 功能和 Node.js 内置模块,但不支持某些不常见或不适合无服务器工作负载的功能。有关详情,请参阅 JavaScript 支持。
函数可以使用25 网络 打开最多 个套接字 内置模块。
传入请求的最大大小限制为 18 MB。此限制适用于传递给函数的所有参数的总大小,以及以及任何请求标头或有效负载(如果通过 HTTPS 端点调用该函数)。