Docs Menu
Docs Home
/ /
Atlas Device SDKs
/

Call an Atlas Function

On this page

  • Before You Begin
  • Call a Function

You can call an Atlas Function from a client application using Atlas Device SDK. Functions are serverless JavaScript functions that let you define and execute server-side logic. These server-side Functions can run in the context of the authenticated user, and thus honor the rules, roles, and permissions that you have assigned to your data in Atlas.

For more information on configuring and writing Atlas Functions, refer to Atlas Functions in the App Services documentation.

  1. In an App Services App, define an Atlas Function.

  2. In your client project, initialize the App client.

  3. Then, authenticate a user. You access Functions through the user object.

The example on this page demonstrates calling an Atlas Function that takes two arguments, performs some work, and returns the result.

Important

Make sure to sanitize client data to protect against code injection when using Functions.

To call an Atlas Function, use the call_function() member function on the user object. Pass in the name of the function as a string for the first parameter. This function takes two arguments, which we provide as a string array of arguments.

The callback can provide an optional string result, or an optional error. In this example, we check that the result has a value.

To call an Atlas Function, use the Functions.CallAsync() method on the User object, passing in the name of the function as the first parameter and the arguments as the remaining parameters:

var bsonValue = await
user.Functions.CallAsync("sum", 2, 40);
// The result must now be cast to Int32:
var sum = bsonValue.ToInt32();
// Or use the generic overloads to avoid casting the BsonValue:
sum = await
user.Functions.CallAsync<int>("sum", 2, 40);

Note

The CallAsync() method returns a single BsonValue object, which you can deserialize after calling the function or by using the generic overload. Both of these approaches to deserialization are shown in the code above.

A BsonValue object can hold a single primitive value (as shown in the example above), or hold a complete BSON document. If you have a class that maps to the returned object, you can deserialize to that class by using the generic overload. For example, the following code calls a function that returns an object from a collection of "RealmTasks". Since we know the shape of the returned object, we we can deserialize the BsonValue to a class that we have created, and then we have access to the properties and methods on that object:

To call a Function, call User.functions.call(). Pass the Function name as the first argument and all arguments for the Function in a List as the second argument.

To include objects as arguments to the Function, convert them to JSON first. You can do this using the jsonEncode() function included in the built-in dart:convert library.

The Function returns a dynamic value containing MongoDB Extended JSON (EJSON) deserialized to a native Dart object.

To execute a function from the SDK, use the getFunctions() method of the your App to retrieve a Functions manager.

Pass the name and parameters of the function you would like to call to callFunction() or callFunctionAsync():

To call a function, you can either pass its name and arguments to User.callFunction() or call the function as if it was a method on the User.functions property.

To call an Atlas Function, pass its name and all arguments to Functions.call().

You can serialize Function arguments and return values using an EJSON encoder. For more information, including examples, refer to EJSON Encoding.

To call this Atlas Function from the SDK:

To execute a function from the SDK, use the getFunctions() method of the your App to retrieve a Functions manager.

Pass the name and parameters of the function you would like to call to callFunction() or callFunctionAsync():

To execute a function in Objective-C, call the callFunctionNamed:arguments:completionBlock:. method on the RLMUser object.

Provide the Function name, arguments, and completion block to execute when the Function call is complete.

To execute a function in Swift, use the functions object on the currently logged-in user.

The functions object has dynamic members corresponding to functions. In this case, functions.concatenate() refers to the concatenate function. Pass a BSONArray of arguments.

func testAsyncCallFunction() async {
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// ... log in ...
let user = app.currentUser!
do {
// The dynamic member name `concatenate` is directly associated with the
// function name. The first argument is the `BSONArray` of arguments to be
// provided to the function - in this case, a string that represents a
// username and a string that represents an email domain.
let concatenatedString = try await user.functions.concatenate([AnyBSON("john.smith"), AnyBSON("@companyemail.com")])
print("Called function 'concatenate' and got result: \(concatenatedString)")
assert(concatenatedString == "john.smith@companyemail.com")
} catch {
print("Function call failed: \(error.localizedDescription)")
}
}

The trailing closure is the completion handler to call when the function call is complete. This handler is executed on a non-main global DispatchQueue.

To call a function, you can either pass its name and arguments to User.callFunction() or call the function as if it was a method on the User.functions property.

