Docs 菜单

Docs 主页Atlas App Services

Atlas Functions

在此页面上

  • 概述
  • 如何编写函数
  • 用户和系统函数
  • 定义函数
  • 调用函数
  • 约束

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 使用 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 的文档:

←