Realm sync and restful api best approach?

Hello, I am working on a project that has two endpoints, one is a mobile application and the other one is a web-based admin site. For the website, I was intending to use React js and a Nodejs restful API with MongoDB for data storage. For the mobile application, I wanted to use react native since am from a react js background therefore it will be pretty easy for me to learn and use it for my project.

Now my worry is here, I want to use my mongo database for both endpoints. The admin should update data from the website that should be accessed from the mobile application and similarly the mobile users should update their individual data that can also be accessed from the web app. Mobile users should also be able to use the app when offline and data sync when the connection is restored. Kindly advise the best approach for this.

Hi. Your use case is one of the most common ones we see in customers and fits nicely into our ecosystem. Using App Services you can have your mobile clients connect to sync and your web clients can connect via GraphQL, Data API, or Query Anywhere.

Do you have any specific questions?

1 Like

Hello, thank you for getting back.
Now my second issue is working with the mobile app service. The documentation is too less for a beginner , or lets say am not the docs only person. I have been trying working with realm flexible sync for 2 weeks now but don’t seem to get it right .

My recent try seems to connect successfully, but I don’t really understand how everything else works from adding to db, querying, and other operations.

Here is my scenario .

I want the mobile app to be used by students, each student should login with their username and password that should be given to them by the admins (the admins create the account from the website portal).

After login in, each student should access data related to them, the app should also store user instance so they may continue using the app even if online.

There should be an exam module that will be queried to the app. The students will pick their answers from the multiple choices and on submit(when offline or online), the answers marked and results returned.

The app should be able to store individual student previous scores.

Kindly help me on working around this with the flexible sync. At least give me an approach for this.

Thank you in advance

Hi. Have you played with one of the tutorials yet? I would highly reccomend doing so since it looks like you are still understanding sync: how it works, what needs to be set up, etc.

What you are trying to do is very possible. The easiest way I can think about doing this would be:

  1. Create a new app
  2. Add your schemas in the “schemas” page. This uses JSON schema
  3. All schemas should have a student_id field which stores the unique id for a given student
  4. Enable flexible sync and add the “student_id” as a queryable field
  5. Connect an app and issue a subscription for all relevant tables (user, exams, classes, etc) for "student_id" == ${student_id}

How do I work with subscriptions, give me a code example of working with subscriptions, then inserting on my data, then when opening my realm, do I define a realm name??

For the questions, they are nit tired to any student, and therefore should be accessed by every student under a specific topic if that topic is active by that time. So how do i query these questions too??

Hi, ill start out with responding to your question:

How do I work with subscriptions, give me a code example of working with subscriptions, then inserting on my data, then when opening my realm, do I define a realm name??

These are the basic building blocks of flexible sync and there are examples of using these throughout the documentation and in our tutorials. I will link these below though.

I recommend starting with one of the Realm Sync tutorials: Sync Tutorials | MongoDB

For React-Native specifically, try:

The React Native Tutorial goes into more detail than the Quick Start, including a template app (Task Tracker).

If you get stuck on a specific implementation detail or concept, please share more context including:

  • your versions of React and Node.js
  • snippet of code (if applicable)
  • expected behaviour
  • actual behaviour (error message or other outcome)

As for your second comment:

For the questions, they are nit tired to any student, and therefore should be accessed by every student under a specific topic if that topic is active by that time. So how do i query these questions too??

How would you ideally “query” this data. Sync works very similarily to just querying and pulling in the data. If your query would be something like db.questions.find({topic: "history"}) then to subscribe to that query in sync all you would need to do is make the “topic” field a queryable field and then subscribe to "topic" == "history"

1 Like

Hello about the react native tutorial, I am trying to run the command but I get the error “app create failed: failed to authenticate with Mongo DB cloud API: you are not authorized for this resource”

I am on ubuntu Linux

Hi. You’ll need to log in to the cli. If you just run the command it doesnt know if you actually have permissions to do anything. Please see this page or navigate to the “Deployment” section of a realm app you are using and then click “cli” to give you a copy and pastable login command.