// Connect to an App Services App and authenticate a user
auto appConfig = realm::App::configuration();
appConfig.app_id = APP_ID;
auto app = realm::App(appConfig);
auto user = app.login(realm::App::credentials::anonymous()).get();
auto sync_config = user.flexible_sync_configuration();
// If the function takes arguments, pass them as a string array.
// Any quotes within the array must be escaped.
auto argArray = "[\"john.smith\", \"@companyemail.com\"]";
// Call an App Services function as the logged-in user
auto result = user.call_function("concatenate", argArray).get();
// Verify that the result has a value
CHECK(result);
auto functionResult = result.value();
// Prints "Calling the concatenate function returned
// "john.smith@companyemail.com"."
std::cout << "Calling the concatenate function returned " << functionResult
<< ".\n";
var item = await user.Functions.CallAsync<MyClass>
("getItem", "5f7f7638024a99f41a3c8de4");
var name = item.Name;
final response = await user.functions.call("addition", [1, 2]);
// convert EJSON response to Dart number
print(response);
final responseAsNum = num.tryParse(response["\$numberDouble"]);
prints(responseAsNum); // prints 3
String appID = YOUR_APP_ID; // replace this with your App ID
App app = new App(new AppConfiguration.Builder(appID).build());
Credentials credentials = Credentials.anonymous();
app.loginAsync(credentials, it -> {
if (it.isSuccess()) {
User user = app.currentUser();
assert user != null;
Functions functionsManager = app.getFunctions(user);
List<Integer> args = Arrays.asList(1, 2);
functionsManager.callFunctionAsync("sum", args, Integer.class, result -> {
if (result.isSuccess()) {
Log.v("EXAMPLE", "Sum value: " + result.get());
} else {
Log.e("EXAMPLE", "failed to call sum function with: " + result.getError());
}
});
} else {
Log.e("EXAMPLE", "Error logging into the Realm app. Make sure that anonymous authentication is enabled. Error: " + it.getError());
}
});
// wrap the code below in an async function to 'await' for the promises to resolve
const numA = 2;
const numB = 3;
const result = await user.functions.sum(numA, numB);
const resultOfCallFunction = await user.callFunction("sum", numA, numB); // alternate syntax to call a MongoDB Realm Function
console.log(
`Using the "functions.sum()" method: the sum of ${numA} + ${numB} = ${result}`
);
console.log(
`Using the "callFunction()" method: the sum of ${numA} + ${numB} = ${resultOfCallFunction}`
);
Using the "functions.sum()" method: the sum of 2 + 3 = 5
Using the "callFunction()" method: the sum of 2 + 3 = 5
runBlocking {
val app: App = App.create(appID)
val user = app.login(credentials)
// Access the Atlas Function through the authenticated user
// Pass the Function name and all arguments
val response = user.functions.call<Int>("sum", 1, 2)
print(response) // prints: 3
}
val appID = YOUR_APP_ID // replace this with your App ID
val app: App = App(AppConfiguration.Builder(appID).build())
val anonymousCredentials: Credentials = Credentials.anonymous()
app.loginAsync(anonymousCredentials) {
if (it.isSuccess) {
val user: User? = app.currentUser()
val functionsManager: Functions = app.getFunctions(user)
val args: List<Int> = listOf(1, 2)
functionsManager.callFunctionAsync("sum", args, Integer::class.java) { result ->
if (result.isSuccess) {
Log.v("EXAMPLE", "Sum value: ${result.get()}")
} else {
Log.e("EXAMPLE", "failed to call sum function with: " + result.error)
}
}
} else {
Log.e("EXAMPLE", "Error logging into the Realm app. Make sure that anonymous authentication is enabled. Error: " + it.error)
}
}
RLMApp *app = [RLMApp appWithId:YOUR_APP_ID];
// ... log in ...
RLMUser *user = [app currentUser];
// Call concatenate function
[user callFunctionNamed:@"concatenate"
arguments:@[@"john.smith", @"@companyemail.com"]
completionBlock:^(id<RLMBSON> result, NSError *error) {
if (error) {
NSLog(@"Function call failed: %@", [error localizedDescription]);
return;
}
NSLog(@"Called function 'concatenate' and got result: %@", result);
assert([result isEqual:@"john.smith@companyemail.com"]);
}];
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// ... log in ...
let user = app.currentUser!
// The dynamic member name `concatenate` is directly associated with the
// function name. The first argument is the `BSONArray` of arguments to be
// provided to the function - in this case, a string that represents a
// username and a string that represents an email domain.
// The trailing closure is the completion handler to call when the function
// call is complete. This handler is executed on a non-main global
// `DispatchQueue`.
user.functions.concatenate([AnyBSON("john.smith"), AnyBSON("@companyemail.com")]) { concatenate, error in
guard error == nil else {
print("Function call failed: \(error!.localizedDescription)")
return
}
guard case let .string(value) = concatenate else {
print("Unexpected non-string result: \(concatenate ?? "nil")")
return
}
print("Called function 'concatenate' and got result: \(value)")
assert(value == "john.smith@companyemail.com")
}
// wrap the code below in an async function to 'await' for the promises to resolve
const numA = 2;
const numB = 3;
const result = await user.functions.sum(numA, numB);
const resultOfCallFunction = await user.callFunction("sum", numA, numB); // alternate syntax to call a MongoDB Realm Function
console.log(
`Using the "functions.sum()" method: the sum of ${numA} + ${numB} = ${result}`
);
console.log(
`Using the "callFunction()" method: the sum of ${numA} + ${numB} = ${resultOfCallFunction}`
);
Using the "functions.sum()" method: the sum of 2 + 3 = 5
Using the "callFunction()" method: the sum of 2 + 3 = 5

Back

Connect to Atlas

Next

Access MongoDB