Mongo query works in mongo shell but not in a bash mongo --eval? - mongodb

Here is an example query:
db.readings.find( {"_id.s" : ISODate("2012-11-01T00:05:00Z") } ).count()
Query works in the mongo shell. However, in a bash script or directly in the Ubuntu shell
mongo fivemin --eval "printjson(db.readings.find( {"_id.s" : ISODate("2012-11-01T00:05:00Z") } ).count())"
returns a SyntaxError: missing : after property id (shell eval):1
I can't seem to find a problem with the query. I reverted to { "_id" : {"s" : ...} }, and it still gives the same problem. find().count() works however.

Had the same issue in bash shell.
This will fail because of double quotes:
mongo fivemin --eval "printjson(db.readings.find( {"_id.s" : ISODate("2012-11-01T00:05:00Z") } ).count())"
But using the eval string in single quote it works:
mongo fivemin --eval 'printjson(db.readings.find( {"_id.s" : ISODate("2012-11-01T00:05:00Z") } ).count())'
And if you use a $ sign like $regex you need to escape it:
mongo fivemin --eval 'printjson(db.readings.find( {"_id.s" : {"\$regex":"2012-11-01T*"} } ).count())'

use single quotes into double,
e.g.:
mongo fivemin --eval "printjson(db.readings.find( {'_id.s' : ISODate('2012-11-01T00:05:00Z') } ).count())"

There is also another possible issue using --eval with bash double quotes, if the query contains mongo operators i.e. $ne, $gt etc, since operators start with $.
double quotes:
$ echo " '$ne': null "
$ => '': null
single quotes:
$ echo ' "$ne": null '
$ => "$ne": null
Bash tries to replace these operators with variables.
$ ne = 'test'
$ echo " '$ne': null "
$ => 'test': null
So, I always recommend to use --eval with single quotes.

Just sat and thought about it. It seems to be a problem with bash exiting out on the " (should have noticed immediately!). Instead I used ' (or I guess you can use /" for JSON) so the query looks like:
printjson(db.readings.find({'_id.s' : ISODate('2013-01-01T00:05:00Z') }).count())"

The best way to handle this is to build the mongo command in a var. Then use eval command to execute the mongo command:
mongo_update_query="db.collectionName.update({ name:\""${some_name}"\", \
{ \$addToSet: { nick_names : { \$each : [ ${name_array} ] }}});"
mongo_cmd_str=$(echo "mongo --host ${mongo_host} --port ${mongo_port} ${mongo_database} --eval '${mongo_update_query}'")
# the actual call to mongo query
eval ${mongo_cmd_str}

Related

Run a command in mongodb container with credentials from outside

