Skip to content

Commit bdc2102

Browse files
committed
add geography field to dataset and usecase. Add sdg to usecase
1 parent b6d6dab commit bdc2102

File tree

10 files changed

+162
-5
lines changed

10 files changed

+162
-5
lines changed

api/models/Dataset.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class Dataset(models.Model):
5959
max_length=50, default=DatasetStatus.DRAFT, choices=DatasetStatus.choices
6060
)
6161
sectors = models.ManyToManyField("api.Sector", blank=True, related_name="datasets")
62+
geographies = models.ManyToManyField(
63+
"api.Geography", blank=True, related_name="datasets"
64+
)
6265
access_type = models.CharField(
6366
max_length=50,
6467
default=DatasetAccessType.PUBLIC,
@@ -91,6 +94,14 @@ def sectors_indexing(self) -> list[str]:
9194
"""
9295
return [sector.name for sector in self.sectors.all()] # type: ignore
9396

97+
@property
98+
def geographies_indexing(self) -> list[str]:
99+
"""Geographies for indexing.
100+
101+
Used in Elasticsearch indexing.
102+
"""
103+
return [geo.name for geo in self.geographies.all()] # type: ignore
104+
94105
@property
95106
def formats_indexing(self) -> list[str]:
96107
"""Formats for indexing.

api/models/UseCase.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class UseCase(models.Model):
4444
choices=UseCaseRunningStatus.choices,
4545
)
4646
sectors = models.ManyToManyField("api.Sector", blank=True, related_name="usecases")
47+
sdgs = models.ManyToManyField("api.SDG", blank=True, related_name="usecases")
48+
geographies = models.ManyToManyField(
49+
"api.Geography", blank=True, related_name="usecases"
50+
)
4751
contributors = models.ManyToManyField(
4852
"authorization.User", blank=True, related_name="contributed_usecases"
4953
)
@@ -75,5 +79,13 @@ def sectors_indexing(self):
7579
def tags_indexing(self):
7680
return [tag.value for tag in self.tags.all()] # type: ignore
7781

82+
@property
83+
def sdgs_indexing(self):
84+
return [sdg.code for sdg in self.sdgs.all()] # type: ignore
85+
86+
@property
87+
def geographies_indexing(self):
88+
return [geo.name for geo in self.geographies.all()] # type: ignore
89+
7890
class Meta:
7991
db_table = "use_case"

