さて、Spring Dataでは、このような種類のクエリはtrivial
ではありません。 。
悪いニュース:
SpringDataRepositoryにはMongoDB Aggregation
のソリューションがありません 。したがって、MongoRepositoryに、aggregateBy...
などのメソッドを実装することはできません。
朗報:
SpringDataはMongoTemplate
を提供します 標準のMongoDBシェルで行うように、複雑なクエリを実行できるクラス。
したがって、exclude
したいだけです 一部の条件に一致しないサブドキュメントの場合、集約pipelines
を定義する必要があります 。
想定:
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
を見つけます 追加する必要がある場所:
<!-- 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
は、データベースと対話するための機能セットを提供するSpringのMongoDBサポートの中心的なクラスです。テンプレート...
ドメインオブジェクト間のマッピングを提供します およびMongoDBドキュメント 。 詳細a>
次に、@Service
で クラス、@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
およびAddress
デフォルトの空のコンストラクターが必要です!