Skip to content

Commit 9f45e22

Browse files
committed
Much faster query times (for Source) by _not_ manipulating
Django ORM objects and instead using raw dictionaries.
1 parent 34c5a4c commit 9f45e22

2 files changed

Lines changed: 46 additions & 17 deletions

File tree

src/api/contrib/samples.http

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,29 @@ Accept-Language: en-US,en;q=0.5
102102

103103
###
104104

105+
# @name VoyageSources
106+
POST {{CurrentHost}}/contrib/data
107+
Accept: application/json
108+
Content-Type: application/json
109+
Accept-Language: en-US,en;q=0.5
110+
111+
{
112+
"q1": {
113+
"query": {
114+
"model": "document_source",
115+
"filter": []
116+
},
117+
"fields": [
118+
"title",
119+
"short_ref",
120+
"bib",
121+
"notes"
122+
]
123+
}
124+
}
125+
126+
###
127+
105128
# @name location_tree
106129
GET {{CurrentHost}}/contrib/location_tree
107130

src/api/contrib/views.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ def to_q(self) -> Q:
3232
# Default to equals
3333
return Q(**{self.field: self.value})
3434

35+
def remap(r: dict[str, any], remapped: list[str]):
36+
for f in remapped:
37+
key = f.replace("_id", "")
38+
if key in r:
39+
r[f] = r[key]
40+
del r[key]
41+
return r
42+
3543

3644
class DataQuery:
3745
"""Represents a query on a specific model with filters."""
@@ -57,25 +65,23 @@ def execute(self, fields: List[str]) -> List[ResolvedEntityData]:
5765
query &= filter_obj.to_q()
5866

5967
# Execute the query and return the results
60-
queryset = model_class.objects.filter(query)
61-
# Convert to list of dictionaries with only the requested fields
62-
result = []
63-
for instance in queryset:
64-
entity_data = {}
65-
for field in fields:
66-
try:
67-
value = getattr(instance, field)
68-
# Ensure the value is of a compatible type
69-
if value is not None and not isinstance(value, (str, int, float, bool)):
70-
value = str(value)
71-
entity_data[field] = value
72-
except AttributeError:
73-
entity_data[field] = None
74-
result.append(entity_data)
75-
68+
# Get all valid field names for the model
69+
valid_field_names = {f.name for f in model_class._meta.fields}
70+
# Filter out invalid field names.
71+
# First detect fields with _id suffix that should be remapped.
72+
remapped = [f for f in fields if "_id" in f and f not in valid_field_names]
73+
fields = [f.replace("_id", "") if f in remapped else f for f in fields]
74+
valid_fields = [f for f in fields if f in valid_field_names]
75+
if len(valid_fields) < len(fields):
76+
print("Invalid fields found in query: ")
77+
print([f for f in fields if f not in valid_fields])
78+
print("Expected:")
79+
print(valid_field_names)
80+
result = list(model_class.objects.filter(query).values(*valid_fields))
81+
if len(remapped) > 0:
82+
result = [remap(r, remapped) for r in result]
7683
return result
7784

78-
7985
class DataResolver:
8086
"""Resolver for a single data query."""
8187

0 commit comments

Comments
 (0)