MongoError: cannot do queries on admin in atlas - mongodb

I just set up a free MongoDB on Atlas. I added a database called 'react-project' that I'm trying to connect to using mongoose. Here is my connection string:
mongoose.connect('mongodb+srv://myUser:myPassword#myCluster.mongodb.net/react-project');
As you can see, at the end of the query I specify the database I want to connect to. I can connect to the mongodb instance just fine, but when I try and do an operation (such as Model.find()), I get the following MongoError:
MongoError: cannot do raw queries on admin in atlas
This leads me to believe that it is not connecting to the 'react-project' database, but is connecting to the 'admin' database instead.
Why is this happening and how can I connect to the correct database?
Here is the code I'm running that is giving me the error:
var productSchema = mongoose.Schema({
productId: Number,
img: String,
price: Number,
title: String,
type: String
});
var Product = mongoose.model('Product', productSchema);
// Return all products
Product.find(function(error,result) {
if (error) return console.error(error);
console.log(result);
});

I had the exact same issue. Seems like its a new one.
Heres my connection string that now works
mongoose.connect('mongodb://USERNAME:PASSWORD#myShard-shard-00-00-lbofd.mongodb.net:27017,myShard-shard-00-01-lbofd.mongodb.net:27017,myShard-shard-00-02-lbofd.mongodb.net:27017/MYDBNAME?ssl=true&replicaSet=myShard-shard-0&authSource=admin');
To create a new DB I used MongoDB Compass. Copy the connection string from the Atlas site(the longer one - 3.4 I believe), when you open mongodb compass it will recognize that there is a connection string in your clipboard (OSX) and will allow you to populate the connection for Compass with a simple click. You can create a new Database from there (Click on MyCluster at top left - then Create Database. Put the name of the new db in the bolded MYDBNAME in my connection string.
It did take a few refreshes to see new data.
I had much the same connection string as you (db name/shard different etc) - I was able to POST but not GET. POSTS didnt create error (but I could not find data I posted) and GET threw the same error as you got.

I just got this error after trying to switch from my paid Mongo Atlas cluster back to my free cluster. The solution for me ended up being blissfully simple:
In the URI, I changed /admin to the name of the free cluster's db or /test in my case.
String before fix:
"mongoURI": "mongodb+srv://<username>:<password>#cluster0-azhuz.mongodb.net/admin?retryWrites=true&w=majority"
String after fix:
"mongoURI": "mongodb+srv://<username>:<password>#cluster0-azhuz.mongodb.net/test?retryWrites=true&w=majority"

Had the same issue, none of the above helped. Documenting my solution since this page is the first hit on Google.
If you're using the connect-mongo library like I was, you can fix it by using the older connection string (Node 2.2 not Node 3.0). To get that in Atlas, Click on your cluster -> Connect -> Connect Your Application -> under driver choose node v. 2.2 and copy that connection string.
This is because connect-mongo can't handle the "+srv" in the newer strings.
So that string should look like
mongodb://<user>:<password>#cluster0-shard-00-00-rnmsm.mongodb.net:27017,cluster0-shard-00-01-rnmsm.mongodb.net:27017,cluster0-shard-00-02-rnmsm.mongodb.net:27017/test?ssl=true&replicaSet=cluster0-shard-0&authSource=admin&retryWrites=true&w=majority

Got the same issue.
Changing connection string to 3.4 version (the longer one instead of 3.6) helped.
Strange, it had worked well on it on 3.6 before the issue appeared.

I have faced the same problem. Just change the /admin to your Cluster name in MongoURL.
Example:
mongodb+srv://UserName:Password#cluster0-qkaef.mongodb.net/ClusterName?retryWrites=true&w=majority

I ran into this issue using the Serverless Framework and AWS Lambda. My issue was that the environment variables were not being updated with my deploy command and it was using an older version of my Atlas connection string with an out-dated user with incorrect permissions.
So while that was a specific occurrence of my error, for other users that run into this, it seems like it could also just be a permissions issue with the user.

I found a very simple solution on a different website, but decided to share it here!
Basically, substitute /admin in the connection string to the name of your cluster in MongoDB Atlas.

Make sure you following this step. (my node version v10.15.0, mongodb compass Version 1.16.3 (1.16.3))
Make Sure your user have right readWriteAnyDatabase#admin
then copy
mongodb+srv://<yourUsername>:<yourPassword>#devconnector-xszss.mongodb.net/admin
after you copy when open mongoDB Compass will display the alert prop like this then click connect button
after login create the new database. In this case my database that I already create is name devconnector.
then in your app (in this case my app is using Nodejs) and make sure that in the url mongodb+srv://<yourUsername>:<yourPassword>#devconnector-xszss.mongodb.net/YourdatabseYouJustCreate in my case the database that I just created is devconnector. make sure it is not admin
then you can make a post request. (my post request code). my UserSchema
I hope this will help you.

I know it's really late to answer this but I was having the same problem and I just put Mongodb user name after a '/' now my connection string looks like mongodb+srv://UddeshRW:uddesh#cluster0-2erky.mongodb.net/<Mongodb user name>

I noticed you're using mongoose. Banged my head against the wall for an hour, until I rechecked the mongoose docs.
mongoose.connect('mongodb://localhost:27017/myapp', {useNewUrlParser: true});
the .connect() method has a second parameter to specify to use the new url parser for mongo :)
Hope this helps someone (or my future self)!

