Skip to content

Commit

Permalink
[ALS-6724] Nested facets
Browse files Browse the repository at this point in the history
- Nested queries, just 1 level deep for now
- Update details endpoint
- Tests!
- Deleted unused equals fn
  • Loading branch information
Luke Sikina committed Sep 6, 2024
1 parent a43a77d commit f7565e7
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,7 @@ public class ConceptResultSetExtractor implements ResultSetExtractor<Concept> {
@Autowired
private ConceptResultSetUtil conceptResultSetUtil;

private record ConceptWithId(Concept c, int id) {
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
ConceptWithId conceptWithId = (ConceptWithId) object;
return id == conceptWithId.id;
}

@Override
public int hashCode() {
return Objects.hashCode(id);
}
};
private record ConceptWithId(Concept c, int id) {};

@Override
public Concept extractData(ResultSet rs) throws SQLException, DataAccessException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ public Facet(Facet core, Map<String, String> meta) {
public Facet(String name, String category) {
this(name, "", "", "", null, null, category, null);
}

public Facet withChildren(List<Facet> children) {
return new Facet(this.name, this.display, this.description, this.fullName, this.count, children, this.category, this.meta);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.util.StringUtils;

import java.sql.ResultSet;
import java.sql.SQLException;
Expand All @@ -10,26 +11,44 @@

public class FacetCategoryExtractor implements ResultSetExtractor<List<FacetCategory>> {

private record Pair(String parent, String category) {
Pair(Facet facet) {
this(facet.name(), facet.category());
}
};

@Override
public List<FacetCategory> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<Facet> facets = new ArrayList<>();
Map<String, FacetCategory> categories = new HashMap<>();
Map<Pair, List<Facet>> childrenForParent = new HashMap<>();

while (rs.next()) {
// build out all the facets and make shells of the facet categories
String category = rs.getString("category_name");
Facet facet = new Facet(
rs.getString("name"), rs.getString("display"),
rs.getString("description"), rs.getString("full_name"), rs.getInt("facet_count"),
null, category, null
List.of(), category, null
);
FacetCategory facetCategory = new FacetCategory(
category, rs.getString("category_display"),
rs.getString("category_description"), List.of()
);
facets.add(facet);
String parentName = rs.getString("parent_name");
if (StringUtils.hasLength(parentName)) {
Pair key = new Pair(parentName, category);
List<Facet> facetsForParent = childrenForParent.getOrDefault(key, new ArrayList<>());
facetsForParent.add(facet);
childrenForParent.put(key, facetsForParent);
} else {
facets.add(facet);
}
categories.put(category, facetCategory);
}
facets = facets.stream()
.map(f -> f.withChildren(childrenForParent.getOrDefault(new Pair(f), List.of())))
.toList();
// group facets by category, then add them to their respective category
Map<String, List<Facet>> grouped = facets.stream().collect(Collectors.groupingBy(Facet::category));
return categories.entrySet().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public Facet mapRow(ResultSet rs, int rowNum) throws SQLException {
rs.getString("description"),
rs.getString("full_name"),
null,
null,
List.of(),
rs.getString("category"),
null
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,29 @@ public Optional<Facet> getFacet(String facetCategory, String facet) {
MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("facetCategory", facetCategory)
.addValue("facetName", facet);
return template.query(sql, params, mapper).stream().findFirst();
return template.query(sql, params, mapper).stream().findFirst()
.map(f -> f.withChildren(getFacetChildren(f.category(), f.name())));
}

private List<Facet> getFacetChildren(String facetCategory, String parentFacetName) {
String sql = """
SELECT
facet_category.name AS category,
facet.name, facet.display, facet.description,
facet_meta_full_name.value AS full_name
FROM
facet
LEFT JOIN facet as parent_facet ON facet.parent_id = parent_facet.facet_id
LEFT JOIN facet_category ON facet_category.facet_category_id = facet.facet_category_id
LEFT JOIN facet_meta AS facet_meta_full_name ON facet.facet_id = facet_meta_full_name.facet_id AND facet_meta_full_name.KEY = 'full_name'
WHERE
parent_facet.name = :facetName
AND facet_category.name = :facetCategory
""";
MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("facetCategory", facetCategory)
.addValue("facetName", parentFacetName);
return template.query(sql, params, mapper);
}

public Map<String, String> getFacetMeta(String facetCategory, String facet) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,63 +44,56 @@ static void mySQLProperties(DynamicPropertyRegistry registry) {
@Test
void shouldGetAllFacets() {
Filter filter = new Filter(List.of(), "", List.of());

List<FacetCategory> actual = subject.getFacets(filter);

Assertions.assertEquals(2, actual.size());
}

@Test
void shouldFilterFacetsBySearch() {
Filter filter = new Filter(List.of(), "X", List.of());
List<FacetCategory> actual = subject.getFacets(filter);

List<FacetCategory> expected = List.of(
new FacetCategory(
"site", "Site", "Filter variables by site",
new FacetCategory("study_ids_dataset_ids", "Study IDs/Dataset IDs", "",
List.of(
new Facet("bch", "BCH", "Boston Childrens Hospital", "Boston Childrens Hospital", 1, null, "category", null)
new Facet("1", "GIC", null, null, 13, List.of(), "study_ids_dataset_ids", null),
new Facet("phs000284", "CFS", null, "Chronic Fatigue Syndrome", 3, List.of(), "study_ids_dataset_ids", null),
new Facet("phs000007", "FHS", null, "Framingham Heart Study", 3, List.of(), "study_ids_dataset_ids", null),
new Facet("phs002385", "HCT_for_SCD", null, null, 3, List.of(), "study_ids_dataset_ids", null),
new Facet("phs002808", "nuMoM2b", null, null, 3, List.of(), "study_ids_dataset_ids", null),
new Facet("2", "National Health and Nutrition Examination Survey", null, null, 2, List.of(), "study_ids_dataset_ids", null),
new Facet("phs002715", "NSRR CFS", null, "National Sleep Research Resource", 2, List.of(), "study_ids_dataset_ids", null),
new Facet("3", "1000 Genomes Project", null, null, 0, List.of(), "study_ids_dataset_ids", null),
new Facet("phs003463", "RECOVER_Adult", null, null, 0, List.of(), "study_ids_dataset_ids", null),
new Facet("phs003543", "NSRR_HSHC", null, null, 0, List.of(), "study_ids_dataset_ids", null),
new Facet("phs003566", "SPRINT", null, null, 0, List.of(), "study_ids_dataset_ids", null),
new Facet("phs001963", "DEMENTIA-SEQ", null, null, 0, List.of(
new Facet("NEST_1", "My Nested Facet 1", null, null, 0, List.of(), "study_ids_dataset_ids", null),
new Facet("NEST_2", "My Nested Facet 2", null, null, 0, List.of(), "study_ids_dataset_ids", null)
), "study_ids_dataset_ids", null)
)
),
new FacetCategory(
"data_source", "Data Source", "What does this data relate to (image, questionnaire...)",
new FacetCategory("nsrr_harmonized", "Common Data Element Collection", "",
List.of(
new Facet("imaging", "Imaging", "Data derived from an image", "Data derived from an image", 1, null, "data_source", null),
new Facet("questionnaire", "questionnaire", "Data derived from a questionnaire", "Data derived from a questionnaire", 1, null, "data_source", null),
new Facet("lab_test", "Lab Test", "Data derived from a lab test", "Data derived from a lab test", 1, null, "data_source", null)
new Facet("LOINC", "LOINC", null, null, 1, List.of(), "nsrr_harmonized", null),
new Facet("PhenX", "PhenX", null, null, 1, List.of(), "nsrr_harmonized", null),
new Facet("gad_7", "Generalized Anxiety Disorder Assessment (GAD-7)", null, null, 0, List.of(), "nsrr_harmonized", null),
new Facet("taps_tool", "NIDA CTN Common Data Elements = TAPS Tool", null, null, 0, List.of(), "nsrr_harmonized", null)
)
)
);

Assertions.assertEquals(expected, actual);
}

@Test
void shouldFilterFacetsByFacet() {
Filter filter = new Filter(List.of(new Facet("bch", "BCH", "Boston Childrens Hospital", "Boston Childrens Hospital", 1, null, "category", null)), "", List.of());
List<FacetCategory> actual = subject.getFacets(filter);

List<FacetCategory> expected = List.of(
new FacetCategory(
"site", "Site", "Filter variables by site",
List.of(
new Facet("bch", "BCH", "Boston Childrens Hospital", "Boston Childrens Hospital", 1, null, "category", null),
new Facet("narnia", "Narnia", "Narnia", "Narnia", 1, null, "category", null)
)
),
new FacetCategory(
"data_source", "Data Source", "What does this data relate to (image, questionnaire...)",
List.of(
new Facet("imaging", "Imaging", "Data derived from an image", "Data derived from an image", 1, null, "data_source", null),
new Facet("questionnaire", "questionnaire", "Data derived from a questionnaire", "Data derived from a questionnaire", 1, null, "data_source", null),
new Facet("lab_test", "Lab Test", "Data derived from a lab test", "Data derived from a lab test", 1, null, "data_source", null)
)
)
);
void shouldGetFacetWithChildren() {
Optional<Facet> actual = subject.getFacet("study_ids_dataset_ids", "phs001963");
Facet expected = new Facet("phs001963", "DEMENTIA-SEQ", null, null, null, List.of(
new Facet("NEST_1", "My Nested Facet 1", null, null, null, List.of(), "study_ids_dataset_ids", null),
new Facet("NEST_2", "My Nested Facet 2", null, null, null, List.of(), "study_ids_dataset_ids", null)
), "study_ids_dataset_ids", null);

Assertions.assertTrue(actual.isPresent());
Assertions.assertEquals(expected, actual.get());
}

@Test
void shouldGetFacet() {
Optional<Facet> actual = subject.getFacet("study_ids_dataset_ids", "phs000007");
Optional<Facet> expected = Optional.of(new Facet("phs000007", "FHS", null, "Framingham Heart Study", null, null, "study_ids_dataset_ids", null));
Optional<Facet> expected = Optional.of(new Facet("phs000007", "FHS", null, "Framingham Heart Study", null, List.of(), "study_ids_dataset_ids", null));

Assertions.assertEquals(expected, actual);
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/resources/seed.sql
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,8 @@ COPY public.facet (facet_id, facet_category_id, name, display, description, pare
31 1 phs002808 nuMoM2b \N \N
32 1 phs003566 SPRINT \N \N
33 1 phs001963 DEMENTIA-SEQ \N \N
55 1 NEST_1 My Nested Facet 1 \N 33
56 1 NEST_2 My Nested Facet 2 \N 33
19 2 gad_7 Generalized Anxiety Disorder Assessment (GAD-7) \N \N
18 2 taps_tool NIDA CTN Common Data Elements = TAPS Tool \N \N
\.
Expand Down

0 comments on commit f7565e7

Please sign in to comment.