Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions chatterbot/storage/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,21 @@ class MongoDatabaseAdapter(StorageAdapter):
`MongoDB connection string <https://docs.mongodb.com/manual/reference/connection-string/>`_
:type database_uri: str

:keyword mongodb_client_kwargs: Additional keyword arguments to pass to the MongoClient constructor.
This can include SSL/TLS settings, authentication options, and other
PyMongo client configuration parameters.
:type mongodb_client_kwargs: dict

.. code-block:: python

# Basic connection
database_uri='mongodb://example.com:8100/'

# Connection with SSL/TLS (e.g., Amazon DocumentDB)
database_uri='mongodb://USER:[email protected]:27017/?ssl=true&replicaSet=rs0',
mongodb_client_kwargs={
'tlsCAFile': 'path/to/rds-combined-ca-bundle.pem'
}
"""

def __init__(self, **kwargs):
Expand All @@ -27,8 +39,11 @@ def __init__(self, **kwargs):
'database_uri', 'mongodb://localhost:27017/chatterbot-database'
)

# Use the default host and port
self.client = MongoClient(self.database_uri)
# Extract additional MongoClient parameters
mongodb_client_kwargs = kwargs.get('mongodb_client_kwargs', {})

# Use the default host and port with additional client parameters
self.client = MongoClient(self.database_uri, **mongodb_client_kwargs)

# Increase the sort buffer to 42M if possible
try:
Expand Down
88 changes: 88 additions & 0 deletions docs/storage/mongodb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,93 @@ To start the MongoDB container, run:

For more information on Docker and ``docker compose``, see the `Docker Compose documentation`_.

Using MongoDB with SSL/TLS
--------------------------

For secure connections to remote MongoDB instances (such as Amazon DocumentDB, MongoDB Atlas, or production deployments), you can use SSL/TLS certificates.

Amazon DocumentDB Example
~~~~~~~~~~~~~~~~~~~~~~~~~

Amazon DocumentDB requires SSL/TLS connections with a certificate file. Here's how to configure ChatterBot:

1. Download the Amazon RDS CA certificate bundle:

.. code-block:: bash

wget https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

2. Configure ChatterBot to use the certificate:

.. code-block:: python

from chatterbot import ChatBot

bot = ChatBot(
'MyBot',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter',
database_uri='mongodb://USERNAME:[email protected]:27017/?ssl=true&replicaSet=rs0&readPreference=secondaryPreferred',
mongodb_client_kwargs={
'tlsCAFile': 'global-bundle.pem' # Path to your certificate file
}
)

MongoDB Atlas Example
~~~~~~~~~~~~~~~~~~~~~

For MongoDB Atlas with SSL/TLS:

.. code-block:: python

from chatterbot import ChatBot

bot = ChatBot(
'MyBot',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter',
database_uri='mongodb+srv://USERNAME:[email protected]/?retryWrites=true&w=majority',
mongodb_client_kwargs={
'tls': True,
'tlsAllowInvalidCertificates': False # Use True only for testing
}
)

Self-Signed Certificates
~~~~~~~~~~~~~~~~~~~~~~~~

If you're using self-signed certificates:

.. code-block:: python

from chatterbot import ChatBot

bot = ChatBot(
'MyBot',
storage_adapter='chatterbot.storage.MongoDatabaseAdapter',
database_uri='mongodb://localhost:27017/chatterbot-database?ssl=true',
mongodb_client_kwargs={
'tlsCAFile': '/path/to/ca.pem',
'tlsCertificateKeyFile': '/path/to/client.pem',
'tlsAllowInvalidCertificates': False
}
)

Additional MongoDB Client Options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The ``mongodb_client_kwargs`` parameter accepts any valid PyMongo MongoClient options, including:

- ``tlsCAFile``: Path to CA certificate file
- ``tlsCertificateKeyFile``: Path to client certificate file
- ``tls``: Enable/disable TLS
- ``tlsAllowInvalidCertificates``: Allow invalid certificates (not recommended for production)
- ``serverSelectionTimeoutMS``: Timeout for server selection
- ``connectTimeoutMS``: Connection timeout
- ``socketTimeoutMS``: Socket timeout
- ``maxPoolSize``: Maximum connection pool size
- ``minPoolSize``: Minimum connection pool size

For a complete list of options, see the `PyMongo MongoClient documentation`_.

MongoDB Adapter Class Attributes
--------------------------------

Expand All @@ -50,3 +137,4 @@ MongoDB Adapter Class Attributes

.. _pymongo: https://pypi.org/project/pymongo/
.. _Docker Compose documentation: https://docs.docker.com/compose/
.. _PyMongo MongoClient documentation: https://pymongo.readthedocs.io/en/stable/api/pymongo/mongo_client.html
25 changes: 24 additions & 1 deletion tests/storage/test_mongo_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ def setUpClass(cls):

cls.has_mongo_connection = False

cls.database_uri = 'mongodb://localhost:27017/chatterbot_test_database'

try:
client = MongoClient(
serverSelectionTimeoutMS=0.1
)
client.server_info()

cls.adapter = MongoDatabaseAdapter(
database_uri='mongodb://localhost:27017/chatterbot_test_database',
database_uri=cls.database_uri,
raise_on_missing_search_text=False
)

Expand Down Expand Up @@ -72,6 +74,27 @@ def test_count_returns_value(self):
self.adapter.create(text="Test statement")
self.assertEqual(self.adapter.count(), 1)

def test_mongodb_client_kwargs_parameter(self):
"""
Test that the adapter accepts mongodb_client_kwargs parameter.
This enables SSL/TLS connections to services like Amazon DocumentDB.
"""
adapter = MongoDatabaseAdapter(
database_uri=self.database_uri,
mongodb_client_kwargs={
'serverSelectionTimeoutMS': 100,
'connectTimeoutMS': 100
},
raise_on_missing_search_text=False
)

# Verify the adapter was created successfully
self.assertIsNotNone(adapter)
self.assertIsNotNone(adapter.client)

# Clean up
adapter.close()

def test_filter_text_statement_not_found(self):
"""
Test that None is returned by the find method
Expand Down
Loading