Nah, Dalam Data Musim Semi, kueri semacam itu bukan trivial
.
Kabar buruk:
Spring Data Repository tidak memiliki solusi untuk MongoDB Aggregation
. Jadi, Anda tidak dapat menerapkan di MongoRepository metode apa pun untuk melakukannya, seperti aggregateBy...
Kabar baik:
Data Musim Semi menyediakan MongoTemplate
class yang memungkinkan Anda untuk mengeksekusi kueri kompleks, seperti yang akan Anda lakukan di shell MongoDB standar.
Jadi, karena Anda hanya ingin exclude
subdocument yang tidak cocok dengan beberapa kondisi, kita perlu mendefinisikan pipelines
agregat .
Saya berasumsi:
zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter
Agregasi MongoDB akan menjadi:
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"}}
])
Jika semua filter berhasil, kami mendapatkan:
[
{
"address" : [
{
"zip" : 12345
},
{
"zip" : 12345
}
],
"firstName" : "George",
"lastName" : "Washington"
}
]
Sekarang, dengan cara Spring Data, Anda perlu menambahkan beberapa perubahan dalam proyek Anda:
Pertama, temukan mongo-config.xml
Anda di mana Anda perlu menambahkan:
<!-- 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
adalah kelas pusat dari dukungan MongoDB Spring yang menyediakan set fitur untuk berinteraksi dengan database. Templat ...
menyediakan pemetaan antara objek domain dan dokumen MongoDB . Info selengkapnya
Kedua, di @Service
. Anda kelas, tambahkan kode berikut untuk dimuat di @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();
}
Catatan: Keduanya, Person
dan Address
harus memiliki konstruktor kosong default!