diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/auth/authorization/CatalogAuthorizationManager.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/auth/authorization/CatalogAuthorizationManager.java index 7022be4a0e..d4ae0d690c 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/auth/authorization/CatalogAuthorizationManager.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/auth/authorization/CatalogAuthorizationManager.java @@ -239,8 +239,8 @@ public void checkCanAssignOrSeePermissions(String organizationId, long studyId, @Override public void checkCanCreateUpdateDeleteVariableSets(String organizationId, long studyId, String userId) throws CatalogException { - if (!isAtLeastOrganizationOwnerOrAdmin(organizationId, userId)) { - throw CatalogAuthorizationException.notOrganizationOwnerOrAdmin("create, update or delete variable sets."); + if (!isAtLeastStudyAdministrator(organizationId, studyId, userId)) { + throw CatalogAuthorizationException.notStudyAdmin("create, update or delete variable sets."); } } diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/AnnotationMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/AnnotationMongoDBAdaptor.java index 02ce564972..ebede7d04f 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/AnnotationMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/AnnotationMongoDBAdaptor.java @@ -70,11 +70,23 @@ public abstract class AnnotationMongoDBAdaptor extends CatalogMongoDBAdaptor protected abstract MongoDBCollection getCollection(); - abstract OpenCGAResult transactionalUpdate(ClientSession clientSession, T entry, ObjectMap parameters, + OpenCGAResult transactionalUpdate(ClientSession clientSession, T entry, ObjectMap parameters, List variableSetList, QueryOptions queryOptions) + throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { + return transactionalUpdate(clientSession, entry, parameters, variableSetList, queryOptions, true); + } + + abstract OpenCGAResult transactionalUpdate(ClientSession clientSession, T entry, ObjectMap parameters, + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException; - abstract OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) + OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) + throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { + return transactionalUpdate(clientSession, studyUid, query, updateDocument, true); + } + + abstract OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument, + boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException; public enum AnnotationSetParams implements QueryParam { diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/ClinicalAnalysisMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/ClinicalAnalysisMongoDBAdaptor.java index 7a359e5a7e..1e24abeead 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/ClinicalAnalysisMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/ClinicalAnalysisMongoDBAdaptor.java @@ -355,20 +355,21 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, ClinicalAnalysis @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, ClinicalAnalysis entry, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, + boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { throw new NotImplementedException("Please call to the other transactionalUpdate method passing the ClinicalAudit list"); } @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, - UpdateDocument updateDocument) + UpdateDocument updateDocument, boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); Document updateOperation = updateDocument.toFinalUpdateDocument(); if (!updateOperation.isEmpty()) { - return versionedMongoDBAdaptor.update(clientSession, query, entryList -> { + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateClinicalReferences = (clinicalList) -> { logger.debug("Update clinical analysis. Query: {}, Update: {}", query.toBsonDocument(), updateDocument); DataResult update = clinicalCollection.update(clientSession, query, updateOperation, null); @@ -385,7 +386,12 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, logger.debug("{} clinical analyses successfully updated", update.getNumUpdated()); return endWrite(tmpStartTime, update.getNumMatches(), update.getNumUpdated(), Collections.emptyList()); - }, null, null); + }; + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, query, null, updateClinicalReferences, null, null); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, query, null, updateClinicalReferences); + } } else { throw new CatalogDBException("Nothing to update"); } diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/CohortMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/CohortMongoDBAdaptor.java index 6b948a722b..0ca4d2477e 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/CohortMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/CohortMongoDBAdaptor.java @@ -286,7 +286,7 @@ public OpenCGAResult update(Query query, ObjectMap parameters, List @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, Cohort cohort, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { long tmpStartTime = startQuery(); Query tmpQuery = new Query() @@ -341,7 +341,8 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, Cohort co } @Override - OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) + OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument, + boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FamilyMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FamilyMongoDBAdaptor.java index 97bfd92a67..5ee3d65675 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FamilyMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FamilyMongoDBAdaptor.java @@ -378,7 +378,7 @@ public OpenCGAResult update(Query query, ObjectMap parameters, List @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, Family family, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { long tmpStartTime = startQuery(); long studyUid = family.getStudyUid(); @@ -397,145 +397,161 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, Family fa QueryParams.STUDY_UID.key(), QueryParams.MEMBERS.key() + "." + IndividualDBAdaptor.QueryParams.ID.key()); Bson bsonQuery = parseQuery(tmpQuery); - return versionedMongoDBAdaptor.update(clientSession, bsonQuery, fieldsToInclude, (entrylist) -> { - String familyId = entrylist.get(0).getString(QueryParams.ID.key()); - DataResult result = updateAnnotationSets(clientSession, studyUid, familyUid, parameters, - variableSetList, queryOptions, true); - List familyMemberIds = family.getMembers().stream().map(Individual::getId).collect(Collectors.toList()); - boolean updateRoles = queryOptions.getBoolean(ParamConstants.FAMILY_UPDATE_ROLES_PARAM); - boolean updatePedigree = queryOptions.getBoolean(ParamConstants.FAMILY_UPDATE_PEDIGREEE_GRAPH_PARAM); - if (CollectionUtils.isNotEmpty(parameters.getAsList(QueryParams.MEMBERS.key()))) { - List newIndividuals = parameters.getAsList(QueryParams.MEMBERS.key(), Map.class); - Set newIndividualIds = newIndividuals.stream().map(i -> (String) i.get(IndividualDBAdaptor.QueryParams.ID - .key())).collect(Collectors.toSet()); - - Set currentIndividualIds = family.getMembers().stream().map(Individual::getId).collect(Collectors.toSet()); - - // Obtain new members to be added to the family - List missingIndividualIds = new ArrayList<>(); - for (String newIndividualId : newIndividualIds) { - if (!currentIndividualIds.contains(newIndividualId)) { - missingIndividualIds.add(newIndividualId); - } - } - - // Obtain members to remove from family - List oldIndividualIds = new ArrayList<>(); - for (String currentIndividualId : currentIndividualIds) { - if (!newIndividualIds.contains(currentIndividualId)) { - oldIndividualIds.add(currentIndividualId); - } - } - updateFamilyReferenceInIndividuals(clientSession, family, missingIndividualIds, oldIndividualIds); - updateRoles = true; - familyMemberIds = new ArrayList<>(newIndividualIds); + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateFamilyReferences = (familyList) -> { + String familyId = familyList.get(0).getString(QueryParams.ID.key()); + DataResult result = updateAnnotationSets(clientSession, studyUid, familyUid, parameters, + variableSetList, queryOptions, true); + List familyMemberIds = family.getMembers().stream().map(Individual::getId).collect(Collectors.toList()); + boolean updateRoles = queryOptions.getBoolean(ParamConstants.FAMILY_UPDATE_ROLES_PARAM); + boolean updatePedigree = queryOptions.getBoolean(ParamConstants.FAMILY_UPDATE_PEDIGREEE_GRAPH_PARAM); + if (CollectionUtils.isNotEmpty(parameters.getAsList(QueryParams.MEMBERS.key()))) { + List newIndividuals = parameters.getAsList(QueryParams.MEMBERS.key(), Map.class); + Set newIndividualIds = newIndividuals.stream().map(i -> (String) i.get(IndividualDBAdaptor.QueryParams.ID + .key())).collect(Collectors.toSet()); + + Set currentIndividualIds = family.getMembers().stream().map(Individual::getId).collect(Collectors.toSet()); + + // Obtain new members to be added to the family + List missingIndividualIds = new ArrayList<>(); + for (String newIndividualId : newIndividualIds) { + if (!currentIndividualIds.contains(newIndividualId)) { + missingIndividualIds.add(newIndividualId); } + } - if (updateRoles) { - // CALCULATE ROLES - if (!familyMemberIds.isEmpty()) { - // Fetch individuals with relevant information to guess the relationship - Query individualQuery = new Query() - .append(IndividualDBAdaptor.QueryParams.STUDY_UID.key(), studyUid) - .append(IndividualDBAdaptor.QueryParams.ID.key(), familyMemberIds); - QueryOptions relationshipOptions = dbAdaptorFactory.getCatalogIndividualDBAdaptor().fixOptionsForRelatives( - null); - OpenCGAResult memberResult = dbAdaptorFactory.getCatalogIndividualDBAdaptor().get(clientSession, - individualQuery, relationshipOptions); - family.setMembers(memberResult.getResults()); - Map> roles = calculateRoles(clientSession, studyUid, family); - parameters.put(QueryParams.ROLES.key(), roles); - } else { - parameters.put(QueryParams.ROLES.key(), Collections.emptyMap()); - } + // Obtain members to remove from family + List oldIndividualIds = new ArrayList<>(); + for (String currentIndividualId : currentIndividualIds) { + if (!newIndividualIds.contains(currentIndividualId)) { + oldIndividualIds.add(currentIndividualId); } + } - if (updatePedigree && !updateRoles && !parameters.containsKey(QueryParams.DISORDERS.key())) { - PedigreeGraph pedigreeGraph = computePedigreeGraph(clientSession, family); - parameters.put(QueryParams.PEDIGREE_GRAPH.key(), pedigreeGraph); - } + updateFamilyReferenceInIndividuals(clientSession, family, missingIndividualIds, oldIndividualIds); + updateRoles = true; + familyMemberIds = new ArrayList<>(newIndividualIds); + } - Document familyUpdate = parseAndValidateUpdateParams(clientSession, parameters, tmpQuery).toFinalUpdateDocument(); + if (updateRoles) { + // CALCULATE ROLES + if (!familyMemberIds.isEmpty()) { + // Fetch individuals with relevant information to guess the relationship + Query individualQuery = new Query() + .append(IndividualDBAdaptor.QueryParams.STUDY_UID.key(), studyUid) + .append(IndividualDBAdaptor.QueryParams.ID.key(), familyMemberIds); + QueryOptions relationshipOptions = dbAdaptorFactory.getCatalogIndividualDBAdaptor().fixOptionsForRelatives( + null); + OpenCGAResult memberResult = dbAdaptorFactory.getCatalogIndividualDBAdaptor().get(clientSession, + individualQuery, relationshipOptions); + family.setMembers(memberResult.getResults()); + Map> roles = calculateRoles(clientSession, studyUid, family); + parameters.put(QueryParams.ROLES.key(), roles); + } else { + parameters.put(QueryParams.ROLES.key(), Collections.emptyMap()); + } + } - if (familyUpdate.isEmpty() && result.getNumUpdated() == 0) { - if (!parameters.isEmpty()) { - logger.error("Non-processed update parameters: {}", parameters.keySet()); - } - throw new CatalogDBException("Nothing to be updated"); - } + if (updatePedigree && !updateRoles && !parameters.containsKey(QueryParams.DISORDERS.key())) { + PedigreeGraph pedigreeGraph = computePedigreeGraph(clientSession, family); + parameters.put(QueryParams.PEDIGREE_GRAPH.key(), pedigreeGraph); + } + + Document familyUpdate = parseAndValidateUpdateParams(clientSession, parameters, tmpQuery).toFinalUpdateDocument(); + + if (familyUpdate.isEmpty() && result.getNumUpdated() == 0) { + if (!parameters.isEmpty()) { + logger.error("Non-processed update parameters: {}", parameters.keySet()); + } + throw new CatalogDBException("Nothing to be updated"); + } - List events = new ArrayList<>(); - if (!familyUpdate.isEmpty()) { - Bson finalQuery = parseQuery(tmpQuery); + List events = new ArrayList<>(); + if (!familyUpdate.isEmpty()) { + Bson finalQuery = parseQuery(tmpQuery); - logger.debug("Family update: query : {}, update: {}", finalQuery.toBsonDocument(), familyUpdate.toBsonDocument()); - result = familyCollection.update(clientSession, finalQuery, familyUpdate, new QueryOptions("multi", true)); + logger.debug("Family update: query : {}, update: {}", finalQuery.toBsonDocument(), familyUpdate.toBsonDocument()); + result = familyCollection.update(clientSession, finalQuery, familyUpdate, new QueryOptions("multi", true)); - // Compute pedigree graph - if (updateRoles || parameters.containsKey(QueryParams.DISORDERS.key())) { - PedigreeGraph pedigreeGraph = computePedigreeGraph(clientSession, family); - Document pedigreeGraphDoc = getMongoDBDocument(pedigreeGraph, "PedigreeGraph"); + // Compute pedigree graph + if (updateRoles || parameters.containsKey(QueryParams.DISORDERS.key())) { + PedigreeGraph pedigreeGraph = computePedigreeGraph(clientSession, family); + Document pedigreeGraphDoc = getMongoDBDocument(pedigreeGraph, "PedigreeGraph"); - UpdateDocument updateDocument = new UpdateDocument() - .setSet(new Document(QueryParams.PEDIGREE_GRAPH.key(), pedigreeGraphDoc)); - familyUpdate = updateDocument.toFinalUpdateDocument(); - familyCollection.update(clientSession, finalQuery, familyUpdate, new QueryOptions("multi", true)); - } + UpdateDocument updateDocument = new UpdateDocument() + .setSet(new Document(QueryParams.PEDIGREE_GRAPH.key(), pedigreeGraphDoc)); + familyUpdate = updateDocument.toFinalUpdateDocument(); + familyCollection.update(clientSession, finalQuery, familyUpdate, new QueryOptions("multi", true)); + } - if (parameters.containsKey(QueryParams.ID.key())) { - String newFamilyId = parameters.getString(QueryParams.ID.key()); - - // Fetch members (we don't trust those from the Family object because they could have been updated previously) - Query query = new Query() - .append(IndividualDBAdaptor.QueryParams.FAMILY_IDS.key(), familyId) - .append(IndividualDBAdaptor.QueryParams.STUDY_UID.key(), studyUid); - OpenCGAResult individualResult = dbAdaptorFactory.getCatalogIndividualDBAdaptor().get(clientSession, - query, IndividualManager.INCLUDE_INDIVIDUAL_IDS); - List memberIds = individualResult.getResults().stream().map(Individual::getId) - .collect(Collectors.toList()); - - // Remove familyId from all members - updateFamilyReferenceInIndividuals(clientSession, family, null, memberIds); - family.setId(newFamilyId); - updateFamilyReferenceInIndividuals(clientSession, family, memberIds, null); - } + if (parameters.containsKey(QueryParams.ID.key())) { + String newFamilyId = parameters.getString(QueryParams.ID.key()); + + // Fetch members (we don't trust those from the Family object because they could have been updated previously) + Query query = new Query() + .append(IndividualDBAdaptor.QueryParams.FAMILY_IDS.key(), familyId) + .append(IndividualDBAdaptor.QueryParams.STUDY_UID.key(), studyUid); + OpenCGAResult individualResult = dbAdaptorFactory.getCatalogIndividualDBAdaptor().get(clientSession, + query, IndividualManager.INCLUDE_INDIVIDUAL_IDS); + List memberIds = individualResult.getResults().stream().map(Individual::getId) + .collect(Collectors.toList()); + + // Remove familyId from all members + updateFamilyReferenceInIndividuals(clientSession, family, null, memberIds); + family.setId(newFamilyId); + updateFamilyReferenceInIndividuals(clientSession, family, memberIds, null); + } - if (result.getNumMatches() == 0) { - throw new CatalogDBException("Family " + familyId + " not found"); - } - if (result.getNumUpdated() == 0) { - events.add(new Event(Event.Type.WARNING, familyId, "Family was already updated")); - } - logger.debug("Family {} successfully updated", familyId); - } + if (result.getNumMatches() == 0) { + throw new CatalogDBException("Family " + familyId + " not found"); + } + if (result.getNumUpdated() == 0) { + events.add(new Event(Event.Type.WARNING, familyId, "Family was already updated")); + } + logger.debug("Family {} successfully updated", familyId); + } + + return endWrite(tmpStartTime, 1, 1, events); + }; - return endWrite(tmpStartTime, 1, 1, events); - }, Arrays.asList(QueryParams.MEMBERS_ID.key(), QueryParams.MEMBERS_SAMPLES_ID.key()), - this::iterator, (DBIterator iterator) -> updateReferencesAfterFamilyVersionIncrement(clientSession, iterator)); + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, bsonQuery, fieldsToInclude, updateFamilyReferences, + Arrays.asList(QueryParams.MEMBERS_ID.key(), QueryParams.MEMBERS_SAMPLES_ID.key()), + this::iterator, (DBIterator iterator) -> updateReferencesAfterFamilyVersionIncrement(clientSession, iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, bsonQuery, fieldsToInclude, updateFamilyReferences); + } } @Override - OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) + OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument, + boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); List fieldsToInclude = Arrays.asList(QueryParams.ID.key(), QueryParams.UID.key(), QueryParams.VERSION.key(), QueryParams.STUDY_UID.key(), QueryParams.MEMBERS.key() + "." + IndividualDBAdaptor.QueryParams.ID.key()); - return versionedMongoDBAdaptor.update(clientSession, query, fieldsToInclude, (entrylist) -> { - Document familyUpdate = updateDocument.toFinalUpdateDocument(); + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateFamilyReferences = (familyList) -> { + Document familyUpdate = updateDocument.toFinalUpdateDocument(); - if (familyUpdate.isEmpty()) { - throw new CatalogDBException("Nothing to be updated"); - } + if (familyUpdate.isEmpty()) { + throw new CatalogDBException("Nothing to be updated"); + } - logger.debug("Family update: query : {}, update: {}", query.toBsonDocument(), familyUpdate.toBsonDocument()); - DataResult result = familyCollection.update(clientSession, query, familyUpdate, - new QueryOptions(MongoDBCollection.MULTI, true)); - logger.debug("{} families successfully updated", result.getNumUpdated()); - return endWrite(tmpStartTime, result.getNumMatches(), result.getNumUpdated(), Collections.emptyList()); - }, Arrays.asList(QueryParams.MEMBERS_ID.key(), QueryParams.MEMBERS_SAMPLES_ID.key()), - this::iterator, (DBIterator iterator) -> updateReferencesAfterFamilyVersionIncrement(clientSession, iterator)); + logger.debug("Family update: query : {}, update: {}", query.toBsonDocument(), familyUpdate.toBsonDocument()); + DataResult result = familyCollection.update(clientSession, query, familyUpdate, + new QueryOptions(MongoDBCollection.MULTI, true)); + logger.debug("{} families successfully updated", result.getNumUpdated()); + return endWrite(tmpStartTime, result.getNumMatches(), result.getNumUpdated(), Collections.emptyList()); + }; + + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, query, fieldsToInclude, updateFamilyReferences, + Arrays.asList(QueryParams.MEMBERS_ID.key(), QueryParams.MEMBERS_SAMPLES_ID.key()), + this::iterator, (DBIterator iterator) -> updateReferencesAfterFamilyVersionIncrement(clientSession, iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, query, fieldsToInclude, updateFamilyReferences); + } } private PedigreeGraph computePedigreeGraph(ClientSession clientSession, Family family) diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FileMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FileMongoDBAdaptor.java index 0f8383a990..7617a49d20 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FileMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/FileMongoDBAdaptor.java @@ -380,7 +380,7 @@ public OpenCGAResult update(Query query, ObjectMap parameters, List @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, File file, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); long studyUid = file.getStudyUid(); @@ -438,8 +438,8 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, File file, } @Override - OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) - throws CatalogDBException { + OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument, + boolean incrementVersion) throws CatalogDBException { long tmpStartTime = startQuery(); Document fileUpdate = updateDocument.toFinalUpdateDocument(); diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/IndividualMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/IndividualMongoDBAdaptor.java index 03a6704af1..c3f65b924a 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/IndividualMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/IndividualMongoDBAdaptor.java @@ -374,7 +374,7 @@ public OpenCGAResult update(Query query, ObjectMap parameters, List @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, Individual individual, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { long tmpStartTime = startQuery(); long studyUid = individual.getStudyUid(); @@ -392,106 +392,123 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, Indiv QueryParams.STUDY_UID.key()); Bson bson = parseQuery(tmpQuery); - return versionedMongoDBAdaptor.update(clientSession, bson, fieldsToInclude, (entryList) -> { - String individualId = entryList.get(0).getString(QueryParams.ID.key()); - DataResult result = updateAnnotationSets(clientSession, studyUid, individualUid, parameters, - variableSetList, queryOptions, true); - UpdateDocument updateDocument = parseAndValidateUpdateParams(clientSession, parameters, tmpQuery, queryOptions); - Document individualUpdate = updateDocument.toFinalUpdateDocument(); + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateIndividualReferences = (individualList) -> { + String individualId = individualList.get(0).getString(QueryParams.ID.key()); + DataResult result = updateAnnotationSets(clientSession, studyUid, individualUid, parameters, + variableSetList, queryOptions, true); + UpdateDocument updateDocument = parseAndValidateUpdateParams(clientSession, parameters, tmpQuery, queryOptions); + Document individualUpdate = updateDocument.toFinalUpdateDocument(); + + if (individualUpdate.isEmpty() && result.getNumUpdated() == 0) { + if (!parameters.isEmpty()) { + logger.error("Non-processed update parameters: {}", parameters.keySet()); + } + throw new CatalogDBException("Nothing to be updated"); + } - if (individualUpdate.isEmpty() && result.getNumUpdated() == 0) { - if (!parameters.isEmpty()) { - logger.error("Non-processed update parameters: {}", parameters.keySet()); - } - throw new CatalogDBException("Nothing to be updated"); - } + List events = new ArrayList<>(); + if (!individualUpdate.isEmpty()) { + Bson finalQuery = parseQuery(tmpQuery); - List events = new ArrayList<>(); - if (!individualUpdate.isEmpty()) { - Bson finalQuery = parseQuery(tmpQuery); + logger.debug("Individual update: query : {}, update: {}", finalQuery.toBsonDocument(), + individualUpdate.toBsonDocument()); - logger.debug("Individual update: query : {}, update: {}", finalQuery.toBsonDocument(), - individualUpdate.toBsonDocument()); + result = individualCollection.update(clientSession, finalQuery, individualUpdate, new QueryOptions("multi", true)); - result = individualCollection.update(clientSession, finalQuery, individualUpdate, new QueryOptions("multi", true)); + if (result.getNumMatches() == 0) { + throw new CatalogDBException("Individual " + individualId + " not found"); + } + if (result.getNumUpdated() == 0) { + events.add(new Event(Event.Type.WARNING, individualId, "Individual was already updated")); + } - if (result.getNumMatches() == 0) { - throw new CatalogDBException("Individual " + individualId + " not found"); - } - if (result.getNumUpdated() == 0) { - events.add(new Event(Event.Type.WARNING, individualId, "Individual was already updated")); - } + if (!updateDocument.getAttributes().isEmpty()) { + List addedSamples = updateDocument.getAttributes().getAsLongList("ADDED_SAMPLES"); + List removedSamples = updateDocument.getAttributes().getAsLongList("REMOVED_SAMPLES"); - if (!updateDocument.getAttributes().isEmpty()) { - List addedSamples = updateDocument.getAttributes().getAsLongList("ADDED_SAMPLES"); - List removedSamples = updateDocument.getAttributes().getAsLongList("REMOVED_SAMPLES"); + // Set new individual reference + dbAdaptorFactory.getCatalogSampleDBAdaptor().updateIndividualFromSampleCollection(clientSession, + studyUid, addedSamples, individualId); - // Set new individual reference - dbAdaptorFactory.getCatalogSampleDBAdaptor().updateIndividualFromSampleCollection(clientSession, - studyUid, addedSamples, individualId); + // Set individual reference to "" + dbAdaptorFactory.getCatalogSampleDBAdaptor().updateIndividualFromSampleCollection(clientSession, + studyUid, removedSamples, ""); + } - // Set individual reference to "" - dbAdaptorFactory.getCatalogSampleDBAdaptor().updateIndividualFromSampleCollection(clientSession, - studyUid, removedSamples, ""); - } + // If the list of disorders or phenotypes is altered, we will need to update the corresponding effective lists + // of the families associated (if any) + if (parameters.containsKey(QueryParams.DISORDERS.key()) || parameters.containsKey(QueryParams.PHENOTYPES.key())) { + recalculateFamilyDisordersPhenotypes(clientSession, studyUid, individualUid); + } - // If the list of disorders or phenotypes is altered, we will need to update the corresponding effective lists - // of the families associated (if any) - if (parameters.containsKey(QueryParams.DISORDERS.key()) || parameters.containsKey(QueryParams.PHENOTYPES.key())) { - recalculateFamilyDisordersPhenotypes(clientSession, studyUid, individualUid); - } + if (StringUtils.isNotEmpty(parameters.getString(QueryParams.ID.key()))) { + // We need to update the individual id reference in all its samples + dbAdaptorFactory.getCatalogSampleDBAdaptor().updateIndividualIdFromSamples(clientSession, studyUid, + individualId, parameters.getString(QueryParams.ID.key())); - if (StringUtils.isNotEmpty(parameters.getString(QueryParams.ID.key()))) { - // We need to update the individual id reference in all its samples - dbAdaptorFactory.getCatalogSampleDBAdaptor().updateIndividualIdFromSamples(clientSession, studyUid, - individualId, parameters.getString(QueryParams.ID.key())); + // Update the family roles + familyDBAdaptor.updateIndividualIdFromFamilies(clientSession, studyUid, individualUid, individualId, + parameters.getString(QueryParams.ID.key())); + } - // Update the family roles - familyDBAdaptor.updateIndividualIdFromFamilies(clientSession, studyUid, individualUid, individualId, - parameters.getString(QueryParams.ID.key())); - } + if (parameters.containsKey(QueryParams.FATHER_UID.key()) || parameters.containsKey(QueryParams.MOTHER_UID.key())) { + // If the parents have changed, we need to check family roles + recalculateFamilyRolesForMember(clientSession, studyUid, individualUid); + } - if (parameters.containsKey(QueryParams.FATHER_UID.key()) || parameters.containsKey(QueryParams.MOTHER_UID.key())) { - // If the parents have changed, we need to check family roles - recalculateFamilyRolesForMember(clientSession, studyUid, individualUid); - } + logger.debug("Individual {} successfully updated", individualId); + } - logger.debug("Individual {} successfully updated", individualId); - } + return endWrite(tmpStartTime, 1, 1, events); + }; - return endWrite(tmpStartTime, 1, 1, events); - }, Collections.singletonList(QueryParams.SAMPLES_IDS.key()), this::iterator, - (DBIterator iterator) -> updateReferencesAfterIndividualVersionIncrement(clientSession, studyUid, iterator)); + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, bson, fieldsToInclude, updateIndividualReferences, + Collections.singletonList(QueryParams.SAMPLES_IDS.key()), this::iterator, + (DBIterator iterator) -> updateReferencesAfterIndividualVersionIncrement(clientSession, studyUid, + iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, bson, fieldsToInclude, updateIndividualReferences); + } } - OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) + OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument, + boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); List fieldsToInclude = Arrays.asList(QueryParams.ID.key(), QueryParams.UID.key(), QueryParams.VERSION.key(), QueryParams.STUDY_UID.key()); - return versionedMongoDBAdaptor.update(clientSession, query, fieldsToInclude, (entryList) -> { - List events = new ArrayList<>(); - Document update = updateDocument.toFinalUpdateDocument(); - if (!update.isEmpty()) { - logger.debug("Individual update: query : {}, update: {}", query.toBsonDocument(), update.toBsonDocument()); - DataResult result = individualCollection.update(clientSession, query, update, - new QueryOptions(MongoDBCollection.MULTI, true)); - List individualIds = entryList.stream().map(x -> x.getString(QueryParams.ID.key())) - .collect(Collectors.toList()); - if (result.getNumUpdated() == 0) { - for (String individualId : individualIds) { - events.add(new Event(Event.Type.WARNING, individualId, "Individual was already updated")); - } - } - - logger.debug("Individual(s) {} successfully updated", StringUtils.join(individualIds, ", ")); - return endWrite(tmpStartTime, result.getNumMatches(), result.getNumUpdated(), events); - } else { - return endWrite(tmpStartTime, entryList.size(), 0, events); + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateIndividualReferences = (individualList) -> { + List events = new ArrayList<>(); + Document update = updateDocument.toFinalUpdateDocument(); + if (!update.isEmpty()) { + logger.debug("Individual update: query : {}, update: {}", query.toBsonDocument(), update.toBsonDocument()); + DataResult result = individualCollection.update(clientSession, query, update, + new QueryOptions(MongoDBCollection.MULTI, true)); + List individualIds = individualList.stream().map(x -> x.getString(QueryParams.ID.key())) + .collect(Collectors.toList()); + if (result.getNumUpdated() == 0) { + for (String individualId : individualIds) { + events.add(new Event(Event.Type.WARNING, individualId, "Individual was already updated")); } - }, Collections.singletonList(QueryParams.SAMPLES_IDS.key()), this::iterator, - (DBIterator iterator) -> updateReferencesAfterIndividualVersionIncrement(clientSession, studyUid, iterator)); + } + + logger.debug("Individual(s) {} successfully updated", StringUtils.join(individualIds, ", ")); + return endWrite(tmpStartTime, result.getNumMatches(), result.getNumUpdated(), events); + } else { + return endWrite(tmpStartTime, individualList.size(), 0, events); + } + }; + + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, query, fieldsToInclude, updateIndividualReferences, + Collections.singletonList(QueryParams.SAMPLES_IDS.key()), this::iterator, + (DBIterator iterator) -> updateReferencesAfterIndividualVersionIncrement(clientSession, studyUid, + iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, query, fieldsToInclude, updateIndividualReferences); + } } // If we know the study uid, we should be calling to the other transactionalUpdate method that receives the entire object instead of diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/SampleMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/SampleMongoDBAdaptor.java index d9058193e7..e4a550090c 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/SampleMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/SampleMongoDBAdaptor.java @@ -62,6 +62,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.stream.Collectors; @@ -262,7 +263,7 @@ public OpenCGAResult update(long uid, ObjectMap parameters, List va try { return runTransaction(clientSession -> privateUpdate(clientSession, documentResult.first(), parameters, variableSetList, - queryOptions)); + queryOptions, true)); } catch (CatalogException e) { logger.error("Could not update sample {}: {}", sampleId, e.getMessage(), e); throw new CatalogDBException("Could not update sample " + sampleId + ": " + e.getMessage(), e.getCause()); @@ -297,7 +298,7 @@ public OpenCGAResult update(Query query, ObjectMap parameters, List String sampleId = sampleDocument.getString(QueryParams.ID.key()); try { result.append(runTransaction(clientSession -> privateUpdate(clientSession, sampleDocument, parameters, variableSetList, - queryOptions))); + queryOptions, true))); } catch (CatalogException e) { logger.error("Could not update sample {}: {}", sampleId, e.getMessage(), e); result.getEvents().add(new Event(Event.Type.ERROR, sampleId, e.getMessage())); @@ -309,7 +310,7 @@ public OpenCGAResult update(Query query, ObjectMap parameters, List } OpenCGAResult privateUpdate(ClientSession clientSession, Document sampleDocument, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { long tmpStartTime = startQuery(); String sampleId = sampleDocument.getString(QueryParams.ID.key()); @@ -321,7 +322,7 @@ OpenCGAResult privateUpdate(ClientSession clientSession, Document sample .append(QueryParams.STUDY_UID.key(), studyUid) .append(QueryParams.UID.key(), sampleUid); Bson bsonQuery = parseQuery(tmpQuery); - return versionedMongoDBAdaptor.update(clientSession, bsonQuery, (entrylist) -> { + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateSampleReferences = (sampleList) -> { // Perform the update DataResult result = updateAnnotationSets(clientSession, studyUid, sampleUid, parameters, variableSetList, queryOptions, true); @@ -372,12 +373,21 @@ OpenCGAResult privateUpdate(ClientSession clientSession, Document sample } return endWrite(tmpStartTime, 1, 1, events); - }, this::iterator, (DBIterator iterator) -> updateReferencesAfterSampleVersionIncrement(clientSession, iterator)); + }; + + List fieldsToInclude = Arrays.asList(QueryParams.ID.key(), QueryParams.UID.key(), QueryParams.VERSION.key(), + QueryParams.STUDY_UID.key(), PRIVATE_INDIVIDUAL_UID); + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, bsonQuery, fieldsToInclude, updateSampleReferences, this::iterator, + (DBIterator iterator) -> updateReferencesAfterSampleVersionIncrement(clientSession, iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, bsonQuery, fieldsToInclude, updateSampleReferences); + } } @Override OpenCGAResult transactionalUpdate(ClientSession clientSession, Sample sample, ObjectMap parameters, - List variableSetList, QueryOptions queryOptions) + List variableSetList, QueryOptions queryOptions, boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); long studyUid = sample.getStudyUid(); @@ -396,8 +406,8 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, Sample sa QueryParams.STUDY_UID.key(), PRIVATE_INDIVIDUAL_UID); Bson bsonQuery = parseQuery(tmpQuery); - return versionedMongoDBAdaptor.update(clientSession, bsonQuery, fieldsToInclude, (entrylist) -> { - String sampleId = entrylist.get(0).getString(QueryParams.ID.key()); + SnapshotVersionedMongoDBAdaptor.FunctionWithException updateSampleReferences = (sampleList) -> { + String sampleId = sampleList.get(0).getString(QueryParams.ID.key()); // Perform the update DataResult result = updateAnnotationSets(clientSession, studyUid, sampleUid, parameters, variableSetList, queryOptions, true); @@ -420,12 +430,12 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, Sample sa result = sampleCollection.update(clientSession, finalQuery, sampleUpdate, new QueryOptions(MongoDBCollection.MULTI, true)); if (updateParams.getSet().containsKey(PRIVATE_INDIVIDUAL_UID)) { - long individualUid = entrylist.get(0).getLong(PRIVATE_INDIVIDUAL_UID); + long individualUid = sampleList.get(0).getLong(PRIVATE_INDIVIDUAL_UID); long newIndividualUid = updateParams.getSet().getLong(PRIVATE_INDIVIDUAL_UID); // If the sample has been associated a different individual if (newIndividualUid != individualUid) { - int version = entrylist.get(0).getInteger(QueryParams.VERSION.key()); + int version = sampleList.get(0).getInteger(QueryParams.VERSION.key()); Sample tmpSample = new Sample() .setUid(sampleUid) .setVersion(version) @@ -455,17 +465,23 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, Sample sa } return endWrite(tmpStartTime, 1, 1, events); - }, this::iterator, (DBIterator iterator) -> updateReferencesAfterSampleVersionIncrement(clientSession, iterator)); + }; + + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, bsonQuery, fieldsToInclude, updateSampleReferences, this::iterator, + (DBIterator iterator) -> updateReferencesAfterSampleVersionIncrement(clientSession, iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, bsonQuery, fieldsToInclude, updateSampleReferences); + } } @Override - OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument) + OpenCGAResult transactionalUpdate(ClientSession clientSession, long studyUid, Bson query, UpdateDocument updateDocument, + boolean incrementVersion) throws CatalogParameterException, CatalogDBException, CatalogAuthorizationException { long tmpStartTime = startQuery(); - List includeIds = Arrays.asList(QueryParams.ID.key(), QueryParams.UID.key(), QueryParams.VERSION.key(), - QueryParams.STUDY_UID.key(), PRIVATE_INDIVIDUAL_UID); - return versionedMongoDBAdaptor.update(clientSession, query, includeIds, (sampleList) -> { + Function, OpenCGAResult> updateSampleReferences = (sampleList) -> { List events = new ArrayList<>(); Document update = updateDocument.toFinalUpdateDocument(); if (!update.isEmpty()) { @@ -481,7 +497,16 @@ OpenCGAResult transactionalUpdate(ClientSession clientSession, long stud logger.debug("Samples {} successfully updated", StringUtils.join(sampleIds, ", ")); } return endWrite(tmpStartTime, sampleList.size(), sampleList.size(), events); - }, this::iterator, (DBIterator iterator) -> updateReferencesAfterSampleVersionIncrement(clientSession, iterator)); + }; + + List includeIds = Arrays.asList(QueryParams.ID.key(), QueryParams.UID.key(), QueryParams.VERSION.key(), + QueryParams.STUDY_UID.key(), PRIVATE_INDIVIDUAL_UID); + if (incrementVersion) { + return versionedMongoDBAdaptor.update(clientSession, query, includeIds, updateSampleReferences::apply, this::iterator, + (DBIterator iterator) -> updateReferencesAfterSampleVersionIncrement(clientSession, iterator)); + } else { + return versionedMongoDBAdaptor.updateWithoutVersionIncrement(clientSession, query, includeIds, updateSampleReferences::apply); + } } private void updateReferencesAfterSampleVersionIncrement(ClientSession clientSession, DBIterator iterator) @@ -528,7 +553,7 @@ void updateCohortReferences(ClientSession clientSession, long studyUid, List iterator(ClientSession session, Query query, QueryOptions options) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException; } + @FunctionalInterface + public interface FunctionWithException { + OpenCGAResult execute(List entryList) + throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException; + } + protected void insert(ClientSession session, Document document) { // Versioning private parameters document.put(VERSION, 1); @@ -149,7 +155,7 @@ protected void insert(ClientSession session, Document document) { archiveCollection.insert(session, document, QueryOptions.empty()); } - protected OpenCGAResult update(ClientSession session, Bson sourceQuery, VersionedModelExecution> update, + protected OpenCGAResult update(ClientSession session, Bson sourceQuery, FunctionWithException update, PostVersionIncrementIterator postVersionIncrementIterator, ReferenceModelExecution postVersionIncrementExecution) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { @@ -158,8 +164,7 @@ protected OpenCGAResult update(ClientSession session, Bson sourceQuery, V } protected OpenCGAResult update(ClientSession session, Bson sourceQuery, List fieldsToInclude, - VersionedModelExecution> update, - PostVersionIncrementIterator postVersionIncrementIterator, + FunctionWithException update, PostVersionIncrementIterator postVersionIncrementIterator, ReferenceModelExecution postVersionIncrementExecution) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { return update(session, sourceQuery, fieldsToInclude, update, Collections.emptyList(), postVersionIncrementIterator, @@ -167,8 +172,7 @@ protected OpenCGAResult update(ClientSession session, Bson sourceQuery, L } protected OpenCGAResult update(ClientSession session, Bson sourceQuery, List fieldsToInclude, - VersionedModelExecution> update, - List postVersionIncrementAdditionalIncludeFields, + FunctionWithException update, List postVersionIncrementAdditionalIncludeFields, PostVersionIncrementIterator dbIterator, ReferenceModelExecution postVersionIncrementExecution) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { @@ -301,6 +305,53 @@ protected OpenCGAResult updateWithoutVersionIncrement(Bson sourceQuery, N return executionResult; } + protected OpenCGAResult updateWithoutVersionIncrement(ClientSession clientSession, Bson sourceQuery, + List fieldsToInclude, FunctionWithException update) + throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { + // Obtain all entries that will be updated + Set includeFields = new HashSet<>(Arrays.asList(PRIVATE_UID, VERSION, RELEASE_FROM_VERSION, PRIVATE_TRANSACTION_ID)); + if (fieldsToInclude != null) { + includeFields.addAll(fieldsToInclude); + } + QueryOptions options = new QueryOptions(QueryOptions.INCLUDE, includeFields); + List entryList = new LinkedList<>(); + List allUids = new LinkedList<>(); + try (MongoDBIterator iterator = collection.iterator(clientSession, sourceQuery, null, null, options)) { + while (iterator.hasNext()) { + Document result = iterator.next(); + entryList.add(result); + + long uid = result.get(PRIVATE_UID, Number.class).longValue(); + allUids.add(uid); + } + } + + // Execute main update + OpenCGAResult executionResult = update.execute(entryList); + + // Fetch document containing update and copy into the archive collection + Bson bsonQuery = Filters.in(PRIVATE_UID, allUids); + options = new QueryOptions(MongoDBCollection.NO_CURSOR_TIMEOUT, true); + QueryOptions upsertOptions = new QueryOptions() + .append(MongoDBCollection.REPLACE, true) + .append(MongoDBCollection.UPSERT, true); + try (MongoDBIterator iterator = collection.iterator(clientSession, bsonQuery, null, null, options)) { + while (iterator.hasNext()) { + Document result = iterator.next(); + result.remove(PRIVATE_MONGO_ID); + + // Insert/replace in archive collection + Bson tmpBsonQuery = Filters.and( + Filters.eq(PRIVATE_UID, result.get(PRIVATE_UID)), + Filters.eq(VERSION, result.get(VERSION)) + ); + archiveCollection.update(clientSession, tmpBsonQuery, result, upsertOptions); + } + } + + return executionResult; + } + /** * Revert to a previous version. *