Hello, I have tried so much to have my flexible sync working, I have the log with the response okay but seems like am still missing something.
When I query the data I get result.length as 0 and even if I insert a record I still get 0.
I also don’t see any data on my atlas collections.
Node version 18.12.1
React version 18.1.0
Realm version ^11.1.0

Here is my flexible sync code:

import React, {
  createContext,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import {ResultSchema} from '../database/schemas';
import {useAuth} from '../provider/AuthProvider';

const QueriesContext = createContext();

const QueriesProvider = ({children}) => {
  // initialize state
  const [data, setData] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const {user} = useAuth();
  const realmRef = useRef(null);

  // Fetch data
  useEffect(() => {
    if (user == null) {
      console.error('Null user? Needs to log in!');
      return;
    }

    // Enables offline-first: opens a local realm immediately without waiting
    // for the download of a synchronized realm to be completed.
    const OpenRealmBehaviorConfiguration = {
      type: 'openImmediately',
    };

    const config = {
      schema: [ResultSchema],
      sync: {
        user: user,
        flexible: true,
        initialSubscriptions: {
          update: (subs, realm) => {
            subs.add(realm.objects('Result').filtered('chv_id == "+user.id+"'));
          },
        },
        newRealmFileBehavior: OpenRealmBehaviorConfiguration,
        existingRealmFileBehavior: OpenRealmBehaviorConfiguration,
      },
    };

    // Open realm and sync
    Realm.open(config).then(realm => {
      realmRef.current = realm;
      const subs = realm.subscriptions;
      subs.update(mutableSubs => {
        mutableSubs.add(
          realm.objects('Result').filtered('chv_id == "+user.id+"'),
        );
      });
      realm.subscriptions.waitForSynchronization();
      realm.objects(ResultSchema.name);
    });

    return () => {
      // cleanup function
      closeRealm();
    };
  }, [user]);

  // View results
  let getResults = () => {
    const realm = realmRef.current;
    return realm.objects(ResultSchema.name);
  };

  // Create new results
  let addResults = () => {
    const realm = realmRef.current;
    realm.subscriptions.waitForSynchronization();
    realm.write(() => {
      realm.create('Result', {
        _id: ObjectId('637799211d66c64212188801'),
        chv_id: user.id,
        final_assessment_score: 0,
        module: 'Hypertension',
        post_test_score: 57,
        pre_test_score: 44,
        support_supervision_score: 0,
      });
    });
  };

  // close realm
  const closeRealm = () => {
    const realm = realmRef.current;
    if (realm) {
      realm.close();
      realmRef.current = null;
      setData([]);
    }
  };

  // Render the children within the QueriesContext's provider. The value contains
  // everything that should be made available to descendants that use the
  return (
    <QueriesContext.Provider
      value={{
        data,
        addResults,
        getResults,
      }}>
      {children}
    </QueriesContext.Provider>
  );
};

export default QueriesProvider;

const useData = () => {
  const data = useContext(QueriesContext);
  if (data == null) {
    throw new Error('useData() called outside of a QueriesProvider?'); // an alert is not placed because this is an error for the developer not the user
  }
  return data;
};

export {useData};

type or paste code here

Hi. Can you please send a link to your app in the console? I suspect your issue is that you are inserting data that is outside of your query. You subscription is subs.add(realm.objects('Result').filtered('chv_id == "+user.id+"')); but I am not sure that is doing what you want. Try replacing that with just subs.add(realm.objects('Result')) and I suspect things will start working.

I believe you are likely trying to add a subscription like:

filtered("chv_id == $0", user.id)

Hey , My issue was my subscription so I changed the subscription to: subs.add(realm.objects('Result').filtered(chv_id == “${user.id}”));
and it now works perfectly. Thanks.

Back to the general collections that need to be available for all users, do I set subscriptions when querying them…??

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.