Bene, in Spring Data questo tipo di query non è trivial
.
Cattive notizie:
Spring Data Repository non ha una soluzione per MongoDB Aggregation
. Quindi, non puoi implementare in MongoRepository alcun metodo per farlo, come aggregateBy...
Buone notizie:
Spring Data fornisce MongoTemplate
classe che ti consente di eseguire query complesse, come faresti nella shell MongoDB standard.
Quindi, poiché vuoi solo exclude
documento secondario che non soddisfa alcune condizioni, è necessario definire le pipelines
aggregate .
Presumo:
zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter
L'aggregazione MongoDB sarebbe:
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"}}
])
Se tutti i filtri hanno successo, abbiamo:
[
{
"address" : [
{
"zip" : 12345
},
{
"zip" : 12345
}
],
"firstName" : "George",
"lastName" : "Washington"
}
]
Ora, in modo Spring Data, devi aggiungere alcune modifiche al tuo progetto:
Per prima cosa, trova il tuo mongo-config.xml
dove devi aggiungere:
<!-- 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
è la classe centrale del supporto MongoDB di Spring che fornisce set di funzionalità per interagire con il database. Il modello ...
fornisce una mappatura tra i tuoi oggetti di dominio e documenti MongoDB . Ulteriori informazioni
Secondo, nel tuo @Service
class, aggiungi il seguente codice da caricare in @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();
}
Nota: Entrambi, Person
e Address
dovrebbe avere un costruttore vuoto predefinito!