/** * @param converter must not be {@literal null}. */ GridFsOperationsSupport(MongoConverter converter) { Assert.notNull(converter, "MongoConverter must not be null!"); this.converter = converter; this.queryMapper = new QueryMapper(converter); }
public long count(Query query, @Nullable Class<?> entityClass, String collectionName) { Assert.notNull(query, "Query must not be null!"); Assert.hasText(collectionName, "Collection name must not be null or empty!"); CountOptions options = new CountOptions(); query.getCollation().map(Collation::toMongoCollation).ifPresent(options::collation); Document document = queryMapper.getMappedObject(query.getQueryObject(), Optional.ofNullable(entityClass).map(it -> mappingContext.getPersistentEntity(entityClass))); return doCount(collectionName, document, options); }
if (isDBObject(value)) { DBObject valueDbo = (DBObject) value; Document resultDbo = new Document(valueDbo.toMap()); List<Object> ids = new ArrayList<Object>(); for (Object id : (Iterable<?>) valueDbo.get(inKey)) { ids.add(convertId(id, getIdTypeForField(documentField))); resultDbo.put(inKey, ids); } else if (valueDbo.containsField("$ne")) { resultDbo.put("$ne", convertId(valueDbo.get("$ne"), getIdTypeForField(documentField))); } else { return getMappedObject(resultDbo, Optional.empty()); else if (isDocument(value)) { ids.add(convertId(id, getIdTypeForField(documentField))); resultDbo.put("$ne", convertId(valueDbo.get("$ne"), getIdTypeForField(documentField))); } else { return getMappedObject(resultDbo, Optional.empty()); return convertId(value, getIdTypeForField(documentField)); if (isNestedKeyword(value)) { return getMappedKeyword(new Keyword((Bson) value), documentField.getPropertyEntity()); if (isAssociationConversionNecessary(documentField, value)) { return convertAssociation(value, documentField);
/** * Maps fields to retrieve to the {@link MongoPersistentEntity}s properties. <br /> * Also converts and potentially adds missing property {@code $meta} representation. * * @param fieldsObject must not be {@literal null}. * @param entity can be {@litearl null}. * @return * @since 1.6 */ public Document getMappedFields(Document fieldsObject, @Nullable MongoPersistentEntity<?> entity) { Assert.notNull(fieldsObject, "FieldsObject must not be null!"); Document mappedFields = fieldsObject.isEmpty() ? new Document() : getMappedObject(fieldsObject, entity); mapMetaAttributes(mappedFields, entity, MetaMapping.FORCE); return mappedFields; }
/** * Extracts the mapped object value for given field out of rawValue taking nested {@link Keyword}s into account * * @param field * @param rawValue * @return */ protected Entry<String, Object> getMappedObjectForField(Field field, Object rawValue) { String key = field.getMappedKey(); Object value; if (isNestedKeyword(rawValue) && !field.isIdField()) { Keyword keyword = new Keyword((Document) rawValue); value = getMappedKeyword(field, keyword); } else { value = getMappedValue(field, rawValue); } return createMapEntry(key, value); }
@Nullable @SuppressWarnings("unchecked") protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersistentEntity<?> entity) { return delegateConvertToMongoType(source, entity); if (isDocument(source)) { return getMappedObject((Document) source, entity); return delegateConvertToMongoType(source, entity); if (isDBObject(source)) { return getMappedObject((BasicDBObject) source, entity); map.put(key, getMappedObject((Document) it.getValue(), entity)); } else { map.put(key, delegateConvertToMongoType(it.getValue(), entity)); return delegateConvertToMongoType(source, entity);
@Nullable MongoConverter mongoConverter, Consumer<Throwable> subscriptionExceptionHandler) { Assert.notNull(mongoDatabaseFactory, "ReactiveMongoDatabaseFactory must not be null!"); this.queryMapper = new QueryMapper(this.mongoConverter); this.updateMapper = new UpdateMapper(this.mongoConverter); this.schemaMapper = new MongoJsonSchemaMapper(this.mongoConverter);
@SuppressWarnings("unchecked") protected <T> Flux<GeoResult<T>> geoNear(NearQuery near, Class<?> entityClass, String collectionName, Class<T> returnType) { if (near == null) { throw new InvalidDataAccessApiUsageException("NearQuery must not be null!"); } if (entityClass == null) { throw new InvalidDataAccessApiUsageException("Entity class must not be null!"); } String collection = StringUtils.hasText(collectionName) ? collectionName : determineCollectionName(entityClass); Document nearDocument = near.toDocument(); Document command = new Document("geoNear", collection); command.putAll(nearDocument); return Flux.defer(() -> { if (nearDocument.containsKey("query")) { Document query = (Document) nearDocument.get("query"); command.put("query", queryMapper.getMappedObject(query, getPersistentEntity(entityClass))); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Executing geoNear using: {} for class: {} in collection: {}", serializeToJsonSafely(command), entityClass, collectionName); } GeoNearResultDocumentCallback<T> callback = new GeoNearResultDocumentCallback<>( new ProjectingReadCallback<>(mongoConverter, entityClass, returnType, collectionName), near.getMetric()); return executeCommand(command, this.readPreference).flatMapMany(document -> { List<Document> results = document.get("results", List.class); return results == null ? Flux.empty() : Flux.fromIterable(results); }).skip(near.getSkip() != null ? near.getSkip() : 0).map(callback::doWith); }); }
/** * Creates a new {@link DefaultIndexOperations}. * * @param mongoOperations must not be {@literal null}. * @param collectionName must not be {@literal null} or empty. * @param type can be {@literal null}. * @since 2.1 */ public DefaultIndexOperations(MongoOperations mongoOperations, String collectionName, @Nullable Class<?> type) { Assert.notNull(mongoOperations, "MongoOperations must not be null!"); Assert.hasText(collectionName, "Collection name must not be null or empty!"); this.mongoOperations = mongoOperations; this.mapper = new QueryMapper(mongoOperations.getConverter()); this.collectionName = collectionName; this.type = type; }
@Override public <S, T> T findAndReplace(Query query, S replacement, FindAndReplaceOptions options, Class<S> entityType, String collectionName, Class<T> resultType) { Assert.notNull(query, "Query must not be null!"); Assert.notNull(replacement, "Replacement must not be null!"); Assert.notNull(options, "Options must not be null! Use FindAndReplaceOptions#empty() instead."); Assert.notNull(entityType, "EntityType must not be null!"); Assert.notNull(collectionName, "CollectionName must not be null!"); Assert.notNull(resultType, "ResultType must not be null! Use Object.class instead."); Assert.isTrue(query.getLimit() <= 1, "Query must not define a limit other than 1 ore none!"); Assert.isTrue(query.getSkip() <= 0, "Query must not define skip."); MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(entityType); Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), entity); Document mappedFields = queryMapper.getMappedFields(query.getFieldsObject(), entity); Document mappedSort = queryMapper.getMappedSort(query.getSortObject(), entity); Document mappedReplacement = operations.forEntity(replacement).toMappedDocument(this.mongoConverter).getDocument(); return doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, query.getCollation().map(Collation::toMongoCollation).orElse(null), entityType, mappedReplacement, options, resultType); }
@Override public boolean exists(Query query, @Nullable Class<?> entityClass, String collectionName) { if (query == null) { throw new InvalidDataAccessApiUsageException("Query passed in to exist can't be null"); } Assert.notNull(collectionName, "CollectionName must not be null!"); Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), getPersistentEntity(entityClass)); return execute(collectionName, new ExistsCallback(mappedQuery, query.getCollation().map(Collation::toMongoCollation).orElse(null))); }
@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); Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), entity); String mappedFieldName = queryMapper.getMappedFields(new Document(field, 1), entity).keySet().iterator().next(); Class<T> mongoDriverCompatibleType = mongoDatabaseFactory.getCodecFor(resultClass) // .map(Codec::getEncoderClass) // .orElse((Class<T>) BsonValue.class); Flux<?> result = execute(collectionName, collection -> { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Executing findDistinct using query {} for field: {} in collection: {}", serializeToJsonSafely(mappedQuery), field, collectionName); } DistinctPublisher<T> publisher = collection.distinct(mappedFieldName, mappedQuery, mongoDriverCompatibleType); return query.getCollation().map(Collation::toMongoCollation).map(publisher::collation).orElse(publisher); }); if (resultClass == Object.class || mongoDriverCompatibleType != resultClass) { Class<?> targetType = getMostSpecificConversionTargetType(resultClass, entityClass, field); MongoConverter converter = getConverter(); result = result.map(it -> converter.mapValueToTargetType(it, targetType, NO_OP_REF_RESOLVER)); } return (Flux<T>) result; }
public <T> Flux<T> mapReduce(Query filterQuery, Class<?> domainType, String inputCollectionName, Class<T> resultType, String mapFunction, String reduceFunction, MapReduceOptions options) { Assert.notNull(filterQuery, "Filter query must not be null!"); Assert.notNull(domainType, "Domain type must not be null!"); Assert.hasText(inputCollectionName, "Input collection name must not be null or empty!"); Assert.notNull(resultType, "Result type must not be null!"); Assert.notNull(mapFunction, "Map function must not be null!"); Document mappedQuery = queryMapper.getMappedObject(filterQuery.getQueryObject(), mappingContext.getPersistentEntity(domainType)); publisher = publisher.scope(new Document(options.getScopeVariables()));
private List<AggregationOperation> computeCountAggregationPipeline(Query query, @Nullable Class<?> entityType) { CountOperation count = Aggregation.count().as("totalEntityCount"); if (query.getQueryObject().isEmpty()) { return Collections.singletonList(count); } Assert.notNull(entityType, "Entity type must not be null!"); Document mappedQuery = queryMapper.getMappedObject(query.getQueryObject(), mappingContext.getPersistentEntity(entityType)); CriteriaDefinition criteria = new CriteriaDefinition() { @Override public Document getCriteriaObject() { return mappedQuery; } @Nullable @Override public String getKey() { return null; } }; return Arrays.asList(Aggregation.match(criteria), count); }
String reduceFunction, @Nullable MapReduceOptions mapReduceOptions, Class<T> resultType) { Assert.notNull(domainType, "Domain type must not be null!"); Assert.notNull(inputCollectionName, "Input collection name must not be null!"); Assert.notNull(resultType, "Result type must not be null!"); Assert.notNull(mapFunction, "Map function must not be null!"); Assert.notNull(reduceFunction, "Reduce function must not be null!"); .filter(queryMapper.getMappedObject(query.getQueryObject(), mappingContext.getPersistentEntity(domainType))); mapReduce = mapReduce.scope(new Document(mapReduceOptions.getScopeVariables()));
protected DBRef createDBRef(Object target, MongoPersistentProperty property) { Assert.notNull(target, "Target object must not be null!"); if (target instanceof DBRef) { return (DBRef) target; } MongoPersistentEntity<?> targetEntity = mappingContext.getPersistentEntity(target.getClass()); targetEntity = targetEntity != null ? targetEntity : mappingContext.getPersistentEntity(property); if (null == targetEntity) { throw new MappingException("No mapping metadata found for " + target.getClass()); } MongoPersistentEntity<?> entity = targetEntity; MongoPersistentProperty idProperty = entity.getIdProperty(); if (idProperty != null) { Object id = target.getClass().equals(idProperty.getType()) ? target : entity.getPropertyAccessor(target).getProperty(idProperty); if (null == id) { throw new MappingException("Cannot create a reference to an object with a NULL id."); } return dbRefResolver.createDbRef(property == null ? null : property.getDBRef(), entity, idMapper.convertId(id, idProperty != null ? idProperty.getFieldType() : ObjectId.class)); } throw new MappingException("No id property found on class " + entity.getType()); }
@Nullable protected Object convertAssociation(@Nullable Object source, @Nullable MongoPersistentProperty property) { Object id = convertId(ref.getId(), property != null && property.isIdProperty() ? property.getFieldType() : ObjectId.class); BasicDBList result = new BasicDBList(); for (Object element : (Iterable<?>) source) { result.add(createDbRefFor(element, property)); Document result = new Document(); Document dbObject = (Document) source; for (String key : dbObject.keySet()) { result.put(key, createDbRefFor(dbObject.get(key), property)); return createDbRefFor(source, property);
@Override public Document getMappedObject(Bson query, @Nullable MongoPersistentEntity<?> entity) { Document document = super.getMappedObject(query, entity); for (String s : document.keySet()) { if (s.startsWith("$")) { set = document.get(s, Document.class); Document updateObject = new Document(); Document fieldsToSet = set == null ? new Document() : set;
public <T> GroupByResults<T> group(@Nullable Criteria criteria, String inputCollectionName, GroupBy groupBy, Class<T> entityClass) { document.put("ns", inputCollectionName); document.put("cond", null); } else { document.put("cond", queryMapper.getMappedObject(criteria.getCriteriaObject(), Optional.empty()));
protected <T> Mono<DeleteResult> doRemove(String collectionName, Query query, @Nullable Class<T> entityClass) { Assert.hasText(collectionName, "Collection name must not be null or empty!"); Document removeQuey = queryMapper.getMappedObject(queryObject, entity);