1
1
from django .db .backends .base .schema import BaseDatabaseSchemaEditor
2
+ from django .db .models import Index
3
+ from pymongo .operations import IndexModel
2
4
3
5
from .query import wrap_database_errors
4
6
@@ -7,11 +9,30 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
7
9
@wrap_database_errors
8
10
def create_model (self , model ):
9
11
self .connection .database .create_collection (model ._meta .db_table )
12
+ self ._create_model_indexes (model )
10
13
# Make implicit M2M tables.
11
14
for field in model ._meta .local_many_to_many :
12
15
if field .remote_field .through ._meta .auto_created :
13
16
self .create_model (field .remote_field .through )
14
17
18
+ def _create_model_indexes (self , model ):
19
+ """
20
+ Create all indexes (field indexes, index_together, Meta.indexes) for
21
+ the specified model.
22
+ """
23
+ if not model ._meta .managed or model ._meta .proxy or model ._meta .swapped :
24
+ return
25
+ # Field indexes
26
+ for field in model ._meta .local_fields :
27
+ if self ._field_should_be_indexed (model , field ):
28
+ self ._add_field_index (model , field )
29
+ # Meta.index_together (RemovedInDjango51Warning)
30
+ for field_names in model ._meta .index_together :
31
+ self ._add_composed_index (model , field_names )
32
+ # Meta.indexes
33
+ for index in model ._meta .indexes :
34
+ self .add_index (model , index )
35
+
15
36
def delete_model (self , model ):
16
37
# Delete implicit M2m tables.
17
38
for field in model ._meta .local_many_to_many :
@@ -29,6 +50,9 @@ def add_field(self, model, field):
29
50
self .connection .database [model ._meta .db_table ].update_many (
30
51
{}, [{"$set" : {column : self .effective_default (field )}}]
31
52
)
53
+ # Add an index, if required.
54
+ if self ._field_should_be_indexed (model , field ):
55
+ self ._add_field_index (model , field )
32
56
33
57
def _alter_field (
34
58
self ,
@@ -60,21 +84,45 @@ def remove_field(self, model, field):
60
84
# Unset field on existing documents.
61
85
if column := field .column :
62
86
self .connection .database [model ._meta .db_table ].update_many ({}, {"$unset" : {column : "" }})
87
+ if self ._field_should_be_indexed (model , field ):
88
+ self ._remove_field_index (model , field )
63
89
64
90
def alter_index_together (self , model , old_index_together , new_index_together ):
65
91
pass
66
92
67
93
def alter_unique_together (self , model , old_unique_together , new_unique_together ):
68
94
pass
69
95
70
- def add_index (self , model , index ):
71
- pass
96
+ def add_index (self , model , index , field = None ):
97
+ if index .contains_expressions :
98
+ return
99
+ index_orders = (
100
+ [(field .column , 1 )]
101
+ if field
102
+ else [
103
+ (model ._meta .get_field (field_name ).column , 1 if order == "" else - 1 )
104
+ for field_name , order in index .fields_orders
105
+ ]
106
+ )
107
+ idx = IndexModel (index_orders , name = index .name )
108
+ self .connection .database [model ._meta .db_table ].create_indexes ([idx ])
72
109
73
- def rename_index (self , model , old_index , new_index ):
74
- pass
110
+ def _add_composed_index (self , model , field_names ):
111
+ """Add an index on the given list of field_names."""
112
+ idx = Index (fields = field_names )
113
+ idx .set_name_with_model (model )
114
+ self .add_index (model , idx )
115
+
116
+ def _add_field_index (self , model , field ):
117
+ """Add an index on a field with db_index=True."""
118
+ index = Index (fields = [field .name ])
119
+ index .name = self ._create_index_name (model ._meta .db_table , [field .column ])
120
+ self .add_index (model , index , field = field )
75
121
76
122
def remove_index (self , model , index ):
77
- pass
123
+ if index .contains_expressions :
124
+ return
125
+ self .connection .database [model ._meta .db_table ].drop_index (index .name )
78
126
79
127
def add_constraint (self , model , constraint ):
80
128
pass
0 commit comments