MongoDB access using function nodes, not MongoDB nodes

I'm deploying a node-red flow in a locked down Alpine Linux VM, with node-red starting on boot with no need to login. I want it to be completely tamper proof, so the editor will be disabled. The flow accesses a MongoDB database either on the host machine or or another machine on a local network.

The host machine option works fine, with appropriate port forwarding settings in the VM. However, I want to be able to set the IP address of the database without using the node-red editor. At the moment I'm using the node-red-contrib-mongodb4 node, which works fine, except in common with all of the other MongoDB nodes, it sets the connection details in a config node, which obviously needs the editor to change.

Therefore I want to be able to connect to the database and perform database operations using only function nodes, so I can import the MongoDB connection settings in some way, for example in a config file in a shared folder between host and VM. I have installed the node.js MongoDB driver and put the following in my settings.js file.

functionGlobalContext: {    
        mongoClient:require('mongodb')  
    }

My first attempt at writing a connection node was the following, but it fails with "TypeError: mongoClient is not a function".

var mongoClient=global.get('mongoClient');
const uri = "mongodb+srv://localhost:27017/testDB?retryWrites=true&w=majority";       
const client = mongoClient(uri);
return msg;

So could someone please give me an example of working connection code and one or two simple database operations, for example an insertOne and a find ?

Alternatively, is there any way to import config node settings from a file rather than entering them in the editor?

All help gratefully received.

Would using the mongo node with an environment variable for configuring do what you want?

Possibly, but only if it could be defined outside of the VM and that definition imported (again, through a config file in a shared folder for example). However, I'm afraid i don't know how to define an environment variable inside node-red or to use one in a config node.

Over to you Colin!

ok, I've successfully tested using env in a an exec node to set an environment variable to an ip address and port.

Now I just need to work out how to use that in the mongodb4 node.

No, that won't work. It needs to be set in the vm before node red starts up.

Setting the environment variable works, using the export command in an exec node, but the problem is that the connection settings within the mongodb node are in a config mode, which means they are set at deployment time.

So I'm back to the original problem of wanting to connect to MongoDB and perform database operations via code in a function node.

Your original requirement was to change the IP without access to the editor. Using external env vars will allow that, but you will need to restart node-red. If you need to change the address without node red restarting (which could be done automatically from the flow) then env vars will not do what you want.

This is not what the docs say, if you do it that way, in your function node, you need something like:

const { MongoClient } = global.get('mongoClient')

// Connection URL
const url = 'mongodb+srv://localhost:27017/testDB?retryWrites=true&w=majority';
const client = new MongoClient(url);

// Database Name
const dbName = 'myProject';

...

I've got a bit further, based on the documentation, and come up with the following for (as an example) creating a collection in a pre-existing database. It doesn't throw any errors, but it doesn't work either - doesn't actually do anything.

const { MongoClient } = global.get('mongoClient');
var url = "mongodb://localhost:27017/";

MongoClient.connect(url, function(err, db) {
  if (err) throw err;
  var dbo = db.db("testDB");
  dbo.createCollection("customers", function(err, res) {
    if (err) throw err;
    msg.payload="Collection created";
    db.close();
  });
}); 
return msg;

If this is not already obvious, I'm not an expert javascript programmer and I'm only used to seeing function declarations for named functions, so I'm not sure what's going on here. Can someone please suggest a modification that will enable this to work within a NR function node? I can then copy the pattern and explore other collection operations.

Thanks Colin. I agree, and am not going to pursue the environment variable approach any more.

Other than the fact that you haven't written anything to it, it seems OK to me.

But I'm afraid I gave up on MongoDB long ago when they'd dropped support for ARM for a while and when I discovered that it ran out of room long before its theoretical max db size.