3

Is there a way to use shell variables in a MongoDB query?

I have this for example:

#!/usr/bin/env bash

mongo --eval "use cdt_db; db.users.update({username:'${USER}'}, {'\$set':{roles:['Admin']}});"

I tried single quotes and double quotes, I get this error:

MongoDB shell version v3.4.9
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.9
2017-10-09T13:53:51.747-0700 E QUERY    [thread1] SyntaxError: missing ; before statement @(shell eval):1:4
8
  • Shouldn't $set be without the quotes? The safest way would be to write the expression under single quotes, concatenating it with variable values: mongo cdt_db --eval 'db.users.update({username:"'"$USER"'"}, {$set:{roles:["Admin"]}});'. Commented Oct 9, 2017 at 21:11
  • 1
    yes that seems to work, if you could add an answer explain in detail, I will give an upvote at the very least Commented Oct 9, 2017 at 21:18
  • Glad to hear it. I'll write it up. Commented Oct 9, 2017 at 21:21
  • It works with 2 fewer quote chars, like so: mongo cdt_db --eval 'db.users.update({username:"'${USER}'"}, {$set:{roles:["Admin"]}});' Commented Oct 9, 2017 at 21:25
  • 1
    Let me correct/amend myself. The $USER undergoes a shell parameter expansion (always, unless single-quoted). So if USER='*', then "$USER" will expand to *. However, if you don't double-quote it then it also goes through a pathname expansion (globbing), so $USER will expand to file1 file2 .... If you write cmd 'str' $USER, the variable is pathname-expanded (cmd receives str file1 file2 ...), but if you write cmd 'str'$USER, then the variable is not pathname-expanded (unless has spaces), but spaces in USER are not preserved! So the safe thing is to write cmd 'str'"$USER". Commented Oct 9, 2017 at 22:26

1 Answer 1

3

From the shell standpoint, your query is fine. Variable USER is expanded properly and $ in $set is properly escaped to prevent the shell parameter expansion.

The problem is in your use <dbname> part of the query. According to the docs:

You cannot use any shell helper (e.g. use <dbname>, show dbs, etc.) inside the JavaScript file because they are not valid JavaScript.

Instead, you can use a JavaScript equivalent:

db = db.getSiblingDB('<dbname>')

or, better yet, specify the name of the database via command line argument:

mongo dbname --eval 'query'

Fixed, your query looks like:

mongo cdt_db --eval "db.users.update({username:'${USER}'}, {\$set:{roles:['Admin']}});"

For convenience (less escaping), you might sometimes also consider using single quotes, and concatenate the expanded variables (under double quotes):

mongo cdt_db --eval 'db.users.update({username:"'"${USER}"'"}, {$set:{roles:["Admin"]}});'
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.