use of org.springframework.data.mongodb.core.query.Query in project spring-data-mongodb by spring-projects.
the class MongoTemplate method doSaveVersioned.
@SuppressWarnings("unchecked")
private <T> T doSaveVersioned(AdaptibleEntity<T> source, String collectionName) {
if (source.isNew()) {
return (T) doInsert(collectionName, source.getBean(), this.mongoConverter);
}
// Create query for entity with the id and old version
Query query = source.getQueryForVersion();
// Bump version number
T toSave = source.incrementVersion();
toSave = maybeEmitEvent(new BeforeConvertEvent<T>(toSave, collectionName)).getSource();
toSave = maybeCallBeforeConvert(toSave, collectionName);
if (source.getBean() != toSave) {
source = operations.forEntity(toSave, mongoConverter.getConversionService());
}
source.assertUpdateableIdIfNotSet();
MappedDocument mapped = source.toMappedDocument(mongoConverter);
maybeEmitEvent(new BeforeSaveEvent<>(toSave, mapped.getDocument(), collectionName));
toSave = maybeCallBeforeSave(toSave, mapped.getDocument(), collectionName);
UpdateDefinition update = mapped.updateWithoutId();
UpdateResult result = doUpdate(collectionName, query, update, toSave.getClass(), false, false);
if (result.getModifiedCount() == 0) {
throw new OptimisticLockingFailureException(String.format("Cannot save entity %s with version %s to collection %s. Has it been modified meanwhile?", source.getId(), source.getVersion(), collectionName));
}
maybeEmitEvent(new AfterSaveEvent<>(toSave, mapped.getDocument(), collectionName));
return maybeCallAfterSave(toSave, mapped.getDocument(), collectionName);
}
use of org.springframework.data.mongodb.core.query.Query in project spring-data-mongodb by spring-projects.
the class ReactiveMongoTemplate method doUpdate.
protected Mono<UpdateResult> doUpdate(String collectionName, Query query, @Nullable UpdateDefinition update, @Nullable Class<?> entityClass, boolean upsert, boolean multi) {
if (query.isSorted() && LOGGER.isWarnEnabled()) {
LOGGER.warn(String.format("%s does not support sort ('%s'). Please use findAndModify() instead.", upsert ? "Upsert" : "UpdateFirst", serializeToJsonSafely(query.getSortObject())));
}
MongoPersistentEntity<?> entity = entityClass == null ? null : getPersistentEntity(entityClass);
UpdateContext updateContext = multi ? queryOperations.updateContext(update, query, upsert) : queryOperations.updateSingleContext(update, query, upsert);
updateContext.increaseVersionForUpdateIfNecessary(entity);
Document queryObj = updateContext.getMappedQuery(entity);
UpdateOptions updateOptions = updateContext.getUpdateOptions(entityClass);
Flux<UpdateResult> result;
if (updateContext.isAggregationUpdate()) {
List<Document> pipeline = updateContext.getUpdatePipeline(entityClass);
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, update.getUpdateObject(), queryObj);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
result = execute(collectionName, collection -> {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s", serializeToJsonSafely(queryObj), serializeToJsonSafely(pipeline), collectionName));
}
collection = writeConcernToUse != null ? collection.withWriteConcern(writeConcernToUse) : collection;
return multi ? collection.updateMany(queryObj, pipeline, updateOptions) : collection.updateOne(queryObj, pipeline, updateOptions);
});
} else {
Document updateObj = updateContext.getMappedUpdate(entity);
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.UPDATE, collectionName, entityClass, updateObj, queryObj);
WriteConcern writeConcernToUse = prepareWriteConcern(mongoAction);
result = execute(collectionName, collection -> {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Calling update using query: %s and update: %s in collection: %s", serializeToJsonSafely(queryObj), serializeToJsonSafely(updateObj), collectionName));
}
MongoCollection<Document> collectionToUse = prepareCollection(collection, writeConcernToUse);
if (!UpdateMapper.isUpdateObject(updateObj)) {
Document filter = new Document(queryObj);
Mono<Document> deferredFilter;
if (updateContext.requiresShardKey(filter, entity)) {
if (entity.getShardKey().isImmutable()) {
deferredFilter = Mono.just(updateContext.applyShardKey(entity, filter, null));
} else {
deferredFilter = Mono.from(collection.find(filter, Document.class).projection(updateContext.getMappedShardKey(entity)).first()).defaultIfEmpty(updateObj).map(it -> updateContext.applyShardKey(entity, filter, it));
}
} else {
deferredFilter = Mono.just(filter);
}
ReplaceOptions replaceOptions = updateContext.getReplaceOptions(entityClass);
return deferredFilter.flatMap(it -> Mono.from(collectionToUse.replaceOne(it, updateObj, replaceOptions)));
}
return multi ? collectionToUse.updateMany(queryObj, updateObj, updateOptions) : collectionToUse.updateOne(queryObj, updateObj, updateOptions);
});
}
result = result.doOnNext(updateResult -> {
if (entity != null && entity.hasVersionProperty() && !multi) {
if (updateResult.wasAcknowledged() && updateResult.getMatchedCount() == 0) {
Document updateObj = updateContext.getMappedUpdate(entity);
if (containsVersionProperty(queryObj, entity))
throw new OptimisticLockingFailureException("Optimistic lock exception on saving entity: " + updateObj.toString() + " to collection " + collectionName);
}
}
});
return result.next();
}
use of org.springframework.data.mongodb.core.query.Query in project spring-data-mongodb by spring-projects.
the class ReactiveMongoTemplate method findDistinct.
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#findDistinct(org.springframework.data.mongodb.core.query.Query, java.lang.String, java.lang.String, java.lang.Class, java.lang.Class)
*/
@SuppressWarnings("unchecked")
public <T> Flux<T> findDistinct(Query query, String field, String collectionName, Class<?> entityClass, Class<T> resultClass) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(field, "Field must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(entityClass, "EntityClass must not be null!");
Assert.notNull(resultClass, "ResultClass must not be null!");
MongoPersistentEntity<?> entity = getPersistentEntity(entityClass);
DistinctQueryContext distinctQueryContext = queryOperations.distinctQueryContext(query, field);
Document mappedQuery = distinctQueryContext.getMappedQuery(entity);
String mappedFieldName = distinctQueryContext.getMappedFieldName(entity);
Class<T> mongoDriverCompatibleType = distinctQueryContext.getDriverCompatibleClass(resultClass);
Flux<?> result = execute(collectionName, collection -> {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Executing findDistinct using query %s for field: %s in collection: %s", serializeToJsonSafely(mappedQuery), field, collectionName));
}
FindPublisherPreparer preparer = new QueryFindPublisherPreparer(query, entityClass);
if (preparer.hasReadPreference()) {
collection = collection.withReadPreference(preparer.getReadPreference());
}
DistinctPublisher<T> publisher = collection.distinct(mappedFieldName, mappedQuery, mongoDriverCompatibleType);
distinctQueryContext.applyCollation(entityClass, publisher::collation);
return publisher;
});
if (resultClass == Object.class || mongoDriverCompatibleType != resultClass) {
Class<?> targetType = distinctQueryContext.getMostSpecificConversionTargetType(resultClass, entityClass);
MongoConverter converter = getConverter();
result = result.map(it -> converter.mapValueToTargetType(it, targetType, NO_OP_REF_RESOLVER));
}
return (Flux<T>) result;
}
use of org.springframework.data.mongodb.core.query.Query in project spring-data-mongodb by spring-projects.
the class AbstractMongoQuery method doExecute.
/**
* Execute the {@link RepositoryQuery} of the given method with the parameters provided by the
* {@link ConvertingParameterAccessor accessor}
*
* @param method the {@link MongoQueryMethod} invoked. Never {@literal null}.
* @param processor {@link ResultProcessor} for post procession. Never {@literal null}.
* @param accessor for providing invocation arguments. Never {@literal null}.
* @param typeToRead the desired component target type. Can be {@literal null}.
*/
protected Object doExecute(MongoQueryMethod method, ResultProcessor processor, ConvertingParameterAccessor accessor, @Nullable Class<?> typeToRead) {
Query query = createQuery(accessor);
applyQueryMetaAttributesWhenPresent(query);
query = applyAnnotatedDefaultSortIfPresent(query);
query = applyAnnotatedCollationIfPresent(query, accessor);
FindWithQuery<?> find = //
typeToRead == null ? //
executableFind : executableFind.as(typeToRead);
return getExecution(accessor, find).execute(query);
}
use of org.springframework.data.mongodb.core.query.Query in project spring-data-mongodb by spring-projects.
the class ReactivePartTreeMongoQuery method createQueryInternal.
private Query createQueryInternal(ConvertingParameterAccessor accessor, boolean isCountQuery) {
MongoQueryCreator creator = new MongoQueryCreator(tree, accessor, context, isCountQuery ? false : isGeoNearQuery);
Query query = creator.createQuery();
if (isCountQuery) {
return query;
}
if (tree.isLimiting()) {
query.limit(tree.getMaxResults());
}
TextCriteria textCriteria = accessor.getFullText();
if (textCriteria != null) {
query.addCriteria(textCriteria);
}
String fieldSpec = getQueryMethod().getFieldSpecification();
if (!StringUtils.hasText(fieldSpec)) {
ReturnedType returnedType = processor.withDynamicProjection(accessor).getReturnedType();
if (returnedType.isProjecting()) {
returnedType.getInputProperties().forEach(query.fields()::include);
}
return query;
}
try {
BasicQuery result = new BasicQuery(query.getQueryObject(), Document.parse(fieldSpec));
result.setSortObject(query.getSortObject());
return result;
} catch (JsonParseException o_O) {
throw new IllegalStateException(String.format("Invalid query or field specification in %s!", getQueryMethod()), o_O);
}
}
Aggregations