Docs Menu

Docs HomeAtlas App Services

Tutorial: Build Reverse Search Into Your Application using Triggers and Atlas Search

On this page

  • Prerequisites
  • Create a New Template App
  • Add an Alert Box
  • Create the Alert Box Component
  • Update the Main View
  • Store Alert Terms in Atlas
  • Create a New Collection
  • Enable Access to the Collection
  • Write to the Collection
  • Run and Test the App
  • Add a Trigger
  • Create an Atlas Search Index
  • Add a Database Trigger
  • Define an Atlas function
  • Run and Test the App
  • What's Next?

Estimated time to complete: 30 minutes

You can use Atlas App Services with Atlas Triggers and Atlas Search to build features, such as reverse search, on top of your applications. Reverse search lets you store search parameters, and then match new documents to those parameters.

In this tutorial, you start with a pre-built TypeScript mobile application that includes a working React Native application (frontend) and its corresponding App Services App configuration files (backend). This template app is a basic to-do list application that lets users do various things to manage their tasks. To learn more about the template app, see the Tutorial: Atlas Device Sync for React Native.

After you've got the template app running, you'll add a new feature that alerts you when a user creates a task that contains a specific word or phrase. This feature illustrates how you might implement reverse search into your production application. You will use Atlas to store specific terms to be alerted on, and then match new tasks against those terms by using Atlas Triggers and Atlas Search.

The feature includes:

For example, if you want to know when users submit a time-sensitive task, you might enter a term such as urgent. Then, when a user adds a task that contains the term, such as Urgent: complete this task, you'll be alerted right away.

Before you begin:

  • This tutorial starts with a Template App. You need an Atlas Account, an API key, and appservices to create a Template App.

    • You can learn more about creating an Atlas account in the Atlas Getting Started documentation. For this tutorial, you need an Atlas account with a free-tier cluster.

    • You also need an Atlas API key for the MongoDB Cloud account you wish to log in with. You must be a Project Owner to create a Template App using appservices.

    • To learn more about installing appservices, see Install App Services CLI. After installing, run the login command using the API key for your Atlas project.

  • To run Atlas Search queries, ensure that your Atlas cluster runs MongoDB version 4.2 or higher.

This tutorial is based on the React Native SDK Flexible Sync Template App named react-native.todo.flex. You start with the default app and build new features on it.

To get the template app up and running on your computer, follow the steps described in the React Native tutorial:

  1. Start with the Template App

  2. Set Up the Template App

  3. Get Familiar With the Template App

Once you've set up and explored the template app, it's time to write some code to implement the new alerting feature.

In this section, you add an alert box that lets you enter terms that might appear in specific, important, or time-sensitive tasks.

1

In the template app's src/ directory, create a new AlertBox.tsx file and add the following code. This file contains the UI form that lets you enter the terms to be alerted on.

