Skip to content

Commit 4328341

Browse files
committed
feat(commands): new "document migrate" subcommand
1 parent 73111ea commit 4328341

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

django_opensearch_dsl/management/commands/opensearch.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,11 @@ def _manage_document(
212212
self.stderr.write(f"Error while filtering on '{model}' (from index '{index._name}'):\n{e}'") # noqa
213213
exit(1)
214214
else:
215-
s += f"\n\t- {qs} {document.django.model.__name__}."
215+
if action == OpensearchAction.MIGRATE:
216+
prefix = ""
217+
else:
218+
prefix = f" {qs}"
219+
s += f"\n\t- {prefix} {document.django.model.__name__}."
216220

217221
# Display expected actions
218222
if verbosity or not force:
@@ -231,28 +235,34 @@ def _manage_document(
231235
result = "\n"
232236
for index, kwargs in zip(indices, kwargs_list):
233237
document = index._doc_types[0]() # noqa
234-
qs = document.get_indexing_queryset(stdout=self.stdout._out, verbose=verbosity, action=action, **kwargs)
235-
success, errors = document.update(
236-
qs, action,
237-
parallel=parallel, index_suffix=index_suffix,
238-
refresh=refresh, raise_on_error=False
239-
)
240-
241-
success_str = self.style.SUCCESS(success) if success else success
242-
errors_str = self.style.ERROR(len(errors)) if errors else len(errors)
243238
model = document.django.model.__name__
244239

245-
if verbosity == 1:
246-
result += f"{success_str} {model} successfully {action.past}, {errors_str} errors:\n"
247-
reasons = defaultdict(int)
248-
for e in errors: # Count occurrence of each error
249-
error = e.get(action, {"result": "unknown error"}).get("result", "unknown error")
250-
reasons[error] += 1
251-
for reasons, total in reasons.items():
252-
result += f" - {reasons} : {total}\n"
240+
if action == OpensearchAction.MIGRATE:
241+
document.migrate(index_suffix)
242+
if verbosity >= 1:
243+
result += f"{model} successfully migrated to index {document.get_index_name(suffix=index_suffix)}\n"
244+
else:
245+
qs = document.get_indexing_queryset(stdout=self.stdout._out, verbose=verbosity, action=action, **kwargs)
246+
success, errors = document.update(
247+
qs, action,
248+
parallel=parallel, index_suffix=index_suffix,
249+
refresh=refresh, raise_on_error=False
250+
)
251+
252+
success_str = self.style.SUCCESS(success) if success else success
253+
errors_str = self.style.ERROR(len(errors)) if errors else len(errors)
254+
255+
if verbosity == 1:
256+
result += f"{success_str} {model} successfully {action.past}, {errors_str} errors:\n"
257+
reasons = defaultdict(int)
258+
for e in errors: # Count occurrence of each error
259+
error = e.get(action, {"result": "unknown error"}).get("result", "unknown error")
260+
reasons[error] += 1
261+
for reasons, total in reasons.items():
262+
result += f" - {reasons} : {total}\n"
253263

254-
if verbosity > 1:
255-
result += f"{success_str} {model} successfully {action}d, {errors_str} errors:\n {errors}\n"
264+
if verbosity > 1:
265+
result += f"{success_str} {model} successfully {action}d, {errors_str} errors:\n {errors}\n"
256266

257267
if verbosity:
258268
self.stdout.write(result + "\n")
@@ -308,11 +318,12 @@ def add_arguments(self, parser):
308318
subparser.add_argument(
309319
"action",
310320
type=str,
311-
help="Whether you want to index, delete or update documents in indices.",
321+
help="Whether you want to index, delete or update documents in indices. Or migrate from an index to another.",
312322
choices=[
313323
OpensearchAction.INDEX.value,
314324
OpensearchAction.DELETE.value,
315325
OpensearchAction.UPDATE.value,
326+
OpensearchAction.MIGRATE.value,
316327
],
317328
)
318329
subparser.add_argument(
@@ -345,7 +356,7 @@ def add_arguments(self, parser):
345356
),
346357
)
347358
subparser.add_argument("--force", action="store_true", default=False, help="Do not ask for confirmation.")
348-
subparser.add_argument("--index-suffix", type=str, default=None, help="The suffix for the index name (if you don't provide one, the current index will be used).")
359+
subparser.add_argument("--index-suffix", type=str, default=None, help="The suffix for the index name (if you don't provide one, the current index will be used). Required for `migrate` subcommand.")
349360
subparser.add_argument(
350361
"-i", "--indices", type=str, nargs="*", help="Only update documents on the given indices."
351362
)

django_opensearch_dsl/management/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class OpensearchAction(str, Enum):
77
INDEX = ("index", "indexing", "indexed")
88
UPDATE = ("update", "updating", "updated")
99
CREATE = ("create", "creating", "created")
10+
MIGRATE = ("migrate", "migrating", "migrated")
1011
LIST = ("list", "listing", "listed")
1112
DELETE = ("delete", "deleting", "deleted")
1213

tests/tests/management/test_document.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,11 @@ def test_index_not_refresh(self):
232232
self.assertEqual(ContinentDocument.search().count(), 3)
233233
self.assertEqual(CountryDocument.search().count(), 3)
234234
self.assertEqual(EventDocument.search().count(), 3)
235+
236+
def test_migrate(self):
237+
self.call_command("opensearch", "index", "create", suffix="v1", force=True)
238+
self.call_command("opensearch", "index", "create", suffix="v2", force=True)
239+
self.assertEqual(CountryDocument.get_active_index()._name, "country--v1")
240+
241+
self.call_command("opensearch", "document", "migrate", index_suffix="v2", force=True)
242+
self.assertEqual(CountryDocument.get_active_index()._name, "country--v2")

0 commit comments

Comments
 (0)