|
| 1 | +from pathlib import Path |
| 2 | +from unittest import TestCase |
| 3 | + |
| 4 | +from bson import ObjectId, encode, json_util |
| 5 | + |
| 6 | +from .base import PerformanceTest |
| 7 | +from .models import ( |
| 8 | + IntegerEmbeddedModel, |
| 9 | + LargeNestedModel, |
| 10 | + StringEmbeddedModel, |
| 11 | +) |
| 12 | + |
| 13 | + |
| 14 | +class LargeNestedDocTest(PerformanceTest): |
| 15 | + """Parent class for large nested document tests.""" |
| 16 | + |
| 17 | + dataset = "large_doc_nested.json" |
| 18 | + |
| 19 | + def setUp(self): |
| 20 | + super().setUp() |
| 21 | + with open( # noqa: PTH123 |
| 22 | + Path(self.test_data_path) / Path("nested-models") / self.dataset |
| 23 | + ) as data: |
| 24 | + self.document = json_util.loads(data.read()) |
| 25 | + |
| 26 | + self.data_size = len(encode(self.document)) * self.num_docs |
| 27 | + self.documents = [self.document.copy() for _ in range(self.num_docs)] |
| 28 | + |
| 29 | + def setUpData(self): |
| 30 | + for doc in self.documents: |
| 31 | + model = LargeNestedModel() |
| 32 | + for field_name, model_data in doc.items(): |
| 33 | + if "array" in field_name: |
| 34 | + array_models = [] |
| 35 | + for item in model_data: |
| 36 | + embedded_str_model = StringEmbeddedModel(**item) |
| 37 | + embedded_str_model.unique_field = str(ObjectId()) |
| 38 | + array_models.append(embedded_str_model) |
| 39 | + setattr(model, field_name, array_models) |
| 40 | + elif "embedded_str_doc" in field_name: |
| 41 | + embedded_str_model = StringEmbeddedModel(**model_data) |
| 42 | + embedded_str_model.unique_field = str(ObjectId()) |
| 43 | + setattr(model, field_name, embedded_str_model) |
| 44 | + else: |
| 45 | + embedded_int_model = IntegerEmbeddedModel(**model_data) |
| 46 | + setattr(model, field_name, embedded_int_model) |
| 47 | + model.save() |
| 48 | + |
| 49 | + |
| 50 | +class TestLargeNestedDocCreation(LargeNestedDocTest, TestCase): |
| 51 | + """Benchmark for creating a large nested document.""" |
| 52 | + |
| 53 | + def do_task(self): |
| 54 | + for doc in self.documents: |
| 55 | + model = LargeNestedModel() |
| 56 | + for field_name, model_data in doc.items(): |
| 57 | + if "array" in field_name: |
| 58 | + array_models = [] |
| 59 | + for item in model_data: |
| 60 | + embedded_str_model = StringEmbeddedModel(**item) |
| 61 | + embedded_str_model.unique_field = str(ObjectId()) |
| 62 | + array_models.append(embedded_str_model) |
| 63 | + setattr(model, field_name, array_models) |
| 64 | + elif "embedded_str_doc" in field_name: |
| 65 | + embedded_str_model = StringEmbeddedModel(**model_data) |
| 66 | + embedded_str_model.unique_field = str(ObjectId()) |
| 67 | + setattr(model, field_name, embedded_str_model) |
| 68 | + else: |
| 69 | + embedded_int_model = IntegerEmbeddedModel(**model_data) |
| 70 | + setattr(model, field_name, embedded_int_model) |
| 71 | + model.save() |
| 72 | + |
| 73 | + def after(self): |
| 74 | + LargeNestedModel.objects.all().delete() |
| 75 | + |
| 76 | + |
| 77 | +class TestLargeNestedDocUpdate(LargeNestedDocTest, TestCase): |
| 78 | + """Benchmark for updating an embedded field within a large nested document.""" |
| 79 | + |
| 80 | + def setUp(self): |
| 81 | + super().setUp() |
| 82 | + self.setUpData() |
| 83 | + self.models = list(LargeNestedModel.objects.all()) |
| 84 | + self.data_size = len(encode({"field1": "updated_value0"})) * self.num_docs |
| 85 | + self.iteration = 0 |
| 86 | + |
| 87 | + def do_task(self): |
| 88 | + for model in self.models: |
| 89 | + model.embedded_str_doc_1.field1 = "updated_value" + str(self.iteration) |
| 90 | + model.save() |
| 91 | + self.iteration += 1 |
| 92 | + |
| 93 | + def tearDown(self): |
| 94 | + super().tearDown() |
| 95 | + LargeNestedModel.objects.all().delete() |
| 96 | + |
| 97 | + |
| 98 | +class TestLargeNestedDocFilterById(LargeNestedDocTest, TestCase): |
| 99 | + """Benchmark for filtering large nested documents by a unique field in an embedded document.""" |
| 100 | + |
| 101 | + def setUp(self): |
| 102 | + super().setUp() |
| 103 | + self.setUpData() |
| 104 | + self.ids = [ |
| 105 | + model.embedded_str_doc_1.unique_field for model in list(LargeNestedModel.objects.all()) |
| 106 | + ] |
| 107 | + |
| 108 | + def do_task(self): |
| 109 | + for _id in self.ids: |
| 110 | + list(LargeNestedModel.objects.filter(embedded_str_doc_1__unique_field=_id)) |
| 111 | + |
| 112 | + def tearDown(self): |
| 113 | + super().tearDown() |
| 114 | + LargeNestedModel.objects.all().delete() |
| 115 | + |
| 116 | + |
| 117 | +class TestLargeNestedDocFilterArray(LargeNestedDocTest, TestCase): |
| 118 | + """Benchmark for filtering large nested documents using the __in operator |
| 119 | + for unique values in an embedded document array.""" |
| 120 | + |
| 121 | + def setUp(self): |
| 122 | + super().setUp() |
| 123 | + self.setUpData() |
| 124 | + self.ids = [ |
| 125 | + model.embedded_str_doc_array[0].unique_field |
| 126 | + for model in list(LargeNestedModel.objects.all()) |
| 127 | + ] |
| 128 | + |
| 129 | + def do_task(self): |
| 130 | + for _id in self.ids: |
| 131 | + list(LargeNestedModel.objects.filter(embedded_str_doc_array__unique_field__in=[_id])) |
| 132 | + |
| 133 | + def tearDown(self): |
| 134 | + super().tearDown() |
| 135 | + LargeNestedModel.objects.all().delete() |
0 commit comments