-
Notifications
You must be signed in to change notification settings - Fork 0
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
feat: first poc implementation #2
Conversation
…ns, relations, single-table inheritance and single-table OneToOne relations. Not implemented yet are joins, aggregations (other than count), and embedded document arrays.
@@ -0,0 +1,9 @@ | |||
setup_local_db: | |||
@echo "Creating local database..." | |||
@atlas deployments setup local --type local --port 3307 --force |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
atlas cli local deployments support mongo search
return self.settings_dict | ||
|
||
def get_new_connection(self, conn_params): | ||
name = conn_params.get("NAME") or "test" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Django instantiates the connection in db-less mode (without db name) for operations such as create / drop database.
|
||
|
||
class DatabaseClient(BaseDatabaseClient): | ||
executable_name = "django_mongodb" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this class implements the django sqlshell command, which I personally don't use, so this is optional, but should be fairly easy
self.extr = None | ||
|
||
def build_mongo_filter(self, filter_expr): | ||
referenced_tables = set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bare predicate filter, which is used as $match
in query pipelines or as filter in update/delete.
django_mongodb/compiler.py
Outdated
{"$replaceRoot": {"newRoot": "$_id"}}, | ||
] | ||
|
||
def as_operation(self, with_limits=True, with_col_aliases=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MongoDB implementation of as_sql
of the base sql compiler
|
||
class DatabaseWrapper(BaseDatabaseWrapper): | ||
vendor = "django_mongodb" | ||
data_types = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the base configuration Django, but adapted where needed (notably objectid). Those are currently logical names only, used in prep operations, as we are not generating / updating schematas..
with self.wrap_database_errors: | ||
self.mongo_client.close() | ||
|
||
def _set_autocommit(self, autocommit): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not currently implement transactions, we are also not using any in the backend as of now. But should be possible actually without too much effort to do so, using client_session, and doesn't look that complicated at a first glance, but would need some investigation. Biggest benefit at the moment would be in testing, but for the few models we are using a db cleaning auto-fixture would do.
|
||
@cached_property | ||
def mongo_meta(self): | ||
if hasattr(self.query.model, "MongoMeta"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some custom meta class / props, at the moment only for defining what search indexes are set up on the collections, so that when doing queries via search, we can push the right lookups to the search index.
|
||
def execute_sql( | ||
self, result_type=MULTI, chunked_fetch=False, chunk_size=GET_ITERATOR_CHUNK_SIZE | ||
): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the entry point into the compiler for QuerySet
methods such as fetch_all
, udpate
, delete
.
The implementation is analoguous, but adapted where needed, from the implementation in the base SQLCompiler.
cursor.close() | ||
raise | ||
|
||
if result_type == CURSOR: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is used by raw queries, which rely on cursor methods such as rowcount
for info about query results
|
||
class MongoNothingNode(Node): | ||
def get_mongo_query(self, compiler, connection, is_search=...) -> dict: | ||
return {"$expr": {"$eq": [True, False]}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needed for Queryset#none
self.alias = alias | ||
|
||
def get_mongo(self): | ||
return {"$project": {(self.alias or self.col.target.attname): f"${self.col.target.column}"}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This maps the MongoDB field path to the attribute names we are defining in the MongoDB model.
self.query = query | ||
self.order = query.order_by | ||
|
||
def get_mongo_order(self, attname_as_key=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in aggregation queries, we already have the document with Django attribute names as keys and are setting attname_as_key=True
from django.db.backends.base.schema import BaseDatabaseSchemaEditor | ||
|
||
|
||
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does not at the moment implement and schema migrations. We could add support for field renames and type conversions here, if we'd have use for that.
extended = models.CharField(max_length=100) | ||
|
||
class Meta: | ||
db_table = "testapp_foomodel" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This child model is persistent with it's and it's parents fields in the same collection.
dbdc837
to
1b66fca
Compare
1b66fca
to
0a708d8
Compare
31f2b60
to
e8757a8
Compare
e8757a8
to
3dc452f
Compare
Still pretty basic implementation of Django database datapter for MongoDB.
Reference material on the Django ORM architecture:
https://simpleisbetterthancomplex.com/media/2016/11/db.pdf
This is working:
Notable omissions