好吧,在Spring Data中,这种查询并不简单.
坏消息:
Spring Data Repository没有适用于MongoDB聚合的解决方案.因此,您无法在MongoRepository中实现任何方法来实现此目的,例如aggregateBy …
好消息:
Spring Data提供了MongoTemplate类,该类使您可以执行复杂的查询,就像在标准MongoDB shell中一样.
因此,由于您只想排除不符合某些条件的子文档,因此我们需要定义聚合管道.
我假设:
zip codes are Numeric (In your example is string)
And, to exclude subdocument, we filter by `zip`
There is no any other filter
MongoDB聚合为:
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"}}
])
如果所有筛选器均成功,则我们得到:
[
{
"address" : [
{
"zip" : 12345
},
{
"zip" : 12345
}
],
"firstName" : "George",
"lastName" : "Washington"
}
]
现在,以Spring Data的方式,您需要在项目中添加一些更改:
首先,找到需要添加的mongo-config.xml:
MongoTemplate是Spring的MongoDB支持的核心类,提供与数据库交互的功能集.模板…提供域对象和MongoDB文档之间的映射. More info
其次,在您的@Service类中,添加以下代码以在@PostConstruct中加载
@Autowired
private MongoOperations mongoOperations;
...
public List findByAddressZipCode(int zip) {
List list = new ArrayList();
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 agg = Aggregation.newAggregation(Person.class, list);
return mongoOperations.aggregate(agg, Person.class, Person.class).getMappedResults();
}
注意:Person和Address都应具有默认的空构造函数!