I want to set the compatibility version in mongodb, which is running in a container, but from outside:
docker exec -it docker-compose_mongodb_1 bash -c 'mongo -uroot -p rootpassword --eval "db.adminCommand( { setFeatureCompatibilityVersion: "4.0" } )"'
MongoDB shell version v4.0.23
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("7945d913-f77c-4242-be33-af8e20c07374") }
MongoDB server version: 4.0.23
{
"ok" : 0,
"errmsg" : "Command argument must be of type String, but was of type double in: { setFeatureCompatibilityVersion: 4.0, lsid: { id: UUID(\"7945d913-f77c-4242-be33-af8e20c07374\") }, $db: \"admin\" }. See http://dochub.mongodb.org/core/4.0-feature-compatibility.",
"code" : 14,
"codeName" : "TypeMismatch"
}
Any idea what I am doing wrong?
It looks like a quoting problem: you seem to have double quotes around "4.0", but you've already quoted the entire argument to the --eval argument, so the effect of these quotes isn't what you want (the value (4.0) ends up unquoted, hence the error ("argument must be of type String, but was of type double").
In theory you can just escape the inner quotes:
docker exec -it docker-compose_mongodb_1 bash -c 'mongo -uroot -p rootpassword --eval "db.adminCommand( {setFeatureCompatibilityVersion: \"4.0\" } )"'

mongo terminal, check database exist function

It is a mongo terminal problem,
#!/bin/bash
echo
echo "Hello $USER."
echo "--------------------------"
mongo < myScript.js
with myScript.js as
if (hereAFunctionCheckExistsDatabase('myDatabase'))
doSomething()
exit
Of course show dbs work, but is a echo, I need a function.
My mongo:
MongoDB shell version: 2.4.10
connecting to: test
You need
function hereAFunctionCheckExistsDatabase(db) {
return (db.getMongo().getDBNames().indexOf(db)!=-1);
}
Mongo have also a catalog of namespaces, try this
db.system.namespaces.find( { name: /myDatabase\./ } );
...

Pass a .js file to mongo db.eval()

I am trying to get variety working with db.eval() instead of commandline --eval. This is because I get some problems with authentication.
The normal use is from the commandline:
$ mongo test --eval "var collection = 'users', maxDepth = 3" /path/to/variety.js
What I am trying to do is this:
$ mongo
>> use admin
>> db.auth("foo", "bar")
>> use anotherColl
>> db.eval("/path/to/variety.js", "var collection = 'users', maxDepth = 3")
>> Thu Mar 7 13:19:10 uncaught exception: {
"errmsg" : "compile failed: JS Error: SyntaxError: invalid flag after regular expression nofile_a:0",
"ok" : 0
}
Is there a way to have db.eval() eat an javascript file instead of an string?
According to #Sammaye and my gut feeling you can't put in .js files in db.eval(). However for variety there is an solution described here.
mongo -u USER-p PASS admin --eval "var collection = 'COL', db_name='DB_NAME'" variety.js
And now the authentication problem :(

Can i use mongoexport --query <file> where file is a list of conditions

I have an array of ids stored in a file, and I want to retrieve their data from the mongdb
so i looked into the mongoexport method. it seems --query option can only accept a json instead read a large json or array from a file. In my case, it is about 4000 ids stored in the file. Is there a solution to this?
I was able to use
mongoexport --db db --collection collection --field name --csv -oout ~/data.csv
but how to read query conditions from a file
for example, for mongoid in rails application, query like this is Data.where(:_id.in => array).
or is it possible to do from mongo shell by executing a javscript file
tks
I believe you can use a javascript to output the array you need.
you can use "printjson" command in your script, for example:
create a script.js javascript file as following:
script.js:
printjson( db.albums.find({_id : 18}, {"images" : 1,"_id":0}).toArray() )
Call hi as follow:
mongo test script.js > out.txt
In my local environment albums collection has the following structure:
db.albums.findOne({"_id":18
{
"_id" : 18,
"images" : [
2926,
5377,
8036,
9023,
10119,
11543,
12305,
12556,
12576,
13753,
14414,
14865,
15193,
15933,
17156,
17314,
17391,
20168,
21705,
22016,
22348,
23036,
23452,
24112,
27086,
27310,
27864,
28092,
29184,
29190,
29250,
29354,
29454,
29563,
30366,
30619,
31390,
31825,
31906,
32339,
32674,
33307,
33844,
37475,
37976,
38717,
38774,
39801,
41369,
41752,
44977,
45384,
45643,
46918,
47069,
50099,
52755,
54314,
54497,
62338,
63438,
63572,
63600,
65631,
66953,
67160,
67369,
69802,
71087,
71127,
71282,
73123,
73201,
73954,
74972,
76279,
77054,
78397,
78645,
78936,
79364,
79707,
83065,
83142,
83568,
84160,
85391,
85443,
85488,
86143,
86240,
86949,
89406,
89846,
92591,
92639,
92655,
93844,
93934,
94987,
95324,
95431,
95817,
95864,
96230,
96975,
97026
]
}
>
, so the output I got was:
$ cat out.txt
MongoDB shell version: 2.2.1
connecting to: test
[
{
"images" : [
2926,
5377,
8036,
9023,
10119,
11543,
12305,
12556,
12576,
13753,
14414,
14865,
15193,
15933,
17156,
17314,
17391,
20168,
21705,
22016,
22348,
23036,
23452,
24112,
27086,
27310,
27864,
28092,
29184,
29190,
29250,
29354,
29454,
29563,
30366,
30619,
31390,
31825,
31906,
32339,
32674,
33307,
33844,
37475,
37976,
38717,
38774,
39801,
41369,
41752,
44977,
45384,
45643,
46918,
47069,
50099,
52755,
54314,
54497,
62338,
63438,
63572,
63600,
65631,
66953,
67160,
67369,
69802,
71087,
71127,
71282,
73123,
73201,
73954,
74972,
76279,
77054,
78397,
78645,
78936,
79364,
79707,
83065,
83142,
83568,
84160,
85391,
85443,
85488,
86143,
86240,
86949,
89406,
89846,
92591,
92639,
92655,
93844,
93934,
94987,
95324,
95431,
95817,
95864,
96230,
96975,
97026
]
}
]
Regards,
Moacy

mongo dbname --eval 'db.collection.find()' does not work

Why does this work:
# mongo dbname
MongoDB shell version: 1.8.3
connecting to: nextmuni_staging
> db.collection.find()
{ "foo" : "bar" }
> bye
While this does not work:
# mongo localhost/dbname --eval 'db.collection.find()'
MongoDB shell version: 1.8.3
connecting to: localhost/dbname
DBQuery: dbname.collection -> undefined
It should be exactly the same, no?
Thanks!
The return val of db.collection.find() is a cursor type. Executing this command from within the shell will create a cursor and show you the first page of data. You can start going through the rest by repeating the 'it' command.
I think the scope of variables used during the execution of an eval'd script is only for the lifetime of the script (data can be persisted into collections of course) so once the script terminates those cursor variables no longer exist and so you would be able to send another eval script to page the data. So the behaviour you get during a shell session wouldn't really work from an eval script.
To get close to the behaviour you could run something like this:
mongo dbname --eval "db.collection.find().forEach(printjson)"
That shows you that the command does execute and produce a cursor which you can then iterate over sending the output to stdout.
Edit: I think the point I was trying to make was that the command you are issuing is working its just the output is not what you expect.
The printjson functions covers a lot of ground when scripting with mongo --eval '...'. Rather than chaining .forEach you can simply wrap your call.
$ mongo --eval 'db.stats_data.stats()' db_name
MongoDB shell version: 2.4.14
connecting to: db_name
[object Object]
$ mongo --eval 'db.stats_data.stats().forEach(printjson)' db_name
MongoDB shell version: 2.4.14
connecting to: db_name
Tue Jan 10 15:32:11.961 TypeError: Object [object Object] has no method 'forEach'
$ mongo --eval 'printjson(db.stats_data.stats())' db_name
MongoDB shell version: 2.4.14
connecting to: db_name
{
"ns" : "db_name.stats_data",
"count" : 5516290,
"size" : 789938800,
"avgObjSize" : 143.20110073980882,
"storageSize" : 1164914688,
"numExtents" : 18,
"nindexes" : 3,
"lastExtentSize" : 307515392,
"paddingFactor" : 1.0000000000000457,
"systemFlags" : 1,
"userFlags" : 0,
"totalIndexSize" : 1441559616,
"indexSizes" : {
"_id_" : 185292688,
"owner_id_key_idx" : 427678384,
"onwer_metric_key_idx" : 828588544
},
"ok" : 1
}