mongodb $topN

Divan·2023년 2월 14일

몽고db 5.2버전 이후에 $top기능이 aggregation에서 사용 가능합니다.
이는 mssql에서 parttion와 유사 기능을 합니다.

select 집계함수([컬럼이름]) over (partion by [컬럼이름]) from [테이블 이름]

partion by 참고


topN이 없는 경우

$topN이 나오기 이전에는 아래와 같이 Sort를 진행하고 Push 명령어를 통하여 groupby를 하는 key(아래에서는 category)에 해당하는곳에 list만들어서 넣어서 그것에 unwind하여 각각 rank를 만드는 작업을 하였다.
이는 group을하고 key에 해당하는 list를 다 만들기에 .. 데이터 크기에 따라 상당한 메모리를 요구한다. (메모리 부족 에러가 발생)

	sortState := bson.D{{"$sort", bson.D{{"pair", 1}, {"time", -1}}}}
	groupState := bson.D{{"$group", bson.D{
		{"_id", "$category"},
		{"items", bson.D{{"$push", "$$ROOT"}}},
	}}}
	unwindState := bson.D{{"$unwind", bson.D{
		{"path", "$items"},
		{"includeArrayIndex", "items.rank"},
	}}}
	projectState := bson.D{{"$project", bson.D{
		{"_id", 0},
		{"rank", bson.D{{"$add", bson.A{"$items.rank", 1}}}},
	}}}
	matchState := bson.D{{"$match", bson.D{{"rank", bson.D{{"$lt", 3}}}}}}
	cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{sortState, groupState, unwindState, projectState, matchState})
	

topN를 사용

$top (aggregation accumulator)

위와 같이 category로 group을 만들고 time의 역순으로 정렬을하여 3(n:3)를 뽑아내는 쿼리이다. 보는것과 같이 쿼리내용이 상당히 짧아지며, 메모리를 효율적으로 시스템이 사용한다.

sortState := bson.M{"time": -1}
topState := bson.M{"$topN": bson.M{"output": "$$ROOT", "sortBy": sortState, "n": 3}}
topNState := bson.D{{Key: "$group", Value: bson.M{"_id": "$category", "item": topState}}}
cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{topNState})
profile
하루 25분의 투자

1개의 댓글

comment-user-thumbnail
2023년 2월 14일

Partion -> partition 오타인거 같아용!

답글 달기