Switch database while Meteor is running?

I run some non-Meteor jobs that write metrics to a different Mongo database every time they run; these databases all reside within the same Mongo server.

Currently I restart my Meteor app that views these metrics every time I run a new job, and give it a different MONGO_URL:

$ MONGO_URL=mongodb://localhost:27017/<current db name> meteor

I would much rather have a long-running Meteor instance that can switch databases while running.

Does Meteor support such a thing?

meteor sets the database on the startup. So this is not possible.

I did not test this, but you can try:

var database = new MongoInternals.RemoteCollectionDriver("<mongo url>"); 

MyCollection = new Mongo.Collection("collection_name", { _driver: database });

Thanks @benjamin79, I found some similar info about that internal API on this SO and a little more on this one.

It seems like if I redefine my Mongo collection variables after changing the value of the database, I might be able to get this working.

Right now I’m stuck on how to send the MONGO_URL to the client, because I want to display it, allow the user to change it, and then signal the server somehow.

I can’t figure out how to send a simple string to the client, in this case the value that I got on the server from process.env["MONGO_URL"]; any ideas there?

You can´t change the process.env[“MONGO_URL”] on the fly. It´s loaded only on meteor startup.

Perhaps you can change the in the RemoteCollectionDriver.

Whats your use case? Perhaps using just one db is a better solution.

I’m not attempting to change process.env["MONGO_URL"], just send it to the client to initialize some UI elements that the user can use to inspect, and hopefully change, the mongo URL.

Changing it would be a harder process involving redefining all of my collections on the server with the _driver set to a new database.

I’m exploring just doing everything in one database but it is pretty annoying because I need to give all of my records an extra ID that is the value that was previously what DB they lived in, and I need to change all of my DB indexes and queries to use that value before any others…

You can publish it.

Meteor.publish('mongoUrl', function () {
  this.added('collectionName', 'someRandomId', { mongoUrl: process.env.MONGO_URL });
  this.ready();
});

In the client side ONLY, define a named Mongo collection with the name set to collectionName, subscribe to mongoUrl, then do a findOne('someRandomId') with said defined collection. This is untested but should theoretically work.

Is anyone found a solution ?

You can provide a meteor method which returns the value of: process.env.MONGO_URL to the client.

As example, file is imports/api/serverMethods.js:

if (Meteor.isServer) {
    console.log("[serverMethods.js][entry]")
    Meteor.methods({
        'get_database_info': function (param1) {
            console.log("[get_database_info] is [" + process.env.MONGO_URL + "]");
            return process.env.MONGO_URL;
        }
    });
}

and then on the client (as pure example), in a file named imports/ui/App.js:

Template.navigation.onRendered(function() {
    console.log("navigation template onRendered");
    Meteor.call('get_database_info', function(error, response) {
        if (error) {
            console.log("get_database_info error");
        } else {
            console.log("get_database_info success");
            console.log("response: " + response);
            $("#dbinfo").text(response);
            return response;
        }
    });
});

and then App.html has the content:

<template name="navigation">
    <h4>Uses database: <span id="dbinfo"></span></h4>
</template>