diff --git a/api/src/org/labkey/api/assay/AbstractAssayTsvDataHandler.java b/api/src/org/labkey/api/assay/AbstractAssayTsvDataHandler.java index f8f3f3b2158..421183f59d7 100644 --- a/api/src/org/labkey/api/assay/AbstractAssayTsvDataHandler.java +++ b/api/src/org/labkey/api/assay/AbstractAssayTsvDataHandler.java @@ -121,6 +121,7 @@ import java.util.Objects; import java.util.Set; import java.util.function.Function; +import java.util.stream.Collectors; import static java.util.stream.Collectors.toList; import static org.labkey.api.assay.AssayRunUploadContext.ReImportOption.MERGE_DATA; @@ -1084,13 +1085,27 @@ else if (validatorMap.containsKey(pd)) if (plateId != null && wellLocation != null) { - Map wellSampleCache = plateWellCache.computeIfAbsent(plateId, (id) -> AssayPlateMetadataService.get().getWellLocationToSampleIdMap(container, user, plateId)); + boolean loadMaterialsCache = !plateWellCache.containsKey(plateId); + Map wellSampleCache = plateWellCache.computeIfAbsent(plateId, (id) -> AssayPlateMetadataService.get().getWellLocationToSampleIdMap(plateId)); + + // If we had to load the wellSampleCache we should also preload the ExpMaterials into the + // materialCache, so we don't need to fetch them with individual queries. This has a large + // impact on performance. + if (loadMaterialsCache) + { + Set samplesToFetch = wellSampleCache.values().stream() + .filter(id -> !materialCache.containsKey(id)) + .collect(Collectors.toSet()); + + for (ExpMaterial m : exp.getExpMaterials(samplesToFetch)) + materialCache.put(m.getRowId(), m); + } sampleId = wellSampleCache.get(wellLocation); } if (sampleId != null) { - material = materialCache.computeIfAbsent(sampleId, (id) -> exp.getExpMaterial(id, containerFilter)); + material = materialCache.get(sampleId); } if (material != null) diff --git a/api/src/org/labkey/api/assay/plate/AssayPlateMetadataService.java b/api/src/org/labkey/api/assay/plate/AssayPlateMetadataService.java index 1f35bd5c560..f4b60adb492 100644 --- a/api/src/org/labkey/api/assay/plate/AssayPlateMetadataService.java +++ b/api/src/org/labkey/api/assay/plate/AssayPlateMetadataService.java @@ -187,7 +187,7 @@ void applyHitSelectionCriteria( /** * Returns a Map of Well Location to Sample RowID for a given Plate ID. */ - Map getWellLocationToSampleIdMap(Container container, User user, Long plateId); + Map getWellLocationToSampleIdMap(Long plateId); boolean isWellLookup(ColumnInfo col); diff --git a/assay/src/org/labkey/assay/plate/AssayPlateMetadataServiceImpl.java b/assay/src/org/labkey/assay/plate/AssayPlateMetadataServiceImpl.java index 66f37dc79ca..0f6091a0f74 100644 --- a/assay/src/org/labkey/assay/plate/AssayPlateMetadataServiceImpl.java +++ b/assay/src/org/labkey/assay/plate/AssayPlateMetadataServiceImpl.java @@ -1518,14 +1518,23 @@ public String format(FieldKey fieldKey) return new PlateSchema(querySchema, contextualRoles); } + record WellSampleData(Long sampleId, Integer row, Integer col) {} + @Override - public Map getWellLocationToSampleIdMap(Container container, User user, Long plateId) + public Map getWellLocationToSampleIdMap(Long plateId) { + // Note: this method intentionally does not use PlateManager.get().getWellData, by selecting only the columns + // we need there is a small but measurable performance boost when importing plate assay data + SimpleFilter filter = new SimpleFilter(WellTable.Column.PlateId.fieldKey(), plateId); + Set columns = Set.of(WellTable.Column.SampleID.name(), WellTable.Column.Row.name(), WellTable.Column.Col.name()); + List wells = new TableSelector(AssayDbSchema.getInstance().getTableInfoWell(), columns, filter, null).getArrayList(WellSampleData.class); Map wellLocationToSampleIdMap = new HashMap<>(); - List wellData = PlateManager.get().getWellData(container, user, plateId, true, false); - for (WellData data : wellData) - wellLocationToSampleIdMap.put(data.getPosition(), data.getSampleId()); + for (WellSampleData well : wells) + { + PositionImpl pos = new PositionImpl(null, well.row, well.col); + wellLocationToSampleIdMap.put(pos.getDescription(), well.sampleId); + } return wellLocationToSampleIdMap; }