[MONGODB] MongoDB의 : 집계 프레임 워크 : 그룹화 ID 당 마지막 날짜가 문서를 가져 오기
MONGODBMongoDB의 : 집계 프레임 워크 : 그룹화 ID 당 마지막 날짜가 문서를 가져 오기
나는 다른 모든 필드와 각 국의 마지막 문서를 얻으려면 :
{
"_id" : ObjectId("535f5d074f075c37fff4cc74"),
"station" : "OR",
"t" : 86,
"dt" : ISODate("2014-04-29T08:02:57.165Z")
}
{
"_id" : ObjectId("535f5d114f075c37fff4cc75"),
"station" : "OR",
"t" : 82,
"dt" : ISODate("2014-04-29T08:02:57.165Z")
}
{
"_id" : ObjectId("535f5d364f075c37fff4cc76"),
"station" : "WA",
"t" : 79,
"dt" : ISODate("2014-04-29T08:02:57.165Z")
}
나는 역마다 최신 DT에 대한 t 및 스테이션이 필요합니다. 집계 프레임 워크 :
db.temperature.aggregate([{$sort:{"dt":1}},{$group:{"_id":"$station", result:{$last:"$dt"}, t:{$last:"$t"}}}])
보고
{
"result" : [
{
"_id" : "WA",
"result" : ISODate("2014-04-29T08:02:57.165Z"),
"t" : 79
},
{
"_id" : "OR",
"result" : ISODate("2014-04-29T08:02:57.165Z"),
"t" : 82
}
],
"ok" : 1
}
이 그렇게 할 수있는 가장 효율적인 방법이 있나요?
감사
해결법
-
==============================
1.직접 귀하의 질문에 대답하기 위해, 네, 그것은 가장 효율적인 방법입니다. 그러나 나는 우리가 왜 이렇게되는지를 명확히해야한다고 생각합니까.
직접 귀하의 질문에 대답하기 위해, 네, 그것은 가장 효율적인 방법입니다. 그러나 나는 우리가 왜 이렇게되는지를 명확히해야한다고 생각합니까.
AS는 한 가지 사람들이 $ 조별 리그와 당신이 없는지에 있음을 해보고 싶어요, 그래서 그들은는 "타임 스탬프"값이보고있는에 전달하기 전에 결과를 "정렬"되어보고있는 대안으로 제시되었다 "타임 스탬프"순서이므로 이에 형태 :
db.temperature.aggregate([ { "$sort": { "station": 1, "dt": -1 } }, { "$group": { "_id": "$station", "result": { "$first":"$dt"}, "t": {"$first":"$t"} }} ])
언급 한 바와 같이 그리고 당신은 물론 인덱스 순서대로 정렬 효율적으로 만들기 위해 반영 할 것입니다 :
그러나, 이것은 실제 지점입니다. 다른 사람들이 간과하고있는 것 같다 (그렇지 않으면 그렇게 자신을위한 것은)이 데이터의 모든 가능성이 추가로 각 측정 값이 기록되는 점에서, 시간 순서에 이미 삽입되고 있다는 점이다.
이의 아름다움이 (가) _id 필드가 이미 (a는 기본 ObjectId가와)입니다 그래서 그 자체를 수행으로 "타임 스탬프"순서는 실제로 시간 값을 포함하고이 가능한 성명을 :
db.temperature.aggregate([ { "$group": { "_id": "$station", "result": { "$last":"$dt"}, "t": {"$last":"$t"} }} ])
그리고 그것은 빠릅니다. 왜? 그럼 당신은 인덱스 (호출에 추가 코드) 당신은 또한 "로드"를 필요로하지 않는 문서에 추가하여 인덱스를 선택할 필요가 없습니다.
우리는 이미 문서가 순서대로 $ 마지막 경계를 완벽하게 유효 있도록 (_id가) 알고있다. 어쨌든 모든 것을 스캔, 두 날짜 사이에 동등하게 유효로 _id 값에 당신은 또한 할 수 있었다 "범위"쿼리된다.
여기에서 말할 수있는 유일한 것은 "현실 세계"의 사용에, 그냥 "첫 번째"와 "마지막"점점 반대로 축적 이런 종류의 일을 날짜 범위 사이에 $ 일치로 더 실용적 일 수 있다는 것입니다 _id 값이 "범위"또는 실제 사용에서 비슷한 정의합니다.
그렇다면 이것의 증거는 무엇입니까? 난 그냥 몇 가지 샘플 데이터를 생성하여 그렇게 잘 그것은 매우 쉽게 재현하는 것입니다 :
var stations = [ "AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY" ]; for ( i=0; i<200000; i++ ) { var station = stations[Math.floor(Math.random()*stations.length)]; var t = Math.floor(Math.random() * ( 96 - 50 + 1 )) +50; dt = new Date(); db.temperatures.insert({ station: station, t: t, dt: dt }); }
명령문의 각 양식을 실행하는 내 하드웨어에 (별, 그러나 확실하게 적절하지 spinny 디스크와 8 기가 바이트 노트북) 분명히 인덱스와 정렬 (정렬 문 같은 인덱스에 동일한 키)를 사용하여 버전과 주목할만한 일시 정지를 보여줍니다. 그것은 단지 작은 일시 정지하지만, 차이는 통지 충분히 중요하다.
심지어 $ 일종의 인해 인덱스의 존재에게 최적화되어 있지만 당신은 그 차이를 볼 수있는 설명 출력을보고 (버전 2.6까지, 또는 실제로 문서화 된 것은 아니지만 2.4.9에있다), 시간 촬영 이 나타납니다 다음 인덱스 항목을로드 인덱스 선택으로 할 수 있습니다. 는 "적용"인덱스 쿼리에 대한 모든 필드를 포함하면 차이가 없습니다.
또한, 기록, 순수 일자 색인만을 날짜 값 정렬에 동일한 결과를 제공한다. 아마도 약간 빠르게,하지만 여전히 느린 정렬하지 않고 자연 인덱스 형태보다.
그러니 당신이 행복 할 수있는 첫 번째와 마지막 _id 값에 대한 "범위"로, 다음은 삽입 순서에 자연 인덱스를 사용하여이 작업을 수행하는 가장 효율적인 방법은 실제로 사실이다. 귀하의 실제 주행이 당신 여부에 대한 실용적인 여부에 대한 다를 수 있으며 단순히 인덱스를 구현하기 위해 더 편리되는 및 날짜에 정렬 끝낼 수 있습니다.
하지만 연속 쿼리에서 해당 정보를 사실 저장소에 당신이 할 수있는 귀하의 결과와 함께 값을 얻을 사용하기 위해, 귀하의 질의에 아마도 한 팅겨 "마지막"_id보다 큰 _id 범위 또는를 사용하여 행복했다 경우 :
db.temperature.aggregate([ // Get documents "greater than" the "highest" _id value found last time { "$match": { "_id": { "$gt": ObjectId("536076603e70a99790b7845d") } }}, // Do the grouping with addition of the returned field { "$group": { "_id": "$station", "result": { "$last":"$dt"}, "t": {"$last":"$t"}, "lastDoc": { "$last": "$_id" } }} ])
당신이 실제로 있다면 그리고 그와 같은 결과가 다음 결과에서 ObjectId가의 최대 값을 결정하고 다음 쿼리에서 사용할 수 "에 다음과 같은".
어쨌든, 그 재미 재생을 가지고 있지만 다시 예, 쿼리가 가장 빠른 방법이라고이 경우이다.
-
==============================
2.인덱스는 당신이 정말로 필요로하는 모두이다 :
인덱스는 당신이 정말로 필요로하는 모두이다 :
db.temperature.ensureIndex({ 'station': 1, 'dt': 1 }) for s in db.temperature.distinct('station'): db.temperature.find({ station: s }).sort({ dt : -1 }).limit(1)
물론 구문은 실제로 당신의 언어에 대한 유효 무엇이든 사용.
편집 : 당신이 올바른지이 초래 스테이션 당 왕복, 그리고 그것의 큰 몇 스테이션, 그리고 당신은 여전히 역에 복합 인덱스를 원하는가 1000에 대한 좋은 + DT하지만, 그리고 걸릴하지 않도록 같은 루프 내림차순 정렬의 장점 :
db.temperature.aggregate([ { $sort: { station: 1, dt: -1 } }, { $group: { _id: "$station", result: {$first:"$dt"}, t: {$first:"$t"} } } ])
-
==============================
3.지금까지 집계 쿼리로 당신이 게시 한 것처럼, 나는 당신이 DT에 인덱스를 가지고 특정 만들 것입니다 :
지금까지 집계 쿼리로 당신이 게시 한 것처럼, 나는 당신이 DT에 인덱스를 가지고 특정 만들 것입니다 :
db.temperature.ensureIndex({'dt': 1 })
이 집계 파이프 라인의 시작 부분에 $ 정렬이 가능한 한 효율적이라고 특정 할 것이다.
이 루프의 쿼리 대,이 데이터를 얻을 수있는 가장 효율적인 방법입니다 여부에 관해서는, 가능성이 당신이 얼마나 많은 데이터 포인트의 기능이 될 것입니다. 아마도 "방송국의 수천"및 데이터 포인트의 수천 수백 초, 나는 집계 방식이 더 빠를 것이라고 생각 것입니다.
당신은 더 많은 데이터를 추가하지만, 문제는 집계 쿼리가 모든 문서를 계속해서 터치하는 것입니다. 당신이 수백만 이상의 문서까지 확장 이것은 점점 더 비싼 얻을 것이다. 이 경우에 대한 하나의 접근 방식은 일종의 문서의 총 개수가 고려되고 제한 할 권리 $ 후 $ 제한을 추가하는 것입니다. 즉 비트 해키 및 부정확입니다하지만 필요에 액세스 할 수 있다는 문서의 총 수를 제한하는 것이 도움이 될 것이다.
from https://stackoverflow.com/questions/23360551/mongodb-aggregation-framework-get-last-dated-document-per-grouping-id by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 때 MongoDB를 또는 다른 문서 지향 데이터베이스 시스템을 사용 하는가? [닫은] (0) | 2019.12.03 |
---|---|
[MONGODB] $ graphLookup에 대한 문자열에 ObjectId가 일치 (0) | 2019.12.03 |
[MONGODB] MongoDB를 통해 몽고 쉘에서 중첩 된 배열을 업데이트 [중복] (0) | 2019.12.03 |
[MONGODB] 몽구스 고유 색인 작동하지 않습니다! (0) | 2019.12.03 |
[MONGODB] MongoDB의 쿼리 여러 컬렉션을 한 번에 (0) | 2019.12.03 |