[MONGODB] MongoDB를의 통합 프레임 워크 이동 평균?
MONGODBMongoDB를의 통합 프레임 워크 이동 평균?
당신은 당신이 이동 평균 계산합니다 방법 (예를 들어) (매일) 온도 기상 데이터 50 년, 그 시간 동안, 3 개월 간격을 사용하여이 있다면? 당신은 하나 개의 쿼리로 그렇게 할 수 또는 여러 개의 쿼리를해야 할 것?
Example Data
01/01/2014 = 40 degrees
12/31/2013 = 38 degrees
12/30/2013 = 29 degrees
12/29/2013 = 31 degrees
12/28/2013 = 34 degrees
12/27/2013 = 36 degrees
12/26/2013 = 38 degrees
.....
해결법
-
==============================
1.AGG 프레임 워크는 현재 $지도를 가지고 있으며, $ 감소와 $는 배열 처리가 훨씬 더 straightfoward되도록 내장 범위. 다음은 몇 가지 조건에 의해 필터 할 경우 데이터 집합에 대한 이동 평균 계산의 예입니다. 기본 설정은 각 문서는 필터링이 기준 값과, 예를 들어 포함되고
AGG 프레임 워크는 현재 $지도를 가지고 있으며, $ 감소와 $는 배열 처리가 훨씬 더 straightfoward되도록 내장 범위. 다음은 몇 가지 조건에 의해 필터 할 경우 데이터 집합에 대한 이동 평균 계산의 예입니다. 기본 설정은 각 문서는 필터링이 기준 값과, 예를 들어 포함되고
{sym: "A", d: ISODate("2018-01-01"), val: 10} {sym: "A", d: ISODate("2018-01-02"), val: 30}
여기있어:
// This controls the number of observations in the moving average: days = 4; c=db.foo.aggregate([ // Filter down to what you want. This can be anything or nothing at all. {$match: {"sym": "S1"}} // Ensure dates are going earliest to latest: ,{$sort: {d:1}} // Turn docs into a single doc with a big vector of observations, e.g. // {sym: "A", d: d1, val: 10} // {sym: "A", d: d2, val: 11} // {sym: "A", d: d3, val: 13} // becomes // {_id: "A", prx: [ {v:10,d:d1}, {v:11,d:d2}, {v:13,d:d3} ] } // // This will set us up to take advantage of array processing functions! ,{$group: {_id: "$sym", prx: {$push: {v:"$val",d:"$date"}} }} // Nice additional info. Note use of dot notation on array to get // just scalar date at elem 0, not the object {v:val,d:date}: ,{$addFields: {numDays: days, startDate: {$arrayElemAt: [ "$prx.d", 0 ]}} } // The Juice! Assume we have a variable "days" which is the desired number // of days of moving average. // The complex expression below does this in python pseudocode: // // for z in range(0, size of value vector - # of days in moving avg): // seg = vector[n:n+days] // values = seg.v // dates = seg.d // for v in seg: // tot += v // avg = tot/len(seg) // // Note that it is possible to overrun the segment at the end of the "walk" // along the vector, i.e. not enough date-values. So we only run the // vector to (len(vector) - (days-1). // Also, for extra info, we also add the number of days *actually* used in the // calculation AND the as-of date which is the tail date of the segment! // // Again we take advantage of dot notation to turn the vector of // object {v:val, d:date} into two vectors of simple scalars [v1,v2,...] // and [d1,d2,...] with $prx.v and $prx.d // ,{$addFields: {"prx": {$map: { input: {$range:[0,{$subtract:[{$size:"$prx"}, (days-1)]}]} , as: "z", in: { avg: {$avg: {$slice: [ "$prx.v", "$$z", days ] } }, d: {$arrayElemAt: [ "$prx.d", {$add: ["$$z", (days-1)] } ]} } }} }} ]);
이것은 다음과 같은 출력을 생성 할 수 있습니다 :
{ "_id" : "S1", "prx" : [ { "avg" : 11.738793632512115, "d" : ISODate("2018-09-05T16:10:30.259Z") }, { "avg" : 12.420766702631376, "d" : ISODate("2018-09-06T16:10:30.259Z") }, ... ], "numDays" : 4, "startDate" : ISODate("2018-09-02T16:10:30.259Z") }
-
==============================
2.내가 MongoDB의에서이 작업을 수행하는 경향이 방법은 예를 들어, 매일의 가치에 대한 문서에서 지난 90 일 실행 합계를 유지하다
내가 MongoDB의에서이 작업을 수행하는 경향이 방법은 예를 들어, 매일의 가치에 대한 문서에서 지난 90 일 실행 합계를 유지하다
{"day": 1, "tempMax": 40, "tempMaxSum90": 2232} {"day": 2, "tempMax": 38, "tempMaxSum90": 2230} {"day": 3, "tempMax": 36, "tempMaxSum90": 2231} {"day": 4, "tempMax": 37, "tempMaxSum90": 2233}
새로운 데이터 포인트 대신 읽고 효율적이 간단한 쿼리, 하나 또한이 (사이비 코드)와 같은 하나의 뺄셈으로 다음 합계를 계산할 수 (90 개) 값을 합산의 컬렉션에 추가해야 할 때마다 :
tempMaxSum90(day) = tempMaxSum90(day-1) + tempMax(day) - tempMax(day-90)
매일 다음 인에 대한 90 일 이동 평균은 90 일의 합은 90로 나눈 값.
당신은 또한 다른 이상 이동 평균을 제공하고 싶었 시간 규모 (예 : 일주, 삼십일 90 일, 1 년) 단순히 때마다하는 대신 하나의 합의 각 문서와 금액의 배열, 하나의 합을 유지할 수 -scale이 필요합니다.
그러나이 접근법은 새로운 데이터를 비교적 느리게 수집되는 빠른 검색이 바람직한 시나리오 차트 가장 시계열에 적합한 추가 저장 용량과 새로운 데이터를 삽입하기위한 추가 처리를 요한다.
-
==============================
3.나는 적어도 몇 가지 심각한 체조하지 않고이 작업을 수행 할 수 있으며, 통합 프레임 워크는 현재 버전 (2.6)에 여러 날짜에 대해이 작업을 수행 할 수 있다고 생각하거나하지 않습니다. 그 이유는 어떻게 든 관련 정보의 이전 3 개월의 가치를 포함하는 각 일에 대한 문서를 작성하는 것이 필요하다, 그래서 집계 파이프 라인은 한 번에 하나 개의 문서 만 하나의 문서를 처리하는 것입니다. 이것은 이전의 단계는 $ 그룹에 사용 할 수있는 몇 가지 구별 키와 매일의 기록 (90 개) 사본에 대한 생산 것을 의미 평균을 계산합니다 달러 (A $) 조별로 될 것입니다.
나는 적어도 몇 가지 심각한 체조하지 않고이 작업을 수행 할 수 있으며, 통합 프레임 워크는 현재 버전 (2.6)에 여러 날짜에 대해이 작업을 수행 할 수 있다고 생각하거나하지 않습니다. 그 이유는 어떻게 든 관련 정보의 이전 3 개월의 가치를 포함하는 각 일에 대한 문서를 작성하는 것이 필요하다, 그래서 집계 파이프 라인은 한 번에 하나 개의 문서 만 하나의 문서를 처리하는 것입니다. 이것은 이전의 단계는 $ 그룹에 사용 할 수있는 몇 가지 구별 키와 매일의 기록 (90 개) 사본에 대한 생산 것을 의미 평균을 계산합니다 달러 (A $) 조별로 될 것입니다.
그래서 하나의 집계에 한 번에 두 개 이상의 날짜에 대해이 작업을 수행 할 수있는 방법을 볼 수 없습니다. 나는 그래서 실제 아니다 복잡하더라도, 잘못하고 / 편집해야 할 누군가가 그것을 할 수있는 방법을 발견하면이 답변을 제거 드리겠습니다. PostgreSQL의 파티션 유형의 기능은 여기에 일을 할 것입니다; 어쩌면 그 기능은 언젠가 추가됩니다.
-
==============================
4.나는 내 자신의 질문에 대한 답이있을 수 있습니다 생각합니다. 그것을 할 것입니다 줄지도. 먼저 사용되는 발광 다음 각 배열을 평균 할 줄 사용이로 평균되어야한다 그것의 이웃에 각 문서를지도로 ... 그리고 그것의 ID가 새로운 날짜 간격이 될 것이기 때문에 평균의 새로운 배열은 이동 평균 플롯 초과 근무해야한다 당신은에 대한 관심
나는 내 자신의 질문에 대한 답이있을 수 있습니다 생각합니다. 그것을 할 것입니다 줄지도. 먼저 사용되는 발광 다음 각 배열을 평균 할 줄 사용이로 평균되어야한다 그것의 이웃에 각 문서를지도로 ... 그리고 그것의 ID가 새로운 날짜 간격이 될 것이기 때문에 평균의 새로운 배열은 이동 평균 플롯 초과 근무해야한다 당신은에 대한 관심
나는 더 나은지도-감소 이해하는 데 필요한 것 같아요 ...
:)
예를 들어 ... 우리가 메모리에하고 싶었던 경우 (나중에 우리가 컬렉션을 만들 수 있습니다)
GIST https://gist.github.com/mrgcohen/3f67c597a397132c46f7
표정의 권리를합니까?
-
==============================
5.허용 대답은 나에게 도움이 있지만, 내가 그것을 어떻게 작동하는지 이해하는 렸어요 그리고 내가 밖으로 도움이 다른 사람에게 내 방법을 설명 거라고 생각 때문에. 특히 당신의 상황에 내 대답은 도움이 될 것입니다 생각
허용 대답은 나에게 도움이 있지만, 내가 그것을 어떻게 작동하는지 이해하는 렸어요 그리고 내가 밖으로 도움이 다른 사람에게 내 방법을 설명 거라고 생각 때문에. 특히 당신의 상황에 내 대답은 도움이 될 것입니다 생각
이상적으로 작은 데이터 세트에이 작품
첫번째 그룹 하루 데이터는 각각의 하루 어레이의 모든 추가 일 :
{ "$sort": { "Date": -1 } }, { "$group": { "_id": { "Day": "$Date", "Temperature": "$Temperature" }, "Previous Values": { "$push": { "Date": "$Date", "Temperature": "$Temperature" } } }
이 모습은 다음과 같이 (올바르게 정렬됩니다)하는 기록 당신을 떠날 것이다 :
{"_id.Day": "2017-02-01", "Temperature": 40, "Previous Values": [ {"Day": "2017-03-01", "Temperature": 20}, {"Day": "2017-02-11", "Temperature": 22}, {"Day": "2017-01-18", "Temperature": 03}, ... ]},
이제 매일이 추가 모든 일을 가지고, 우리는 이동 평균이 찾고 뒤로 한,이 _id.Day 필드보다 최신 이전 값 배열에서 항목을 제거해야합니다 :
{ "$project": { "_id": 0, "Date": "$_id.Date", "Temperature": "$_id.Temperature", "Previous Values": 1 } }, { "$project": { "_id": 0, "Date": 1, "Temperature": 1, "Previous Values": { "$filter": { "input": "$Previous Values", "as": "pv", "cond": { "$lte": ["$$pv.Date", "$Date"] } } } } },
이전 값의 배열의 각 항목은보다 작거나 각 레코드의 날짜에 동일 날짜를 포함합니다 :
{"Day": "2017-02-01", "Temperature": 40, "Previous Values": [ {"Day": "2017-01-31", "Temperature": 33}, {"Day": "2017-01-30", "Temperature": 36}, {"Day": "2017-01-29", "Temperature": 33}, {"Day": "2017-01-28", "Temperature": 32}, ... ]}
데이터가 하루이기 때문에 우리는 배열의 첫 번째 (7 개) 기록을 거라고 주 동안 이제 우리는, 우리의 평균 창 크기를 선택할 수 있습니다; 월에, 30; 또는 3 월 90 일 :
{ "$project": { "_id": 0, "Date": 1, "Temperature": 1, "Previous Values": { "$slice": ["$Previous Values", 0, 90] } } },
이전의 온도를 평균하기 위해 우리는 날짜 필드에서 다음 그룹을 이전 값의 배열을 긴장. 언 와인드 작업이 수행 :
{"Day": "2017-02-01", "Temperature": 40, "Previous Values": { "Day": "2017-01-31", "Temperature": 33} }, {"Day": "2017-02-01", "Temperature": 40, "Previous Values": { "Day": "2017-01-30", "Temperature": 36} }, {"Day": "2017-02-01", "Temperature": 40, "Previous Values": { "Day": "2017-01-29", "Temperature": 33} }, ...
오늘 필드가 동일하다고 볼 수 있지만, 우리는 지금 이전 값 배열에서 이전 날짜의 각각에 대한 문서가 있습니다. 이제 우리는 하루에 그룹 다시 후 평균 이전 Values.Temperature은 이동 평균을 얻을 수 있습니다 :
{"$group": { "_id": { "Day": "$Date", "Temperature": "$Temperature" }, "3 Month Moving Average": { "$avg": "$Previous Values.Temperature" } } }
즉입니다! 나는 모든 레코드에 모든 레코드에 합류하는 것은 적합하지 않습니다 것을 알고 있지만,이 작은 데이터 세트에서 잘 작동합니다
from https://stackoverflow.com/questions/25151042/moving-averages-with-mongodbs-aggregation-framework by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] JSON에 BSON 유형 ObjectId가 변환 (MongoDB의에서 보관) -Java (0) | 2019.12.27 |
---|---|
[MONGODB] 어떻게 MongoDB를 함께 배열의 순서를 변경하려면? (0) | 2019.12.26 |
[MONGODB] MongoDB를 집계하여 문자열의 배열을 반환하는 방법 (0) | 2019.12.26 |
[MONGODB] 몽구스의 최대 값을 얻을 (0) | 2019.12.26 |
[MONGODB] MongoDB를 찾을 () 및 findOne () 메소드는 다른 결과를 도시 (0) | 2019.12.26 |