정의
$accumulatorDefines a custom accumulator operator. Accumulators are operators that maintain their state (e.g. totals, maximums, minimums, and related data) as documents progress through the pipeline. Use the
$accumulatoroperator to execute your own JavaScript functions to implement behavior not supported by the MongoDB Query Language. See also$function.$accumulator이 단계에서 사용할 수 있습니다:중요
Executing JavaScript inside of an aggregation operator may decrease performance. Only use the
$accumulatoroperator if the provided pipeline operators cannot fulfill your application's needs.
구문
The $accumulator operator has this syntax:
{ $accumulator: { init: <code>, initArgs: <array expression>, // Optional accumulate: <code>, accumulateArgs: <array expression>, merge: <code>, finalize: <code>, // Optional lang: <string> } }
필드 | 유형 | 설명 | ||||
|---|---|---|---|---|---|---|
문자열 또는 코드 | 상태를 초기화하는 데 사용되는 함수입니다.
디스크로 유출하거나 샤딩된 클러스터에서 쿼리를 실행하면 축적자가 각각 | |||||
배열 | 선택 사항.
중요: | |||||
문자열 또는 코드 | Function used to accumulate documents. The
| |||||
배열 |
| |||||
문자열 또는 코드 | Function used to merge two internal states.
| |||||
문자열 또는 코드 | 선택 사항. 누적 결과를 업데이트하는 데 사용되는 함수입니다.
| |||||
문자열 | The language used in the 중요: 현재 |
행동
The following steps outline how the $accumulator operator processes documents:
The operator begins at an initial state, defined by the init function.
각 문서에 대해 연산자는 누적 함수를 기반으로 상태를 업데이트합니다. 누적 함수의 첫 번째 인수는 현재 상태이며 추가 인수는 accumulateArgs 배열에 지정할 수 있습니다.
When the operator needs to merge multiple intermediate states, it executes the merge function. For more information on when the merge function is called, see Merge Two States with
$merge.
두 상태 병합 $merge
As part of its internal operations, the $accumulator operator may need to merge two separate, intermediate states. The merge function specifies how the operator should merge two states.
병합 함수는 항상 한 번에 두 가지 상태를 병합합니다. 세 개 이상의 상태를 병합해야 하는 경우 두 상태의 결과 병합은 단일 상태 로 병합됩니다. 이 프로세스 모든 상태가 병합될 때까지 반복됩니다.
For example, $accumulator may need to combine two states in the following scenarios:
$accumulator샤딩된 클러스터에서 실행됩니다. 연산자는 최종 결과를 얻기 위해 각 샤드의 결과를 병합해야 합니다.A single
$accumulatoroperation exceeds its specified memory limit. If you specify theallowDiskUseoption, the operator stores the in-progress operation on disk and finishes the operation in memory. Once the operation finishes, the results from disk and memory are merged together using the merge function.
문서 처리 순서
MongoDB가 init(), accumulate(), merge() 함수에 대해 문서를 처리하는 순서는 다를 수 있으며, $accumulator 함수에 해당 문서가 지정된 순서와 다를 수 있습니다.
예를 들어 _id 필드가 알파벳 문자인 일련의 문서를 생각해 보세요.
{ _id: 'a' }, { _id: 'b' }, { _id: 'c' } ... { _id: 'z' }
다음으로 _id 필드를 기준으로 문서를 정렬한 다음 $accumulator 함수를 사용하여 _id 필드 값을 연결하는 집계 파이프라인을 고려합니다.
[ { $sort: { _id: 1 } }, { $group: { _id: null, alphabet: { $accumulator: { init: function() { return "" }, accumulate: function(state, letter) { return(state + letter) }, accumulateArgs: [ "$_id" ], merge: function(state1, state2) { return(state1 + state2) }, lang: "js" } } } } ]
MongoDB는 문서가 정렬된 순서로 처리되는 것을 보장하지 않으므로 alphabet 필드가 반드시 abc...z로 설정되는 것은 아닙니다.
이 동작으로 인해 $accumulator 함수가 특정 순서로 문서를 처리하고 반환할 필요가 없는지 확인합니다.
Javascript 활성화
To use $accumulator, you must have server-side scripting enabled.
If you do not use $accumulator (or $function, $where, or mapReduce), disable server-side scripting:
mongod인스턴스의 경우security.javascriptEnabled구성 옵션 또는 명령줄 옵션을 참조하세요--noscripting.mongos인스턴스의 경우security.javascriptEnabled구성 옵션 또는--noscripting명령줄 옵션을 참조하세요.이전 버전에서 MongoDB는
mongos인스턴스에서 JavaScript 실행을 허용하지 않습니다.
또한 ➤ 보안 구성 옵션으로 MongoDB 실행을 참조하세요.
지원되지 않는 배열 및 문자열 함수
MongoDB 6.0 upgrades the internal JavaScript engine used for server-side JavaScript, $accumulator, $function, and $where expressions and from MozJS-60 to MozJS-91. Several deprecated, non-standard array and string functions that existed in MozJS-60 are removed in MozJS-91.
예시
이 페이지의 예시는 sample_mflix 데이터 세트의 데이터를 사용합니다. 이 데이터 세트를 자체 관리형 MongoDB 배포서버에 로드하는 방법에 대한 자세한 내용은 샘플 데이터세트 로드를 참조하세요. 샘플 데이터베이스를 수정한 경우, 이 페이지의 예시를 실행하려면 데이터베이스를 제거하고 다시 생성해야 할 수 있습니다.
$accumulator 를 사용하여 $avg 연산자 구현
참고
This example walks through using the $accumulator operator to implement the $avg operator, which is already supported by MongoDB. The goal of this example is not to implement new functionality, but to illustrate the behavior and syntax of the $accumulator operator with familiar logic.
The following operation groups the documents by rated, and uses $accumulator to compute the average imdb.rating for each content rating. The $match stage restricts the input to the G, PG, PG-13, and R content ratings, and excludes documents where imdb.rating is not a double, such as an empty string:
db.movies.aggregate( [ { $match: { rated: { $in: [ "G", "PG", "PG-13", "R" ] }, "imdb.rating": { $type: "double" } } }, { $group: { _id: "$rated", avgRating: { $accumulator: { init: function() { // Set the initial state return { count: 0, sum: 0 } }, accumulate: function(state, rating) { // Define how to update the state return { count: state.count + 1, sum: state.sum + rating } }, accumulateArgs: [ "$imdb.rating" ], // Argument required by the accumulate function merge: function(state1, state2) { // When the operator performs a merge, return { // add the fields from the two states count: state1.count + state2.count, sum: state1.sum + state2.sum } }, finalize: function(state) { // After collecting the results from all documents, return (state.sum / state.count) // calculate the average }, lang: "js" } } } }, { $sort: { _id: 1 } } ] )
[ { _id: 'G', avgRating: 6.628092243186578 }, { _id: 'PG', avgRating: 6.43525917926564 }, { _id: 'PG-13', avgRating: 6.404911676001717 }, { _id: 'R', avgRating: 6.456657633242984 } ]
행동
The $accumulator defines an initial state where count and sum are both set to 0. For each document that the $accumulator processes, it updates the state by:
count를 1씩 증가Adding the values of the document's
imdb.ratingfield to thesum. The accumulate function can access theimdb.ratingfield because it is passed in the accumulateArgs field.
문서가 처리될 때마다 accumulate 함수는 업데이트된 상태를 반환합니다.
모든 문서가 처리되면 finalize 함수는 등급의 sum을 문서의 count로 나누어 평균을 구합니다. 이렇게 하면 finalize 함수가 모든 문서의 누적 sum 및 count를 수신하기 때문에 실행 계산된 평균을 계속 유지할 필요가 없습니다.
와(과) 비교하기 $avg
이 작업은 $avg 연산자를 사용하는 다음 파이프라인과 동일합니다.
db.movies.aggregate( [ { $match: { rated: { $in: [ "G", "PG", "PG-13", "R" ] }, "imdb.rating": { $type: "double" } } }, { $group: { _id: "$rated", avgRating: { $avg: "$imdb.rating" } } }, { $sort: { _id: 1 } } ] )
[ { _id: 'G', avgRating: 6.6280922431865825 }, { _id: 'PG', avgRating: 6.435259179265659 }, { _id: 'PG-13', avgRating: 6.404911676001723 }, { _id: 'R', avgRating: 6.456657633242999 } ]
initArgs 을 사용하여 그룹별로 초기 상태 변경
initArgs 옵션을 사용하여 $accumulator의 초기 상태 변경할 수 있습니다. 예시 를 들어 다음과 같은 경우에 유용합니다.
사용자의 상태에 없는 필드 값을 사용하여 사용자의 상태에 영향을 미치거나
처리 중인 그룹에 따라 초기 상태를 다른 값으로 설정합니다.
사용자가 이 데이터를 쿼리 영화를 찾을 수 있는 애플리케이션 허용한다고 가정해 보겠습니다. 사용자가 선호하는 콘텐츠 등급에 대한 결과를 더 많이 표시하는 것이 유용할 수 있습니다. 이 예시 에서, 사용자의 선호 콘텐츠 등급은 PG-13이며, 이는 init 함수에 userProfileRated로 전달됩니다.
다음 집계 파이프라인 groups은 rated에 의해 문서를 작성합니다. 이 작업은 $accumulator를 사용하여 영화의 등급이 사용자 프로필의 등급과 일치하는지 여부에 따라 각 콘텐츠 등급에서 다른 수의 영화를 표시합니다.
참고
다른 기본 콘텐츠 등급으로 이 예시 실행 하려면 initArgs 배열 의 "PG-13"을 "R"와 같은 다른 값으로 바꿉니다.
db.movies.aggregate( [ { $match: { rated: { $in: [ "G", "PG", "PG-13", "R" ] }, "imdb.rating": { $type: "double" } } }, { $sort: { "imdb.rating": -1, title: 1 } }, { $group: { _id: { rated: "$rated" }, movies: { $accumulator: { init: function(rated, userProfileRated) { // Set the initial state return { max: rated === userProfileRated ? 3 : 1, // If the group matches the user's rating, movies: [] // return 3 movies. Otherwise, return 1. } }, initArgs: [ "$rated", "PG-13" ], // Argument to pass to the init function accumulate: function(state, movieTitle) { // Define how to update the state if (state.movies.length < state.max) { state.movies.push(movieTitle); } return state; }, accumulateArgs: [ "$title" ], // Argument required by the accumulate function merge: function(state1, state2) { return { max: state1.max, movies: state1.movies.concat(state2.movies).slice(0, state1.max) } }, finalize: function(state) { // Adjust the state to only return the field we need return state.movies }, lang: "js" } } } }, { $sort: { "_id.rated": 1 } } ] )
[ { _id: { rated: 'G' }, movies: [ 'Modern Times' ] }, { _id: { rated: 'PG' }, movies: [ 'Life' ] }, { _id: { rated: 'PG-13' }, movies: [ 'A Brave Heart: The Lizzie Velasquez Story', 'The Dark Knight', 'The Lord of the Rings: The Return of the King' ] }, { _id: { rated: 'R' }, movies: [ 'The Shawshank Redemption' ] } ]
행동
init 함수는 max 및 movies 필드를 포함하는 초기 상태 정의합니다. max 필드 해당 특정 그룹 의 최대 영화 수를 설정합니다. 문서의 rated 필드 userProfileRated와 일치하는 경우, 해당 그룹 에는 최대 3개의 동영상이 포함됩니다. 그렇지 않고 문서의 rated 필드 userProfileRated와 일치하지 않으면 그룹 최대 하나의 영화가 포함됩니다.init 함수는 initArgs 배열 에서 rated 및 userProfileRated 인수를 모두 받습니다.
$accumulator가 처리하는 각 문서 에 대해, 해당 제목이 movies의 길이를 max 값 위에 두지 않는 경우 영화의 title를 movies 배열 로 푸시합니다. 문서 처리될 때마다 축적 함수는 업데이트된 상태 를 반환합니다.
병합 함수는 두 상태를 병합하는 방법을 정의합니다. 이 함수는 각 상태 의 movies 배열을 함께 연결하고, 결과 배열 의 길이는 slice() 메서드를 사용하여 제한되어 max 값을 초과하지 않도록 합니다.
모든 문서가 처리되면 finalize 함수는 영화 제목만 반환하도록 결과 상태 수정합니다. 이 함수가 없으면 max 필드 도 출력에 포함되어 애플리케이션 에 대한 요구 사항을 충족하지 못합니다.