realm / realm-js

Realm is a mobile database: an alternative to SQLite & key-value stores
https://realm.io
Apache License 2.0
5.68k stars 562 forks source link

Create a hook for direct MongoDB collection access #5388

Open takameyer opened 1 year ago

takameyer commented 1 year ago

Problem

If for some reason, a developer wanted direct access to a MongoDB collection, they would have to type the following code to do so:

function QueryPlants() {
  // Get currently logged in user
  const user = useUser();

  const getPlantByName = async (name: string) => {
    // Access linked MongoDB collection
    const mongodb = user!.mongoClient('mongodb-atlas');
    const plants = mongodb.db('example').collection<Plant>('plants');
    // Query the collection
    const response = await plants.findOne({name});

    return response;
  };
  // ...
}

Solution

This could be abstracted into a single hook:

  const plants = useMongoDb({cluster: 'mongodb-atlas', db: 'example', collection: 'plants'});

Under the hood, the hook could register a collection watcher, to update when anything changes.

Alternatives

The above is just a suggestion of what could be possible, but in practice, there could be something better or more ergonomic. A bit of design and research should be done to determine the best path forward.

How important is this improvement for you?

Would be a major improvement

Feature would mainly be used with

Atlas App Services: Auth or Functions etc

kraenhansen commented 1 year ago

For what it's worth, this is an implementation I did for another app I was working on:

export function useMongoClient() {
  const user = useUser();
  return useMemo(() => {
    return user.mongoClient("mongodb-atlas");
  }, [user]);
}

export function useMongoDB(databaseName = config.databaseName) {
  const client = useMongoClient();
  return useMemo(() => {
    return client.db(databaseName);
  }, [client, databaseName]);
}

export function useMongoCollection<T extends Realm.Services.MongoDB.Document>(
  collectionName: string,
  databaseName = config.databaseName
) {
  const db = useMongoDB(databaseName);
  return useMemo(() => {
    return db.collection<T>(collectionName);
  }, [db, collectionName]);
}