Bueno, en Spring Data este tipo de consultas no es trivial
.
Malas noticias:
Spring Data Repository no tiene una solución para MongoDB Aggregation
. Por lo tanto, no puede implementar en MongoRepository ningún método para hacerlo, como aggregateBy...
Buenas noticias:
Spring Data proporciona MongoTemplate
class que le permite ejecutar consultas complejas, como lo haría en el shell estándar de MongoDB.
Entonces, como solo desea exclude
subdocumento que no coincide con alguna condición, necesitamos definir los pipelines
agregados .
Supongo:
zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter
La agregación de MongoDB sería:
db.person.aggregate([
{$unwind: "$address"},
{$match: {"address.zip": 12345}},
{$group: { _id: { "firstName":"$firstName", "lastName":"$lastName", _id:"$_id" }, address: { $push: "$address" } } },
{$project: {_id:0, "firstName":"$_id.firstName", "lastName":"$_id.lastName", "address": "$address"}}
])
Si todos los filtros tienen éxito, obtendremos:
[
{
"address" : [
{
"zip" : 12345
},
{
"zip" : 12345
}
],
"firstName" : "George",
"lastName" : "Washington"
}
]
Ahora, en Spring Data, necesita agregar algunos cambios en su proyecto:
Primero, encuentra tu mongo-config.xml
donde necesitas agregar:
<!-- Define the mongoDbFactory with your database Name -->
<mongo:db-factory uri="mongodb://user:[email protected]:27017/db"/>
<!-- Define the MongoTemplate -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
MongoTemplate
es la clase central de la compatibilidad con MongoDB de Spring que proporciona conjuntos de características para interactuar con la base de datos. La plantilla ...
proporciona una asignación entre sus objetos de dominio y documentos MongoDB . Más información
Segundo, en su @Service
clase, agregue el siguiente código para que se cargue en @PostConstruct
@Autowired
private MongoOperations mongoOperations;
...
public List<Person> findByAddressZipCode(int zip) {
List<AggregationOperation> list = new ArrayList<AggregationOperation>();
list.add(Aggregation.unwind("address"));
list.add(Aggregation.match(Criteria.where("address.zip").is(zip)));
list.add(Aggregation.group("firstName", "lastName").push("address").as("address"));
list.add(Aggregation.project("firstName", "lastName", "address"));
TypedAggregation<Person> agg = Aggregation.newAggregation(Person.class, list);
return mongoOperations.aggregate(agg, Person.class, Person.class).getMappedResults();
}
Person
y Address
debería tener un constructor vacío por defecto!