api/schema/dataset_schema.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from api.models import (
1414
Dataset,
15+
Geography,
1516
Metadata,
1617
Organization,
1718
Resource,
@@ -253,6 +254,7 @@ class UpdateMetadataInput:
253254
description: Optional[str] = None
254255
tags: Optional[List[str]] = None
255256
sectors: Optional[List[uuid.UUID]] = None
257+
geographies: Optional[List[int]] = None
256258
access_type: Optional[DatasetAccessTypeENUM] = DatasetAccessTypeENUM.PUBLIC
257259
license: Optional[DatasetLicenseENUM] = (
258260
DatasetLicenseENUM.CC_BY_SA_4_0_ATTRIBUTION_SHARE_ALIKE
@@ -328,6 +330,17 @@ def _add_update_dataset_sectors(dataset: Dataset, sectors: List[uuid.UUID]) -> N
328330
dataset.save()
329331

330332

333+
@trace_resolver(
334+
name="add_update_dataset_geographies", attributes={"component": "dataset"}
335+
)
336+
def _add_update_dataset_geographies(dataset: Dataset, geography_ids: List[int]) -> None:
337+
"""Update geographies for a dataset."""
338+
dataset.geographies.clear()
339+
geographies = Geography.objects.filter(id__in=geography_ids)
340+
dataset.geographies.add(*geographies)
341+
dataset.save()
342+
343+
331344
@strawberry.type
332345
class Query:
333346
@strawberry_django.field(
@@ -595,6 +608,8 @@ def add_update_dataset_metadata(
595608
_add_update_dataset_metadata(dataset, metadata_input)
596609
if update_metadata_input.sectors is not None:
597610
_add_update_dataset_sectors(dataset, update_metadata_input.sectors)
611+
if update_metadata_input.geographies is not None:
612+
_add_update_dataset_geographies(dataset, update_metadata_input.geographies)
598613
return MutationResponse.success_response(TypeDataset.from_django(dataset))
599614

600615
@strawberry_django.mutation(

api/schema/usecase_schema.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
from strawberry_django.pagination import OffsetPaginationInput
1717

1818
from api.models import (
19+
SDG,
1920
Dataset,
21+
Geography,
2022
Metadata,
2123
Organization,
2224
Sector,
@@ -62,6 +64,8 @@ class UpdateUseCaseMetadataInput:
6264
metadata: List[UCMetadataItemType]
6365
tags: Optional[List[str]]
6466
sectors: List[uuid.UUID]
67+
sdgs: Optional[List[uuid.UUID]]
68+
geographies: Optional[List[int]] = None
6569

6670

6771
use_case_running_status = strawberry.enum(UseCaseRunningStatus) # type: ignore
@@ -79,6 +83,8 @@ class UseCaseInputPartial:
7983
platform_url: Optional[str] = None
8084
tags: Optional[List[str]] = None
8185
sectors: Optional[List[uuid.UUID]] = None
86+
sdgs: Optional[List[uuid.UUID]] = None
87+
geographies: Optional[List[int]] = None
8288
started_on: Optional[datetime.date] = None
8389
completed_on: Optional[datetime.date] = None
8490

@@ -202,6 +208,23 @@ def _update_usecase_sectors(usecase: UseCase, sectors: List[uuid.UUID]) -> None:
202208
usecase.save()
203209

204210

211+
@trace_resolver(name="update_usecase_geographies", attributes={"component": "usecase"})
212+
def _update_usecase_geographies(usecase: UseCase, geography_ids: List[int]) -> None:
213+
"""Update geographies for a usecase."""
214+
usecase.geographies.clear()
215+
geographies = Geography.objects.filter(id__in=geography_ids)
216+
usecase.geographies.add(*geographies)
217+
usecase.save()
218+
219+
220+
@trace_resolver(name="update_usecase_sdgs", attributes={"component": "usecase"})
221+
def _update_usecase_sdgs(usecase: UseCase, sdgs: List[uuid.UUID]) -> None:
222+
sdgs_objs = SDG.objects.filter(id__in=sdgs)
223+
usecase.sdgs.clear()
224+
usecase.sdgs.add(*sdgs_objs)
225+
usecase.save()
226+
227+
205228
@trace_resolver(
206229
name="add_update_usecase_metadata",
207230
attributes={"component": "usecase", "operation": "mutation"},
@@ -339,6 +362,10 @@ def add_update_usecase_metadata(
339362
_update_usecase_tags(usecase, update_metadata_input.tags)
340363
_add_update_usecase_metadata(usecase, metadata_input)
341364
_update_usecase_sectors(usecase, update_metadata_input.sectors)
365+
if update_metadata_input.sdgs is not None:
366+
_update_usecase_sdgs(usecase, update_metadata_input.sdgs)
367+
if update_metadata_input.geographies is not None:
368+
_update_usecase_geographies(usecase, update_metadata_input.geographies)
342369
return TypeUseCase.from_django(usecase)
343370

344371
@strawberry_django.mutation(handle_django_errors=False)

api/types/type_dataset.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from api.models import Dataset, DatasetMetadata, Resource, Tag
1212
from api.types.base_type import BaseType
1313
from api.types.type_dataset_metadata import TypeDatasetMetadata
14+
from api.types.type_geo import TypeGeo
1415
from api.types.type_organization import TypeOrganization
1516
from api.types.type_resource import TypeResource
1617
from api.types.type_sector import TypeSector
@@ -78,6 +79,25 @@ def sectors(self, info: Info) -> List["TypeSector"]:
7879
except (AttributeError, Dataset.DoesNotExist):
7980
return []
8081

82+
@strawberry.field
83+
def geographies(self, info: Info) -> List["TypeGeo"]:
84+
"""Get geographies for this dataset.
85+
86+
Args:
87+
info: Request info
88+
89+
Returns:
90+
List[TypeGeo]: List of geographies
91+
"""
92+
try:
93+
from api.types.type_geo import TypeGeo
94+
95+
django_instance = cast(Dataset, self)
96+
queryset = django_instance.geographies.all()
97+
return TypeGeo.from_django_list(queryset)
98+
except (AttributeError, Dataset.DoesNotExist):
99+
return []
100+
81101
@strawberry.field
82102
def metadata(self) -> List["TypeDatasetMetadata"]:
83103
"""Get metadata for this dataset."""

api/types/type_usecase.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
)
1616
from api.types.base_type import BaseType
1717
from api.types.type_dataset import TypeDataset, TypeTag
18+
from api.types.type_geo import TypeGeo
1819
from api.types.type_organization import TypeOrganization
20+
from api.types.type_sdg import TypeSDG
1921
from api.types.type_sector import TypeSector
2022
from api.types.type_usecase_dashboard import TypeUseCaseDashboard
2123
from api.types.type_usecase_metadata import TypeUseCaseMetadata
@@ -113,6 +115,28 @@ def sectors(self) -> Optional[List["TypeSector"]]:
113115
except Exception:
114116
return []
115117

118+
@strawberry.field(description="Get SDGs associated with this use case.")
119+
def sdgs(self) -> Optional[List["TypeSDG"]]:
120+
"""Get SDGs associated with this use case."""
121+
try:
122+
queryset = self.sdgs.all() # type: ignore
123+
if not queryset.exists():
124+
return []
125+
return TypeSDG.from_django_list(queryset)
126+
except Exception:
127+
return []
128+
129+
@strawberry.field(description="Get geographies associated with this use case.")
130+
def geographies(self) -> Optional[List["TypeGeo"]]:
131+
"""Get geographies associated with this use case."""
132+
try:
133+
queryset = self.geographies.all() # type: ignore
134+
if not queryset.exists():
135+
return []
136+
return TypeGeo.from_django_list(queryset)
137+
except Exception:
138+
return []
139+
116140
@strawberry.field(description="Get tags associated with this use case.")
117141
def tags(self) -> Optional[List["TypeTag"]]:
118142
"""Get tags associated with this use case."""

api/views/search_dataset.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class DatasetDocumentSerializer(serializers.ModelSerializer):
6464
sectors = serializers.ListField()
6565
formats = serializers.ListField()
6666
catalogs = serializers.ListField()
67+
geographies = serializers.ListField()
6768
has_charts = serializers.BooleanField()
6869
slug = serializers.CharField()
6970
download_count = serializers.IntegerField()
@@ -97,6 +98,7 @@ class Meta:
9798
"sectors",
9899
"formats",
99100
"catalogs",
101+
"geographies",
100102
"has_charts",
101103
"download_count",
102104
"trending_score",
@@ -145,6 +147,7 @@ def get_searchable_and_aggregations(self) -> Tuple[List[str], Dict[str, str]]:
145147
"sectors.raw": "terms",
146148
"formats.raw": "terms",
147149
"catalogs.raw": "terms",
150+
"geographies.raw": "terms",
148151
}
149152
for metadata in enabled_metadata: # type: Metadata
150153
if metadata.filterable:
@@ -253,7 +256,7 @@ def add_filters(self, filters: Dict[str, str], search: Search) -> Search:
253256
for filter in filters:
254257
if filter in excluded_labels:
255258
continue
256-
elif filter in ["tags", "sectors", "formats", "catalogs"]:
259+
elif filter in ["tags", "sectors", "formats", "catalogs", "geographies"]:
257260
raw_filter = filter + ".raw"
258261
if raw_filter in self.aggregations:
259262
filter_values = filters[filter].split(",")

api/views/search_usecase.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class UseCaseDocumentSerializer(serializers.ModelSerializer):
6363
tags = serializers.ListField()
6464
logo = serializers.CharField()
6565
sectors = serializers.ListField(default=[])
66+
geographies = serializers.ListField(default=[])
6667
slug = serializers.CharField()
6768
is_individual_usecase = serializers.BooleanField()
6869
running_status = serializers.CharField()
@@ -117,6 +118,7 @@ class Meta:
117118
"tags",
118119
"logo",
119120
"sectors",
121+
"geographies",
120122
"is_individual_usecase",
121123
"organization",
122124
"user",
@@ -169,6 +171,7 @@ def get_searchable_and_aggregations(self) -> Tuple[List[str], Dict[str, str]]:
169171
aggregations: Dict[str, str] = {
170172
"tags.raw": "terms",
171173
"sectors.raw": "terms",
174+
"geographies.raw": "terms",
172175
"status": "terms",
173176
"running_status": "terms",
174177
}
@@ -304,7 +307,7 @@ def add_filters(self, filters: Dict[str, str], search: Search) -> Search:
304307
for filter in filters:
305308
if filter in excluded_labels:
306309
continue
307-
elif filter in ["tags", "sectors"]:
310+
elif filter in ["tags", "sectors", "geographies"]:
308311
raw_filter = filter + ".raw"
309312
if raw_filter in self.aggregations:
310313
filter_values = filters[filter].split(",")

search/documents/dataset_document.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Catalog,
77
Dataset,
88
DatasetMetadata,
9+
Geography,
910
Metadata,
1011
Organization,
1112
Resource,
@@ -114,6 +115,16 @@ class DatasetDocument(Document):
114115
multi=True,
115116
)
116117

118+
geographies = fields.TextField(
119+
attr="geographies_indexing",
120+
analyzer=ngram_analyser,
121+
fields={
122+
"raw": fields.KeywordField(multi=True),
123+
"suggest": fields.CompletionField(multi=True),
124+
},
125+
multi=True,
126+
)
127+
117128
is_individual_dataset = fields.BooleanField(attr="is_individual_dataset")
118129

119130
has_charts = fields.BooleanField(attr="has_charts")
@@ -185,7 +196,14 @@ def get_queryset(self) -> Any:
185196
def get_instances_from_related(
186197
self,
187198
related_instance: Union[
188-
Resource, Metadata, DatasetMetadata, Sector, Organization, User, Catalog
199+
Resource,
200+
Metadata,
201+
DatasetMetadata,
202+
Sector,
203+
Organization,
204+
User,
205+
Catalog,
206+
Geography,
189207
],
190208
) -> Optional[Union[Dataset, List[Dataset]]]:
191209
"""Get Dataset instances from related models."""
@@ -204,6 +222,8 @@ def get_instances_from_related(
204222
return list(related_instance.datasets.all())
205223
elif isinstance(related_instance, Catalog):
206224
return list(related_instance.datasets.all())
225+
elif isinstance(related_instance, Geography):
226+
return list(related_instance.datasets.all())
207227
return None
208228

209229
class Django:
@@ -225,4 +245,5 @@ class Django:
225245
Organization,
226246
User,
227247
Catalog,
248+
Geography,
228249
]

0 commit comments

Comments
 (0)