Closed spring-projects-issues closed 6 years ago
Phillip Wirth commented
I would like to see this feature too. I don't know any way to create a query like the following using query-dsl while using spring-data-mongodb.
db.foo.find({
"bar" : 5051
},
{bar : 1,
'innerDoc' : {
$elemMatch: {
'innerFoo' : "nice"
}
}
})
vinoth kumar commented
Hi Oliver, Please let me know does this issue resolved in latest version of querydsl? I am in need of this feature for querydsl spring mongo repository
If so Can you please let me know where can I find the documentation
ZhangLiangliang commented
anyEmbedded() is on the query level, since it involves a join alias which are always declared on the query level. Another reason is that the Expression types are the same for most Querydsl modules. It is also documented like this in #115.
So does this mean there is no method like "elemMatch" mothod on generated "QXxx" classes ?
@DBRef
field) when using queryDSL:userRepo.findAll(Expressions.allOf(
QUser.user.tags.any().in("tag1", 'tag99')
))
since anyEmbedded
method is defined on com.querydsl.mongodb.AbstractMongodbQuery
, we can use it with SpringDataMongodbQuery
. But QueryDslMongoRepository#createQuery()
is private method. So maybe it should change to protected or public, then add some convenient method?
Before this was changed , have to do it myself with custom repository implement:
@NoRepositoryBean
public interface MyRepository<T, ID extends Serializable>
extends MongoRepository<T, ID>, QueryDslPredicateExecutor<T> {
public abstract AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> query();
}
public class MyRepositoryImpl<T, ID extends Serializable>
extends QueryDslMongoRepository<T, ID>
implements MongoRepository<T, ID>, MyRepository<T, ID> {
public MyRepositoryImpl(MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations) {
super(entityInformation, mongoOperations);
EntityPath<T> path = SimpleEntityPathResolver.INSTANCE.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
this.entityInformation = entityInformation;
this.mongoOperations = mongoOperations;
}
public MyRepositoryImpl(MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations, EntityPathResolver resolver) {
super(entityInformation, mongoOperations, resolver);
EntityPath<T> path = resolver.createPath(entityInformation.getJavaType());
this.builder = new PathBuilder<T>(path.getType(), path.getMetadata());
this.entityInformation = entityInformation;
this.mongoOperations = mongoOperations;
}
public AbstractMongodbQuery<T, SpringDataMongodbQuery<T>> getQuery() {
return new SpringDataMongodbQuery<T>(mongoOperations, entityInformation.getJavaType());
}
private final PathBuilder<T> builder;
private final EntityInformation<T, ID> entityInformation;
private final MongoOperations mongoOperations;
}
@Configuration
@EnableMongoRepositories(repositoryBaseClass = MyRepositoryImpl.class, basePackageClasses = MyRepository.cass)
@EnableMongoAuditing
class MongoConf {
}
AbstractMongodbQuery<Addr, SpringDataMongodbQuery<Addr>> query = addrRepo.getQuery()
query.anyEmbedded(QAddr.addr.streetList, null).on(
QAddr_Street.street.name.in("street-2", "street-200")
)
List<Addr> addrList = query.fetchResults().getResults()
return addrList
Hong Quang commented
Hi @ZhangLiangliang
: Could you please post your full source code? How can instantiate the Object MongoEntityInformation<T, ID> entityInformation, MongoOperations mongoOperations
ZhangLiangliang commented
@Hong
Quang
That's almost the full source code. I'm using spring-boot + spring-data-mongo.
MongoEntityInformation, MongoOperations is instantiated by the framework.
I think you need to read Adding custom behavior to all repositories.
Still intresting how they were instantiated ? Just using github's advanced searching , such as Where MongoEntityInformation
is used?, then trace, debug.
Christoph Strobl commented
Resolved via DATAMONGO-1848. SpringDataMongodbQuery
now exposes anyEmbedded
.
new SpringDataMongodbQuery<>(mongoTemplate, Person.class)
.where()
.anyEmbedded(QPerson.person.shippingAddresses, QAddress.address)
.on(QAddress.address.planet.eq("Tatooine"))
.fetch();
As I spent some time searching the web for a solution to fit my needs I just want to share how I (miss)-use the elemMatch functionality.
I came up with this util method:
public static <D, Q extends SimpleExpression<D>> PredicateOperation elemMatch(@NonNull ListPath<D, Q> path,
@NonNull Q queryDocument,
@NonNull List<Function<Q, Predicate>> predicates) {
return ExpressionUtils.predicate(
MongodbOps.ELEM_MATCH,
path.any(),
ExpressionUtils.allOf(predicates
.stream()
.map(predicate -> predicate.apply(queryDocument))
.toList())
);
}
That I use in the following way when building predicates:
personRepository.findAll(
QPerson.person.name.eq("Luke")
.and(elemMatch(
QPerson.person.shippingAddresses,
QAddress.address,
List.of(
address -> address.planet.eq("Tatooine"),
address -> address.planet.region.eq("Outer Rim")
)
))
);
I hope it can help someone with the same problem :)
Regards, Petter
Raman Gupta opened DATAMONGO-595 and commented
QueryDSL, as of version 2.5.0, supports building queries with the MongoDB $elemMatch operator:
https://github.com/mysema/querydsl/issues/115
This functionality is available from MongodbQuery using the builder returned by the new method anyEmbedded. However, I don't see any way to access this functionality via QueryDslMongoRepository.
See also: https://github.com/mysema/querydsl/issues/324
Affects: 1.1.1
Issue Links:
3 votes, 6 watchers