Your connection URL can be any of the two:
1.
mongodb+srv://<username>:<pasword>#<your replica set>.mongodb.net/<your database name>?retryWrites=true&w=majority
mongodb+srv://<username>:<pasword>#<your replica set>.mongodb.net/<your database name>?authSource=admin&replicaSet=portal-shard-0&readPreference=primary&ssl=true
your replical set will be there automatically,
those you need to supply to your connection string are username, password and database name
so change the admin in your URL to one of your database name
Your username and password is the username and password of the user your created under Database Access in your mongo dashboard sidebar

Related

mongoclient db.databaseName always returns admin

I'm using nodejs mongodb module v2.2.34
When I connect to a DB using this format:
mongodb+srv://<username>:<password>#MYATLASSERVER.azure.mongodb.net/mydatabase
db.databaseName always returns admin instead of mydatabase.
Why would this happen and how do I get it to return mydatabase as expected?
Thanks!
OK, I think I found the solution
updated the driver to 3.5 and then used:
db.s.options.dbName
seems like a weird object path to get the name from
It's annoying that mongo keeps changing the paths of things with driver / version updates. But I guess that's what we gotta deal with. Feel free to post other solutions if there are more stable ways of doing this. Or to explain why this change was made.

Issue with URI in cloneCollection command

I have two separate mongoDBs on our network. I want to periodically copy collections from a production like db to our testing dbs. I think clone collection is the simplest way to do this but I can't get the URI correct.
I'm getting the error more than one ':' detected. If this is an ipv6 address, it needs to be surrounded by '[' and ']';
Well I've tried reformatting the URI in several different ways but i haven't gotten it correct yet and continue to get errors.
This is what i think should work:
db.cloneCollection('mongodb://username:password#www.server.com/dbname', 'equipment', {})
I expect to be able to clone the collection sitting in another db to the current db.
From mongodb document
db.cloneCollection() cannot be used if the from server has authorization enabled.

How to specify my dbName in mongodb connection string with authentication?

In my express/mongoose app, say I have multiple dbs in the same mongodb server, one is xxx. If I don't have authenticaion, my connection string looks like
mongodb://myserver.cloudappserver.net/xxx
which works great. Now, I added authentication as
use admin
db.createUser({user:"admin",pwd:"yyy",roles:[{role:"root",db:"admin"}]});
Based on documentation, my connection string should look like
mongodb://admin:yyy#myserver.cloudappserver.net/admin
Now, my question is how do I specify the db "xxx" I want to work with?
I figured out based on this... the connection string should look like this
mongodb://admin:yyy#myserver.cloudappserver.net/xxx?authSource=admin

Is meteor using the Mongo Oplog?

