7

I have a mongo replica including one primary two secondaries. There are some accounts only have access to the secondary server. When I connect to one of the secondary through nodejs driver, I couldn't find a way to enable slaveOk. Below is my code. I have to connect to it as a normal server rather than a replica.

options = options || {
        connectTimeoutMS: 30000,
        socketTimeoutMS: 30000,
        // retry to connect for 30 times
        reconnectTries: 30,
        // wait 1 second before retrying
        reconnectInterval: 1000,
        readPreference: mongodb.ReadPreference.SECONDARY_PREFERRED
      };
mongoClient.connect("mongodb://user:pwd@10.0.0.1/test", options, (err, db) => {
    db.command({listCollections: 1})
       .catch((e) => {
         // get exception here about "not master and slaveOk=false" 
       })
}

when I run above code, I will get the exception saying that not master and slaveOk=false. I know that I need to enable slaveOk on the connection before run db.command({listCollections: 1}) but I didn't find a way for that. I know there is a readPreference on options but I have tried below values none of them work:

ReadPreference.PRIMARY, 
ReadPreference.PRIMARY_PREFERRED, 
ReadPreference.SECONDARY, 
ReadPreference.SECONDARY_PREFERRED, 
ReadPreference.NEAREST

In Mongo Shell, I can run rs.slaveOk() command to enable read on the connection on secondary server. Is there a way to enable slaveOk on nodejs driver? So I can run listCollection command through dirver.

Joey Yi Zhao
  • 37,514
  • 71
  • 268
  • 523
  • What do you mean by *"none of them work"*? What are you expecting to happen? Note that in 9/10 cases you really do not want to read from a secondary, unless you really understand what that means. Please elaborate on what you expect and why. – Neil Lunn Jun 30 '17 at 05:41
  • Thanks for pointing out the issue. I have updated my post. What I want to do is to run some commands through nodejs driver on secondary server, for example: `listCollection`. – Joey Yi Zhao Jun 30 '17 at 05:46
  • So the question basically is *"When I set a read preference on the connection and confirm that I am attached to a secondary node, how do I run the `listCollection` command"*? Yep? Some reason why you don't use the driver method that already does this? [`listCollections()`](http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html#listCollections) Noting that you can even just directly specify the "read preference" to that method rather than forcing it on the connection. – Neil Lunn Jun 30 '17 at 05:51
  • Yep, actually running `listCollection` is only one of the command I need. I also need to run other methods such as `db.admin().listDatabases()`. This method also throw exception with the same error – Joey Yi Zhao Jun 30 '17 at 06:32
  • Have you actually supplied the read preference option to that method? Please show the code where you actually try this. I'm trying to avoid this going around in circles because there is no such connection option for slaveOk anymore. It has been removed since the 2.x release of the driver. You are supposed to be using the readPreference. I also go back to the original point that listing collections or anything on a secondary node is not a "guaranteed" process anyway. These things "should" be done from the primary only. – Neil Lunn Jun 30 '17 at 06:43
  • I have updated the code and added `readPreference` options there. It seems the `readPreference` doesn't help. I still get exception because of `not master and slaveOk=false` error. We have DBAs who only have access to secondary servers. So they need to use our application to do some read operations. – Joey Yi Zhao Jun 30 '17 at 06:49

1 Answers1

8

What worked for me was putting the read prefences argument as ?readPreference=secondaryPreferred into the connect url.

Read from secondary replica set in mongodb through javascript has a more complete example.

Andrew Lipscomb
  • 936
  • 8
  • 19
  • This will cause a serious change on the replicaset which I don't want . – Joey Yi Zhao Feb 08 '19 at 09:49
  • I might be missing something about your case but it shouldn't - [secondary replicas are read only](https://docs.mongodb.com/manual/core/replica-set-secondary/) – Andrew Lipscomb Feb 10 '19 at 21:25
  • You can set `slaveOk` via mongo shell but you can't set it via driver – Joey Yi Zhao Feb 11 '19 at 05:37
  • 1
    You can set it in the driver - the [link](https://stackoverflow.com/a/39769834/3886090) above shows you how. It appears to only be settable on connection - not after (which is not really well documented) – Andrew Lipscomb Feb 11 '19 at 08:23