Skip to content

Commit cd6c358

Browse files
committed
Add metadataTypes endpoint - readonly; available for everyone
1 parent 4b4951a commit cd6c358

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/datasets/datasets.controller.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,29 @@ export class DatasetsController {
888888
return this.datasetsService.metadataKeys(parsedFilters);
889889
}
890890

891+
// GET /datasets/metadataTypes
892+
// @UseGuards(PoliciesGuard)
893+
// @CheckPolicies((ability: AppAbility) =>
894+
// ability.can(Action.DatasetRead, DatasetClass),
895+
// )
896+
@Get("/metadataTypes")
897+
@ApiOperation({
898+
summary: "Retrieve all available scientific metadata field types.",
899+
description:
900+
"This endpoint returns the field names and their corresponding data types from the `scientificMetadata` fields of all datasets in the system. It aggregates all the unique field names and their associated types from the dataset collection.",
901+
})
902+
@ApiResponse({
903+
status: 200,
904+
type: Array,
905+
description:
906+
"Returns an array of objects where each object contains a metadata field name and its associated type.",
907+
})
908+
async metadataTypes(): Promise<any[]> {
909+
const result = this.datasetsService.getScientificMetadataTypes();
910+
911+
return result;
912+
}
913+
891914
// GET /datasets/findOne
892915
@UseGuards(PoliciesGuard)
893916
@CheckPolicies("datasets", (ability: AppAbility) =>

src/datasets/datasets.service.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,43 @@ export class DatasetsService {
476476
}
477477
}
478478

479+
async getScientificMetadataTypes() {
480+
// TODO performance research required, say 1K records, 100K and 1M
481+
return this.datasetModel.aggregate([
482+
{
483+
// Step 1: Convert the scientificMetadata object into an array of key-value pairs
484+
$project: {
485+
scientificMetadataArray: { $objectToArray: "$scientificMetadata" },
486+
},
487+
},
488+
{
489+
// Step 2: Unwind the array to treat each field individually
490+
$unwind: "$scientificMetadataArray",
491+
},
492+
{
493+
// Step 3: Group by the field name and accumulate types
494+
$group: {
495+
_id: "$scientificMetadataArray.k", // Group by field name (key)
496+
types: { $addToSet: { $type: "$scientificMetadataArray.v.value" } }, // Add the data type of the value
497+
},
498+
},
499+
{
500+
// Step 4: Convert the array of types into a string for each field name
501+
$project: {
502+
_id: 0, // Don't include the default _id
503+
metadataKey: "$_id",
504+
metadataType: {
505+
$cond: {
506+
if: { $eq: [{ $size: "$types" }, 1] }, // If only one type is present
507+
then: { $arrayElemAt: ["$types", 0] }, // Use the type
508+
else: "mixed", // If there are multiple types, mark it as 'mixed'
509+
},
510+
},
511+
},
512+
},
513+
]);
514+
}
515+
479516
async isElasticSearchDBEmpty() {
480517
if (!this.ESClient) return;
481518
const count = await this.ESClient.getCount();

0 commit comments

Comments
 (0)