Spring Data MongoDB - Aggregation Operation - 01

 

MongoDB의 Aggregation을 지원하는 Java 인터페이스로 $match , $project , $sort 등을 지원해준다.

 

MatchOperation

지정된 조건과 일치하는 Document를 찾아주는 MongoDB에서의 $match를 지원해준다.

{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
{ "_id" : ObjectId("55f5a192d4bede9ac365b257"), "author" : "ahn", "score" : 60, "views" : 1000 }
{ "_id" : ObjectId("55f5a192d4bede9ac365b258"), "author" : "li", "score" : 55, "views" : 5000 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b259"), "author" : "annT", "score" : 60, "views" : 50 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b25a"), "author" : "li", "score" : 94, "views" : 999 }
{ "_id" : ObjectId("55f5a1d3d4bede9ac365b25b"), "author" : "ty", "score" : 95, "views" : 1000 }

/*
 	db.articles.aggregate(
    [ { $match : { author : "dave" } } ]
	)
*/
@Test
public void 저자가_dave인_사용자찾기() {
	MatchOperation matchOperation = Aggregation.match(
		Criteria.where("author").is("dave")
	);

	Aggregation aggregation = Aggregation.newAggregation(
		matchOperation
	);

	mongoTemplate.aggregate(aggregation, "articles", Article.class);
}

/* Results
{ "_id" : ObjectId("512bc95fe835e68f199c8686"), "author" : "dave", "score" : 80, "views" : 100 }
{ "_id" : ObjectId("512bc962e835e68f199c8687"), "author" : "dave", "score" : 85, "views" : 521 }
*/

 

AddFieldsOperation

Document에 새로운 필드를 추가하는 MongoDB에서의 $addFields를 지원해준다.

{
  _id: 1,
  student: "Maya",
  homework: [ 10, 5, 10 ],
  quiz: [ 10, 8 ],
  extraCredit: 0
}
/*
	db.scores.aggregate( [
	{
		 $addFields: {
		   totalHomework: { $sum: "$homework" }
		 }
  } ] )
*/
@Test
public void 숙제점수_총합_필드추가() {
	AggregationExpression homeworkSumExpression = ArithmeticOperators.valueOf("homework").sum();

	AddFieldsOperation addFieldsOperation = Aggregation.addFields()
		.addField("totalHomework").withValueOf(homeworkSumExpression)
		.build();

	Aggregation aggregation = Aggregation.newAggregation(
		addFieldsOperation
	);

	mongoTemplate.aggregate(aggregation, "scores", Score.class);
}

/* Results
{
  _id: 1,
  student: "Maya",
  homework: [ 10, 5, 10 ],
  quiz: [ 10, 8 ],
  extraCredit: 0,
  totalHomework: 25
}
*/

 

ProjectionOperation

원하는 필드를 제외하거나 포함하는 MongoDB에서의 $project를 지원해준다.

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5
}
/*
	db.books.aggregate(
	 [ { $project : { title : 1 , author : 1 } } ]
	)
*/
@Test
public void 제목과_저자만_출력하기() {
	ProjectionOperation projectionOperation = Aggregation.project()
		.and("title").as("title")
		.and("author").as("author");

	Aggregation aggregation = Aggregation.newAggregation(
		projectionOperation
	);

	mongoTemplate.aggregate(aggregation, "books", Book.class);
}

/* Results
{
  "_id" : 1,
  title: "abc123",
  author: { last: "zzz", first: "aaa" }
}
*/

 

SortOperation

원하는 필드로 정렬을 하는 MongoDB에서의 $sort를 지원해준다.

{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan"}
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens"}
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"}
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan"}
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn"}
/*
	db.restaurants.aggregate(
	 [ { $sort : { borough : 1, _id: -1 } } ]
  )
*/
@Test
public void 도시를_기준으로_오름차순_정렬() {
	SortOperation sortOperation = Aggregation.sort(Sort.Direction.ASC, "borough")
			.and(Sort.Direction.DESC, "_id");

	Aggregation aggregation = Aggregation.newAggregation(
		sortOperation
	);

	mongoTemplate.aggregate(aggregation, "restaurants", Restaurant.class);
}

/* Results
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn" }
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn" }
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan" }
{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan" }
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens" }
*/

 

SkipOperation

원하는 양 이후의 Document를 가져오는 MongoDB의 $skip을 지원해준다.

{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan"}
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens"}
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"}
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan"}
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn"}
/*
	db.article.aggregate([
		{ $skip : 2 }
	]);
*/
@Test
public void 두개_이후의_레스토랑() {
	SkipOperation skipOperation = Aggregation.skip(2L);

	Aggregation aggregation = Aggregation.newAggregation(
		skipOperation
	);

	mongoTemplate.aggregate(aggregation, "restaurants", Restaurant.class);
}

/* Results
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"}
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan"}
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn"}
*/

 

LimitOperation

원하는 양만큼 Document를 가져오는 MongoDB의 $limit을 지원해준다.

{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan"}
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens"}
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"}
{ "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan"}
{ "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn"}
/*
	db.article.aggregate([
	   { $limit : 3 }
	]);
*/
@Test
public void 최대_세개까지의_레스토랑() {
	LimitOperation limitOperation = Aggregation.limit(3L);

	Aggregation aggregation = Aggregation.newAggregation(
		limitOperation
	);

	mongoTemplate.aggregate(aggregation, "restaurants", Restaurant.class);
}

/* Results
{ "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan"}
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens"}
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"}
*/

Leave a comment