How can I check if meteor is using the oplog of my mongo?
I have a cluster of mongo and set two envs for my meteor.
MONGO_URL=mongodb://mongo/app?replicaSet=rs0
MONGO_OPLOG_URL=mongodb://mongo/local?authSource=app
How can I check if the opt log is actually in use. Meteor can fallback to query polling which is very inefficient but I would like to see if it's working properly with the oplog.
Any ideas?
Quoting the relevant bits from Meteor's OplogObserveDriver docs:
How to tell if your queries are using OplogObserveDriver
For now, we only have a crude way to tell how many observeChanges calls are using OplogObserveDriver, and not which calls they are.
This uses the facts package, an internal Meteor package that exposes real-time metrics for the current Meteor server. In your app, run meteor add facts, and add the {{> serverFacts}} template to your app. If you are using the autopublish package, Meteor will automatically publish all metrics to all users. If you are not using autopublish, you will have to tell Meteor which users can see your metrics by calling Facts.setUserIdFilter in server code; for example:
Facts.setUserIdFilter(function (userId) {
var user = Meteor.users.findOne(userId);
return user && user.admin;
});
(When running your app locally, Facts.setUserIdFilter(function () { return true; }); may be good enough!)
Now look at your app. The facts template will render a variety of metrics; the ones we're looking for are observe-drivers-oplog and observe-drivers-polling in the mongo-livedata section. If observe-drivers-polling is zero or not rendered at all, then all of your observeChanges calls are using OplogObserveDriver!
To set up oplog tailing, you need to set up a user on my_database, and an oplog_user on local. Then, specify the following URIs to connect to your replica set named test-shard (e.g. if there are 3 hosts named test-shard-[0-2]):
MONGO_URL="mongodb://user:PASS#test-shard-0.mongodb.net:27017,test-shard-1.mongodb.net:27017,test-shard-2.mongodb.net:27017/my_database?ssl=true&replicaSet=test-shard&authSource=admin"
MONGO_OPLOG_URL="mongodb://oplog_user:PASS#test-shard-0.mongodb.net:27017,test-shard-1.mongodb.net:27017,test-shard-2.mongodb.net:27017/local?ssl=true&replicaSet=test-shard&authSource=admin"
On MongoDB Atlas they require ssl=true, and also all users authenticate through the admin database. On another deployment you might just authenticate through my_database, in which case you'd remove the authsource=admin for MONGO_URL and write authsource=my_database for MONGO_OPLOG_URL. See this post for another example.
With MongoDB 3.6 and the Mongo node driver 3.0+, you may be able to use a succinct notation for DNS seedlist connections, e.g. on MongoDB Atlas, to specify the environment variables:
MONGO_URL="mongodb+srv://user:PASS#foo.mongodb.net/my_database"
MONGO_OPLOG_URL="mongodb+srv://oplog_user:PASS#foo.mongodb.net/local"
The link above explains how this notation fills in the ssl, replicaSet, and authSource arguments. This is a lot nicer than the long strings above, and also means you can scale your replica set up and down without needing to reconfigure anything.
As hwillson mentioned, use the facts-ui and facts-base packages (formerly facts) to see if there are any oplogObserveDrivers running in your app. If they are all pollingObserveDriver, than oplog is not set up correctly.
If you are using Kadira APM to monitor your app's performance, you can see if oplogs are working by navigating to the "Live Queries" section and having a look at the "Oplog notifications" chart.
You can see in my screenshot that oplogs are working, as values appear in the chart (bottom right). If oplogs weren't working then this chart would be empty.
This may be very late, but this is the only way that worked for me :
someCollection._driver.mongo._oplogHandle
if this is set to null then the oplog is not enabled, otherwise you can use this handle to check for more details.

Creating a MongoDB Replica Set Service in DreamFactory

I'm trying to create a Service using a MongoDB Replica Set. MongoDB's docs says here that the connection string format has to be
mongodb://[username:password#]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
So, my connection string is something like
mongodb://IP1:PORT1,IP2:PORT2,IP3:PORT3/DATABASE?replicaSet=REPLICA_SET_NAME
But when I try to explore the service, I'm not getting any data, collection or schema and I noticed that DreamFactory created another database called "DATABASE?replicaSet=REPLICA_SET_NAME". I tried to just remove these options "replicaSet=REPLICA_SET_NAME" to see what happens and then I'm getting this error while I explore:
{
"error": [
{
"context": null,
"message": "Failed to list resources for this service.\nIP1:PORT1: not master and slaveOk=false",
"code": 500
}
]
}
If I keep trying to explore the same REST Endpoint (for instance, /rest/API-NAME?names_only=true&include_schemas=true), then I eventually get the correct response. It seems that it tries with a different ip and port every time I make the request.
I also noticed that if I just leave the primary server and remove the options from the connection string, then it works fine. But this is pointless, because I'm losing the whole replica set point.
I even tried to set a lookup key with the name "replicaSet" equals to REPLICA_SET_NAME, but it didn't work either.
How can I use MongoDB replica sets with DreamFactory?
This may not be the solution to your problem but I have few observations.
Techically, your connection string are fine. But what I have found in DreamFactory is, they don't seem to allow options with the connection string. They seem to allow only authentication and database name in connection string. It is considering "DATABASE?replicaSet=REPLICA_SET_NAME" as the database name because they only allow database name in the URI.
This is info box text below the text field to enter the connection string in DreamFactory - "The connection string can include authentication credentials as well as database name. If they contain special characters, please enter them below."
Looks like they meant, "only authentication credentials as well as database name."
When you remove the option "replicaSet=REPLICA_SET_NAME", then you get the desired database name. But since you have replicaset nodes in connection, it will pick one server from them and connect to it. If it connects to primary node things work well as you can read and write to primary node. If it happens to chooses a node that is not primary then you have "Failed to list resources for this service.\nIP1:PORT1: not master and slaveOk=false" error.
The only condition when this should work is -
1. You connect only to the primary node, just to avoid connecting to secondaries.
2. you pass only the database name, just to escape messing up the database name
That's why it works when you just leave the primary server and also remove the options from connection string.