[MONGODB] 매일 그룹 내에서 MongoDB를 집계 [중복]
MONGODB매일 그룹 내에서 MongoDB를 집계 [중복]
내가 이렇게 보이는 몽고에서 일부 문서를 가지고 :
{
_id : ObjectId("..."),
"make" : "Nissan",
..
},
{
_id : ObjectId("..."),
"make" : "Nissan",
"saleDate" : ISODate("2013-04-10T12:39:50.676Z"),
..
}
이상적으로, 내가 셀 수 있도록하고 싶습니다, 메이크업에 의해, 차량의 수는 하루에 판매했다. 그때처럼은 지난 7 일을 통해 같은 오늘로 하나 오늘, 또는 창을 볼 것입니다.
나는 못생긴 코드로 매일보기를 달성 할 수 있었다
db.inventory.aggregate(
{ $match : { "saleDate" : { $gte: ISODate("2013-04-10T00:00:00.000Z"), $lt: ISODate("2013-04-11T00:00:00.000Z") } } } ,
{ $group : { _id : { make : "$make", saleDayOfMonth : { $dayOfMonth : "$saleDate" } }, cnt : { $sum : 1 } } }
)
어느 다음 결과를 얻을 수
{
"result" : [
{
"_id" : {
"make" : "Nissan",
"saleDayOfMonth" : 10
},
"cnt" : 2
},
{
"_id" : {
"make" : "Toyota",
"saleDayOfMonth" : 10
},
"cnt" : 4
},
],
"ok" : 1
}
그 괜찮 그래서,하지만 난 많은 쿼리에서 두 날짜 값을 변경할 필요가 없습니다 선호하는 것입니다. 제가 위에서 언급 한 바와 같이 다음, 나는 마지막 주에 하루 비닝 같은 결과를 볼 (그 때마다 수정할 필요없이, 다시)이 쿼리를 실행할 수 있도록하고 싶습니다.
아, 그리고 여기에 내가 쿼리를 위해 사용했던 샘플 데이터입니다
db.inventory.save({"make" : "Nissan","saleDate" : ISODate("2013-04-10T12:39:50.676Z")});
db.inventory.save({"make" : "Nissan"});
db.inventory.save({"make" : "Nissan","saleDate" : ISODate("2013-04-10T11:39:50.676Z")});
db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-09T11:39:50.676Z")});
db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:38:50.676Z")});
db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:37:50.676Z")});
db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:36:50.676Z")});
db.inventory.save({"make" : "Toyota","saleDate" : ISODate("2013-04-10T11:35:50.676Z")});
미리 감사드립니다, 케빈
해결법
-
==============================
1.$ dateToString 하루가 그룹에 사용하고 단순히 결과에 "YYYY-MM-DD"가 될 수있다 : 몽고 2.8 RC2에서 새 데이터 집합 연산자가있다 :
$ dateToString 하루가 그룹에 사용하고 단순히 결과에 "YYYY-MM-DD"가 될 수있다 : 몽고 2.8 RC2에서 새 데이터 집합 연산자가있다 :
문서에서 예제 :
db.sales.aggregate( [ { $project: { yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }, time: { $dateToString: { format: "%H:%M:%S:%L", date: "$date" } } } } ] )
에서 발생합니다 :
{ "_id" : 1, "yearMonthDay" : "2014-01-01", "time" : "08:15:39:736" }
-
==============================
2.날짜를 기반으로 UPDATE 업데이트 된 대답은 3.6뿐만 아니라 (광산을 포함한 모든 원래의 답변에 언급되지 않은) 판매가 없었다 범위의 날짜를 포함하는 방법을 보여주는에 있습니다.
날짜를 기반으로 UPDATE 업데이트 된 대답은 3.6뿐만 아니라 (광산을 포함한 모든 원래의 답변에 언급되지 않은) 판매가 없었다 범위의 날짜를 포함하는 방법을 보여주는에 있습니다.
샘플 데이터 :
db.inventory.find() { "_id" : ObjectId("5aca30eefa1585de22d7095f"), "make" : "Nissan", "saleDate" : ISODate("2013-04-10T12:39:50.676Z") } { "_id" : ObjectId("5aca30eefa1585de22d70960"), "make" : "Nissan" } { "_id" : ObjectId("5aca30effa1585de22d70961"), "make" : "Nissan", "saleDate" : ISODate("2013-04-10T11:39:50.676Z") } { "_id" : ObjectId("5aca30effa1585de22d70962"), "make" : "Toyota", "saleDate" : ISODate("2013-04-09T11:39:50.676Z") } { "_id" : ObjectId("5aca30effa1585de22d70963"), "make" : "Toyota", "saleDate" : ISODate("2013-04-10T11:38:50.676Z") } { "_id" : ObjectId("5aca30effa1585de22d70964"), "make" : "Toyota", "saleDate" : ISODate("2013-04-10T11:37:50.676Z") } { "_id" : ObjectId("5aca30effa1585de22d70965"), "make" : "Toyota", "saleDate" : ISODate("2013-04-10T11:36:50.676Z") } { "_id" : ObjectId("5aca30effa1585de22d70966"), "make" : "Toyota", "saleDate" : ISODate("2013-04-10T11:35:50.676Z") } { "_id" : ObjectId("5aca30f9fa1585de22d70967"), "make" : "Toyota", "saleDate" : ISODate("2013-04-11T11:35:50.676Z") } { "_id" : ObjectId("5aca30fffa1585de22d70968"), "make" : "Toyota", "saleDate" : ISODate("2013-04-13T11:35:50.676Z") } { "_id" : ObjectId("5aca3921fa1585de22d70969"), "make" : "Honda", "saleDate" : ISODate("2013-04-13T00:00:00Z") }
변수로의 startDate와 endDate가 정의 및 집계에서 그들을 사용 :
startDate = ISODate("2013-04-08T00:00:00Z"); endDate = ISODate("2013-04-15T00:00:00Z"); db.inventory.aggregate([ { $match : { "saleDate" : { $gte: startDate, $lt: endDate} } }, {$addFields:{ saleDate:{$dateFromParts:{ year:{$year:"$saleDate"}, month:{$month:"$saleDate"}, day:{$dayOfMonth:"$saleDate"} }}, dateRange:{$map:{ input:{$range:[0, {$subtract:[endDate,startDate]}, 1000*60*60*24]}, in:{$add:[startDate, "$$this"]} }} }}, {$unwind:"$dateRange"}, {$group:{ _id:"$dateRange", sales:{$push:{$cond:[ {$eq:["$dateRange","$saleDate"]}, {make:"$make",count:1}, {count:0} ]}} }}, {$sort:{_id:1}}, {$project:{ _id:0, saleDate:"$_id", totalSold:{$sum:"$sales.count"}, byBrand:{$arrayToObject:{$reduce:{ input: {$filter:{input:"$sales",cond:"$$this.count"}}, initialValue: {$map:{input:{$setUnion:["$sales.make"]}, in:{k:"$$this",v:0}}}, in:{$let:{ vars:{t:"$$this",v:"$$value"}, in:{$map:{ input:"$$v", in:{ k:"$$this.k", v:{$cond:[ {$eq:["$$this.k","$$t.make"]}, {$add:["$$this.v","$$t.count"]}, "$$this.v" ]} } }} }} }}} }} ])
샘플 데이터에이 결과를 제공합니다 :
{ "saleDate" : ISODate("2013-04-08T00:00:00Z"), "totalSold" : 0, "byBrand" : { } } { "saleDate" : ISODate("2013-04-09T00:00:00Z"), "totalSold" : 1, "byBrand" : { "Toyota" : 1 } } { "saleDate" : ISODate("2013-04-10T00:00:00Z"), "totalSold" : 6, "byBrand" : { "Nissan" : 2, "Toyota" : 4 } } { "saleDate" : ISODate("2013-04-11T00:00:00Z"), "totalSold" : 1, "byBrand" : { "Toyota" : 1 } } { "saleDate" : ISODate("2013-04-12T00:00:00Z"), "totalSold" : 0, "byBrand" : { } } { "saleDate" : ISODate("2013-04-13T00:00:00Z"), "totalSold" : 2, "byBrand" : { "Honda" : 1, "Toyota" : 1 } } { "saleDate" : ISODate("2013-04-14T00:00:00Z"), "totalSold" : 0, "byBrand" : { } }
이 집계는 또한 2 개 $ 그룹 스테이지 간단한 $ 프로젝트 대신 $ 그룹과 복잡한 $ 프로젝트를 수행 할 수 있습니다. 여기있어:
db.inventory.aggregate([ {$match : { "saleDate" : { $gte: startDate, $lt: endDate} } }, {$addFields:{saleDate:{$dateFromParts:{year:{$year:"$saleDate"}, month:{$month:"$saleDate"}, day:{$dayOfMonth : "$saleDate" }}},dateRange:{$map:{input:{$range:[0, {$subtract:[endDate,startDate]}, 1000*60*60*24]},in:{$add:[startDate, "$$this"]}}}}}, {$unwind:"$dateRange"}, {$group:{ _id:{date:"$dateRange",make:"$make"}, count:{$sum:{$cond:[{$eq:["$dateRange","$saleDate"]},1,0]}} }}, {$group:{ _id:"$_id.date", total:{$sum:"$count"}, byBrand:{$push:{k:"$_id.make",v:{$sum:"$count"}}} }}, {$sort:{_id:1}}, {$project:{ _id:0, saleDate:"$_id", totalSold:"$total", byBrand:{$arrayToObject:{$filter:{input:"$byBrand",cond:"$$this.v"}}} }} ])
같은 결과 :
{ "saleDate" : ISODate("2013-04-08T00:00:00Z"), "totalSold" : 0, "byBrand" : { "Honda" : 0, "Toyota" : 0, "Nissan" : 0 } } { "saleDate" : ISODate("2013-04-09T00:00:00Z"), "totalSold" : 1, "byBrand" : { "Honda" : 0, "Nissan" : 0, "Toyota" : 1 } } { "saleDate" : ISODate("2013-04-10T00:00:00Z"), "totalSold" : 6, "byBrand" : { "Honda" : 0, "Toyota" : 4, "Nissan" : 2 } } { "saleDate" : ISODate("2013-04-11T00:00:00Z"), "totalSold" : 1, "byBrand" : { "Toyota" : 1, "Honda" : 0, "Nissan" : 0 } } { "saleDate" : ISODate("2013-04-12T00:00:00Z"), "totalSold" : 0, "byBrand" : { "Toyota" : 0, "Nissan" : 0, "Honda" : 0 } } { "saleDate" : ISODate("2013-04-13T00:00:00Z"), "totalSold" : 2, "byBrand" : { "Honda" : 1, "Toyota" : 1, "Nissan" : 0 } } { "saleDate" : ISODate("2013-04-14T00:00:00Z"), "totalSold" : 0, "byBrand" : { "Toyota" : 0, "Honda" : 0, "Nissan" : 0 } }
2.6에 따라 원래 답변 :
현재 집계 프레임 워크의 다양한 날짜 조작을 처리하는 방법에 대한 내 블로그 항목을 살펴 할 수 있습니다.
당신이 할 수있는 것은 매일 해상도로 날짜를 절단 한 후 날짜와 메이크업에 의해 전체 데이터 집합 (또는 그것의 한 부분) 및 집계를 통해 집계를 실행하는 데 사용할 $ 프로젝트 단계입니다.
샘플 데이터와 함께, 당신은 당신이 날짜 올해, 메이크업에 의해 판매 얼마나 많은 차량을 알고 싶은 말 :
match={"$match" : { "saleDate" : { "$gt" : new Date(2013,0,1) } } }; proj1={"$project" : { "_id" : 0, "saleDate" : 1, "make" : 1, "h" : { "$hour" : "$saleDate" }, "m" : { "$minute" : "$saleDate" }, "s" : { "$second" : "$saleDate" }, "ml" : { "$millisecond" : "$saleDate" } } }; proj2={"$project" : { "_id" : 0, "make" : 1, "saleDate" : { "$subtract" : [ "$saleDate", { "$add" : [ "$ml", { "$multiply" : [ "$s", 1000 ] }, { "$multiply" : [ "$m", 60, 1000 ] }, { "$multiply" : [ "$h", 60, 60, 1000 ] } ] } ] } } }; group={"$group" : { "_id" : { "m" : "$make", "d" : "$saleDate" }, "count" : { "$sum" : 1 } } };
이제 집계를 실행하면이 있습니다 :
db.inventory.aggregate(match, proj1, proj2, group) { "result" : [ { "_id" : { "m" : "Toyota", "d" : ISODate("2013-04-10T00:00:00Z") }, "count" : 4 }, { "_id" : { "m" : "Toyota", "d" : ISODate("2013-04-09T00:00:00Z") }, "count" : 1 }, { "_id" : { "m" : "Nissan", "d" : ISODate("2013-04-10T00:00:00Z") }, "count" : 2 } ], "ok" : 1 }
당신은 꽤 출력까지 또 다른 {$ 프로젝트} 단계를 추가 할 수 있습니다 당신은 {$ 일종의} 단계를 추가 할 수 있지만 기본적으로 각 날짜에 대해, 각각의 메이크업을 위해 당신이 판매되었다 얼마나 많은 수를 얻을.
-
==============================
3.I user1083621의 답변을 좋아하지만 그 방법은이 분야에 작업을 다음 몇 가지 제한 사항이 발생합니다 - 당신은 (예를 들어) 다음 집계 파이프 라인 단계에서 날짜 필드로 사용할 수 있기 때문이다. 당신은 어느 쪽도 비교하거나 임의 날짜 집계 작업을 사용하여 집계 한 후 문자열을해야 할 수 있습니다 (!). 그 모두는 원래 날짜 필드를 투영함으로써 해결 될 수 있지만 그 경우에 당신은 단계를 groupping을 통해 그것을 유지에 어려움을 얻을 것이다. 그리고 결국, 때로는 그냥 임의의 일 시간이 하루의 시작으로 조작 할 수 있습니다. 그래서 여기 내 방법입니다 :
I user1083621의 답변을 좋아하지만 그 방법은이 분야에 작업을 다음 몇 가지 제한 사항이 발생합니다 - 당신은 (예를 들어) 다음 집계 파이프 라인 단계에서 날짜 필드로 사용할 수 있기 때문이다. 당신은 어느 쪽도 비교하거나 임의 날짜 집계 작업을 사용하여 집계 한 후 문자열을해야 할 수 있습니다 (!). 그 모두는 원래 날짜 필드를 투영함으로써 해결 될 수 있지만 그 경우에 당신은 단계를 groupping을 통해 그것을 유지에 어려움을 얻을 것이다. 그리고 결국, 때로는 그냥 임의의 일 시간이 하루의 시작으로 조작 할 수 있습니다. 그래서 여기 내 방법입니다 :
{'$project': { 'start_of_day': {'$subtract': [ '$date', {'$add': [ {'$multiply': [{'$hour': '$date'}, 3600000]}, {'$multiply': [{'$minute': '$date'}, 60000]}, {'$multiply': [{'$second': '$date'}, 1000]}, {'$millisecond': '$date'} ]} ]}, }}
그것은 당신이 제공 :
{ "start_of_day" : ISODate("2015-12-03T00:00:00.000Z") }, { "start_of_day" : ISODate("2015-12-04T00:00:00.000Z") }
빨리 user1083621의 방법보다 그 경우라고 할 수 없습니다.
from https://stackoverflow.com/questions/15938859/mongodb-aggregate-within-daily-grouping by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 몽구스의 스키마 변경 다루기 (0) | 2019.12.13 |
---|---|
[MONGODB] MongoDB를 : 대신 '_id'출력 'ID' (0) | 2019.12.13 |
[MONGODB] Node.js를에서 데이터베이스를 조롱? (0) | 2019.12.13 |
[MONGODB] 어떻게하여 MongoDB의 핵심 기반으로 중복을 제거하는 방법? (0) | 2019.12.13 |
[MONGODB] MongoDB를이 : errno를 : 127.0.0.1:27017 이유에 연결하지 못했습니다 10061 (0) | 2019.12.13 |