src/AlertBox.tsx
import React, {useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {Text, Input, Button} from 'react-native-elements';
import {COLORS} from './Colors';
type Props = {
onSubmit: ({term}: {term: string}) => void;
};
export function AlertBox(props: Props): React.ReactElement<Props> {
const {onSubmit} = props;
const [term, setTerm] = useState('');
return (
<View style={styles.modalWrapper}>
<Text h4 style={styles.addItemTitle}>
Add Alert Term
</Text>
<Input
placeholder="Enter term"
onChangeText={(text: string) => setTerm(text)}
autoCompleteType={undefined}
/>
<Button
title="Submit"
buttonStyle={styles.saveButton}
onPress={() => onSubmit({term})}
/>
</View>
);
}
const styles = StyleSheet.create({
modalWrapper: {
width: 300,
minHeight: 200,
borderRadius: 4,
alignItems: 'center',
},
addItemTitle: {
margin: 20,
},
saveButton: {
width: 280,
backgroundColor: COLORS.primary,
},
});
2

In src/ItemListView.tsx, import the alert box you just defined by adding the following line to the top of the file:

import {AlertBox} from './AlertBox';

Then, add the following code to render a button that displays the alert box when clicked:

  • At the top of the ItemListView function block, add a useState() hook to keep track of the alert box view:

    src/ItemListView.tsx
    export function ItemListView() {
    const realm = useRealm();
    const items = useQuery(Item).sorted('_id');
    const user = useUser();
    const [showNewItemOverlay, setShowNewItemOverlay] = useState(false);
    const [showAlertBox, setShowAlertBox] = useState(false);
  • After the Add To-Do button in the main view, add an Alerts button that toggles the alert box overlay:

    src/ItemListView.tsx
    return (
    <SafeAreaProvider>
    <View style={styles.viewWrapper}>
    ...
    <Button
    title="Add To-Do"
    buttonStyle={styles.addToDoButton}
    onPress={() => setShowNewItemOverlay(true)}
    icon={
    <Icon
    type="material"
    name={'playlist-add'}
    style={styles.showCompletedIcon}
    color="#fff"
    tvParallaxProperties={undefined}
    />
    }
    />
    <Button
    title="Alerts"
    buttonStyle={styles.alertButton}
    onPress={() => setShowAlertBox(true)}
    icon={
    <Icon
    type="material"
    name={'add-alert'}
    style={styles.showCompletedIcon}
    color="#fff"
    tvParallaxProperties={undefined}
    />
    }
    />
    <Overlay
    isVisible={showAlertBox}
    onBackdropPress={() => setShowAlertBox(false)}>
    <AlertBox
    onSubmit={({term}) => {
    setShowAlertBox(false);
    }}
    />
    </Overlay>
    </View>
    </SafeAreaProvider>
    );
  • To change the size and color of the button, add the following lines to the styles block at the bottom of the file:

    src/ItemListView.tsx
    const styles = StyleSheet.create({
    ...
    toggleText: {
    flex: 1,
    fontSize: 16,
    },
    alertButton: {
    backgroundColor: '#808080',
    borderRadius: 4,
    margin: 5,
    }
    });

Now that you've created the frontend component for the alert box, configure the application's backend to store and keep track of your alert terms in Atlas.

1

In the Atlas UI, create a collection to store the terms that users enter in the app:

  1. If you're not already at the Database Deployments page, click the Data Services tab.

  2. For the deployment that's synced to the template app, click Browse Collections.

  3. In the left navigation, click the + icon next to the todo database to add a new collection.

  4. Name the collection alerts, then click Create to save the collection.

2

After creating the collection, you must give your app the necessary permissions to write to the todo.alerts collection:

  1. Click the App Services tab.

  2. Click the tile for your app.

  3. In the left navigation under Data Access, click Rules.

  4. Under the todo database, click the alerts collection.

  5. In the right dialog box, select the readAndWriteAll preset role.

  6. Click Add preset role to confirm your selection.

  7. By default, your application enables deployment drafts. To manually deploy your changes, click Review Draft & Deploy and then Deploy.

3

Once you've configured write access to the todo.alerts collection, return to your application code.

In src/ItemListView.tsx, add the following lines to the top of the function block to create a helper function that writes to the collection:

src/ItemListView.tsx
export function ItemListView() {
const realm = useRealm();
const items = useQuery(Item).sorted('_id');
const user = useUser();
// addAlert() takes a string input and inserts it as a document in the todo.alerts collection
const addAlert = async (text: string) => {
const mongodb = user?.mongoClient("mongodb-atlas");
const alertTerms = mongodb?.db("todo").collection("alerts");
await alertTerms?.insertOne({ term: text.toLowerCase() });
};

The addAlert() function takes a string input and uses the React Native SDK to connect to Atlas and insert the specified alert term as a document to your collection.

Then, add the following line to the alert box submission handler to call addAlert() when a user submits an alert term in the app:

src/ItemListView.tsx
<Overlay
isVisible={showAlertBox}
onBackdropPress={() => setShowAlertBox(false)}>
<AlertBox
onSubmit={({term}) => {
setShowAlertBox(false);
addAlert(term);
}}
/>
</Overlay>
4

Your app should now allow users to enter alert terms one at a time to be stored in Atlas.

Rebuild the app and open it. Submit a few terms to be alerted on such as important or urgent. Then, view your documents in the todo.alerts collection to confirm that the terms appear in Atlas.

Now that you've created the alert box and set up its backing collection, create an Atlas Trigger that alerts you when a new task contains one of your alert terms. Triggers can execute application and database logic in response to a change event. Each trigger links to an Atlas Function that defines the trigger's behavior.

In this section, you create a database trigger that runs whenever a user creates a new task. In the trigger's function, you define:

  • The message that displays in your application logs.

  • The database logic, so that the trigger returns the message only when the document contains an alert term.

  • An Atlas Search query that aggregates other tasks that contain the same alert term.

1

In order to run Atlas Search queries on your data, you must first create an Atlas Search index to map the fields in your collection. In the Atlas UI, create a search index on the todo.Item collection:

  1. Return to the Database Deployments page by clicking the Data Services tab.

  2. Click the name of the deployment that's synced to the template app, then click the Search tab.

  3. To create your first Atlas Search index, click Create Search Index.

  4. In the Configuration Method page, select Visual Editor and click Next.

  5. Leave the Index Name set to default.

  6. In the Database and Collection section, find the todo database and select the Item collection.

  7. Click Next, then click Create Search Index after you've reviewed your index.

  8. Wait for the index to finish building.

    The index should take about one minute to build. When it's finished building, the Status column reads Active.

Note

To learn more about Atlas Search indexes, see Create an Atlas Search Index.

2

To open the database trigger configuration page in the App Services UI:

  1. Click the App Services tab and select the tile for your app.

  2. In the left navigation menu, click Triggers.

  3. Click Add a Trigger and leave the Trigger type set to Database.

  4. Name the trigger sendAlerts.

  5. Configure the trigger to listen only for new task documents inserted into the todo.Item collection:

    • For the Cluster Name, select the deployment that's synced to the template app.

    • For the Database Name and Collection Name, select the todo database and Item collection.

    • For the Operation Type, select Insert.

    • Enable Full Document to include each new report document in the change event passed to the trigger function.

3

Navigate to the Function section of the trigger configuration page and select + New Function from the drop-down menu. Then, define the trigger's function:

  1. Name the function triggers/sendAlerts.

  2. Copy the following code into the function body:

    functions/triggers/sendAlerts.js
    exports = async function(changeEvent) {
    // Read the summary field from the latest inserted document
    const fullDocument = changeEvent.fullDocument;
    const summary = fullDocument.summary;
    // Connect to your Atlas deployment
    const mongodb = context.services.get("mongodb-atlas");
    // Read task and alert data from collections in the todo database
    const tasks = mongodb.db("todo").collection("Item");
    const alerts = mongodb.db("todo").collection("alerts");
    const terms = await alerts.distinct("term");
    // Check if the task summary matches any of the terms in the alerts collection
    for (let i = 0; i < terms.length ; i++) {
    if (summary.toLowerCase().includes(terms[i])) {
    console.log("The following task has been added to a to-do list: " + summary +
    ". You've been alerted because it contains the term, " + terms[i] + ".");
    // Aggregates any tasks that also contain the term by using an Atlas Search query
    const query = await tasks
    .aggregate([
    {
    $search: {
    compound: {
    must: [{
    phrase: {
    query: terms[i],
    path: "summary",
    },
    }],
    mustNot: [{
    equals: {
    path: "isComplete",
    value: true,
    },
    }],
    },
    },
    },
    {
    $limit: 5,
    },
    {
    $project: {
    _id: 0,
    summary: 1,
    },
    },
    ])
    .toArray();
    relatedTerms = JSON.stringify(query);
    if (relatedTerms != '[]') {
    console.log("Related incomplete tasks: " + relatedTerms);
    }
    }
    }
    };

    This JavaScript function returns a message in your application logs when a user enters a task that contains a term stored in the todo.alerts collection.

    The function also includes an Atlas Search query to find other task documents in the todo.Item collection that contain the same alert term. The query uses:

    • The $search pipeline stage to query the collection.

    • The following compound operator clauses:

      • The must clause and phrase operator to query for any tasks with a summary that contains the alert term.

      • The mustNot clause and equals operator to exclude completed tasks.

    • The $limit stage to limit the output to 5 results.

    • The $project stage to exclude all fields except summary.

  3. When you're finished, click Save and deploy the trigger.

4

Atlas is now set up to alert you when a user creates a task in the app that contains an alert term.

Rebuild and run the app to make sure everything works. Enter a few tasks that contain an alert term you've previously entered. Then, view your logs to see the output from the trigger. You can filter for your trigger logs by selecting the Triggers type from the drop-down menu.

For example, if one of your alert terms is important, the log output for a new task might resemble the following:

Logs:
[
"The following task has been added to a to-do list: Complete important tutorial.
You've been alerted because it contains the term, important.",
"Related incomplete tasks: [
{"summary": "Important: Create template app"},
{"summary": "Add important tasks"},
{"summary": "Make sure to read the documentation. This is important."}]"
]

Note

Share Feedback

How did it go? Use the Share Feedback tab at the bottom right of the page to let us know if this tutorial was helpful or if you had any issues.

← Tutorial: Build a Serverless GitHub Contribution Tracker using Triggers, Functions, and Values