Eh bien, dans Spring Data, ce type de requêtes n'est pas trivial
.
Mauvaise nouvelle :
Spring Data Repository n'a pas de solution pour MongoDB Aggregation
. Ainsi, vous ne pouvez pas implémenter dans MongoRepository une méthode pour le faire, comme aggregateBy...
Bonne nouvelle :
Spring Data fournit MongoTemplate
classe qui vous permet d'exécuter des requêtes complexes, comme vous le feriez dans le shell MongoDB standard.
Donc, comme vous voulez juste exclude
sous-document qui ne correspond pas à certaines conditions, nous devons définir l'agrégat pipelines
.
Je suppose :
zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter
L'agrégation MongoDB serait :
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 tous les filtres réussissent, nous obtenons :
[
{
"address" : [
{
"zip" : 12345
},
{
"zip" : 12345
}
],
"firstName" : "George",
"lastName" : "Washington"
}
]
Maintenant, à la manière de Spring Data, vous devez ajouter quelques modifications à votre projet :
Tout d'abord, trouvez votre mongo-config.xml
où vous devez ajouter :
<!-- 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
est la classe centrale du support MongoDB de Spring fournissant des ensembles de fonctionnalités pour interagir avec la base de données. Le modèle ...
fournit un mappage entre vos objets de domaine et Documents MongoDB . Plus d'infos
Deuxièmement, dans votre @Service
class, ajoutez le code suivant à charger dans @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();
}
Remarque : Les deux, Person
et Address
devrait avoir un constructeur vide par défaut !