Pymongo execute javascript

Hello,

I hope this is the right forum for my question.
I’m using the MongoDB docker container and javascript files to creating my database schema which is mounted / copied into /docker-entrypoint of the docker container.
For my deployment I would like to write a small python command-line tool with pymongo 3.11.3 which can create my database schema.

Is it possible to read the javascript schema file into a string and execute it via pymongo? I found only the eval function but this seems to be deprecated. I think think on the /docker-entrypoint the mongoshell execute the javascript but I don’t know how I can run the shell via pymongo.

My goal is, that I have one place of the database schema, which can be used in the docker container (for development) and also with a command line tool.

Thanks a lot

Hello @Philipp_Kraus,

Is it possible to read the javascript schema file into a string and execute it via pymongo?

You can run a JavaScript shell command / method from a mongo shell .js file - as a subprocess in Python. Please refer the subprocess Python module.

For example, I have file script1.js with mongo shell code:

var doc = { a: "str-1" }
db.test.insertOne(doc)

Then this JS file can be run from operating system command prompt as:

mongo script1.js

The same can be run as a sub process in any programming language (including Python, Java, etc.).

in my case the mongodb service is only remote connected, I think this is not possible in this case, because I don’t know if the “mongo” command exists on the system where the subprocess is executed

@Philipp_Kraus, in such case you can try using the db.runCommand to run your database commands. This can be used in the shell and then there is an equivalent method in PyMongo - db.command. But, I have not verified if the syntax will be the same in both cases.

I try this, in shout I read the file into a string variable and pass it to the command but this produces an error, but I cannot / did not understand why. But yes this would be a nice way which I prefer

Hello @Philipp_Kraus, so the script doesn’t work as it is. I don’t have any other ideas at this moment. You can think about keeping all the scripts in PyMongo only, as your one point source of scripts? But, mongo shell is the right tool for DDL and admin work on MongoDB (and the language is the JavaScript).

Hi @Philipp_Kraus,

Can you provide more details on the contents of your JavaScript schema files?

For example, are you referring to importing some data using a JavaScript file or are you perhaps setting up Schema Validation?

I would be inclined to import your data directly via Python so you do not have a dependency on availability of external command line tools in the same Docker container.

Regards,
Stennie

Yes the script works in the docker shell environment well, but not via pymongo. My javascript file:

 db.createCollection("info")
 db.info.insertOne({"version": "1.0.0"}, {"max": 1})

 db.createCollection("file")
 db.file.createIndex({"_id": 1}, {unique: true})
 db.file.createIndex({"pageid": 1}, {unique: false})
 db.file.createIndex({"media_type": 1}, {unique: false, sparse: true})
 db.file.createIndex({"byte_size": 1}, {unique: false, sparse: true})
 // additional indices and creaetView calls

I get on the command call this error:

full error: {'ok': 0.0, 'errmsg': 'no such command: \'db.createCollection("info")\ndb.info.insertOne({"version": "1.0.0"}, '[the code of the script file]'  'code': 59, 'codeName': 'CommandNotFound'}

Hi @Philipp_Kraus,

I would use PyMongo methods to setup your environment so you do not have external dependencies and can also add error handling. You can use create_indexes() to save on round trips for multiple create_index() commands. If an index already exists with the same definition it will not be recreated.

The _id primary index cannot be explicitly created and is always unique, so you should remove this from your set up statements.

Secondary indexes are not unique by default, so you could omit unique:false unless you prefer to see options explicitly listed.

Partial indexes are a more expressive superset of sparse indexes, and preferred in modern versions of MongoDB.

Creating a new db or collection is implicit, so you can skip these calls unless providing collection-specific options (for example, document validation).

Regards,
Stennie

yes, but in this case I have to translate my javascript file into python and need to synchronize by javascript file and my python code. I wouldn’t do this, because I use the javascript file on the /docker-entrypoint to create on starting the MongoDB docker container all collections & indices and as a second way the python code (for my developing the first solution with the javascript file is easier to use and in the productive system the pymongo solution is easier to use, but I don’t want to maintain two solutions)

Hi @Philipp_Kraus,

If I understand correctly, you are only using Docker for your development environment and your production environment is a deployed Python app which may not have the mongo shell installed locally.

In that case I would suggest using a Python script as the entry point for your Docker image (similar to the mongo shell, you would have to install the relevant interpreter for your script).

However, if you prefer to set up your indexes using the mongo shell and JavaScript, you can use the Python subprocess module as suggested by @Prasad_Saya as long as you are also prepared to install mongo in your production environment.

Regards,
Stennie

Hi,

Yes in my Python Docker container I don’t have a mongoshell.

It my be possible, that I add the mongoshell to my Python Docker container and call than the script via subprocess, seems for me reasonable, I will try this first. But is it possible to install the shell only in the container ( I don’t want to install all other stuff to make the container slim as possible)

A general question is: There is no other solution to execute a JavaScript files remotly via pymongo directly, because this would be a very nice feature.