Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for running MongoDB queries on secondary in replicaset mode #1424

Merged
merged 7 commits into from
Jan 23, 2020
Merged
37 changes: 31 additions & 6 deletions redash/query_runner/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,31 @@ class MongoDB(BaseQueryRunner):
@classmethod
def configuration_schema(cls):
return {
"type": "object",
"properties": {
"connectionString": {"type": "string", "title": "Connection String"},
"dbName": {"type": "string", "title": "Database Name"},
"replicaSetName": {"type": "string", "title": "Replica Set Name"},
'type': 'object',
'properties': {
'connectionString': {
'type': 'string',
'title': 'Connection String'
},
'dbName': {
'type': 'string',
'title': "Database Name"
},
'replicaSetName': {
'type': 'string',
'title': 'Replica Set Name'
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arikfr I'm wondering why restyled didn't catch this change of style if black would have turned the single quotes into double quotes?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤷 no idea.

"readPreference": {
"type": "string",
"extendedEnum": [
{"value": "primary", "name": "Primary"},
{"value": "primaryPreferred", "name": "Primary Preferred"},
{"value": "secondary", "name": "Secondary"},
{"value": "secondaryPreferred", "name": "Secondary Preferred"},
{"value": "nearest", "name": "Nearest"},
],
"title": "Replica Set Read Preference",
}
},
"required": ["connectionString", "dbName"],
}
Expand All @@ -158,10 +178,12 @@ def __init__(self, configuration):
)

def _get_db(self):
kwargs = {}
if self.is_replica_set:
db_connection = pymongo.MongoClient(
self.configuration["connectionString"],
replicaSet=self.configuration["replicaSetName"],
readPreference=self.configuration.get("readPreference", "primaryPreferred")
arikfr marked this conversation as resolved.
Show resolved Hide resolved
)
else:
db_connection = pymongo.MongoClient(self.configuration["connectionString"])
Expand All @@ -173,6 +195,9 @@ def test_connection(self):
if not db.command("connectionStatus")["ok"]:
raise Exception("MongoDB connection error")

return db_connection[self.db_name]


def _merge_property_names(self, columns, document):
for property in document:
if property not in columns:
Expand All @@ -192,7 +217,7 @@ def _get_collection_fields(self, db, collection_name):
# For now, the logic is to take the first and last documents (last is determined
# by the Natural Order (http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order)
# as we don't know the correct order. In most single server installations it would be
# find. In replicaset when reading from non master it might not return the really last
# fine. In replicaset when reading from non master it might not return the really last
# document written.
collection_is_a_view = self._is_collection_a_view(db, collection_name)
documents_sample = []
Expand Down