[MONGODB] 기록에 날짜 누락 기입
MONGODB기록에 날짜 누락 기입
나는 ProductViews의 컬렉션이 있습니다.
ProductView의
{
productId: '5b8c0f3204a10228b00a1745,
createdAt: '2018-09-07T17:18:40.759Z',
}
그리고 특정 제품의 일일 조회수를 가져 오는에 대한 쿼리를 가지고있다.
질문
ProductView.aggregate([
{ $match: { productId } },
{ $project: { day: { $substr: ["$createdAt", 0, 10] } } },
{
$group: {
_id: "$day",
count: { $sum: 1 },
time: { $avg: "$createdAt" },
}
},
{ $sort: { _id: 1 } },
{
$project: {
date: '$_id',
views: '$count',
},
},
]).exec((err, result) => ...)
현재 결과
[
{ date: '2018-09-01', views: 1 },
{ date: '2018-09-02', views: 3 },
{ date: '2018-09-04', views: 2 },
{ date: '2018-09-05', views: 5 },
// ...
]
발행물
문제는이 집계는 반환하지 않습니다이다 {날짜 : '2018년 9월 3일', 조회 : 0} 0 전망 일. 데이터의 표시 잘못된 이러한 결과 :
결과는 같아야합니다
[
{ date: '2018-09-01', views: 1 },
{ date: '2018-09-02', views: 3 },
{ date: '2018-09-03', views: 0 },
{ date: '2018-09-04', views: 2 },
{ date: '2018-09-05', views: 5 },
// ...
]
P.S은 :이 범위에 따라 출력 결과에 대한 시작 및 종료 날짜에 통과 할 완벽한 것
해결법
-
==============================
1.당신은 기본 값을 반환하는 몇 가지 추가 단계가 필요합니다. 우선 당신은 하나 개의 문서에있는 모든 결과를 수집하는 null로 _id 세트 $ 그룹을 사용해야합니다. 그럼 당신은 입력으로 일의 배열 $지도를 사용할 수 있습니다. 그 $ 내부 당신이 그 날짜가 현재 결과 집합에 존재하는지 찾기 위해 $ indexOfArray을 사용할 수 있습니다 매핑합니다. 예라면 (인덱스! = -1) 당신은 그렇지 않으면 당신은 그런 다음에 중첩 된 통계를 촉진하기 위해 문서 및 $ replaceRoot의 목록을 다시 얻을 $ 언 와인드을 사용할 수 있습니다 0으로 설정 전망의 기본 하위 문서를 반환해야, 그 값을 반환 할 수 있습니다 최고 수준입니다.
당신은 기본 값을 반환하는 몇 가지 추가 단계가 필요합니다. 우선 당신은 하나 개의 문서에있는 모든 결과를 수집하는 null로 _id 세트 $ 그룹을 사용해야합니다. 그럼 당신은 입력으로 일의 배열 $지도를 사용할 수 있습니다. 그 $ 내부 당신이 그 날짜가 현재 결과 집합에 존재하는지 찾기 위해 $ indexOfArray을 사용할 수 있습니다 매핑합니다. 예라면 (인덱스! = -1) 당신은 그렇지 않으면 당신은 그런 다음에 중첩 된 통계를 촉진하기 위해 문서 및 $ replaceRoot의 목록을 다시 얻을 $ 언 와인드을 사용할 수 있습니다 0으로 설정 전망의 기본 하위 문서를 반환해야, 그 값을 반환 할 수 있습니다 최고 수준입니다.
ProductView.aggregate([ { $match: { productId: '5b8c0f3204a10228b00a1745' } }, { $project: { day: { $substr: ["$createdAt", 0, 10] } } }, { $group: { _id: "$day", count: { $sum: 1 }, time: { $avg: "$createdAt" }, } }, { $sort: { _id: 1 } }, { $project: { date: '$_id', views: '$count', }, }, { $group: { _id: null, stats: { $push: "$$ROOT" } } }, { $project: { stats: { $map: { input: [ "2018-09-01", "2018-09-02", "2018-09-03", "2018-09-04", "2018-09-05" ], as: "date", in: { $let: { vars: { dateIndex: { "$indexOfArray": [ "$stats._id", "$$date" ] } }, in: { $cond: { if: { $ne: [ "$$dateIndex", -1 ] }, then: { $arrayElemAt: [ "$stats", "$$dateIndex" ] }, else: { _id: "$$date", date: "$$date", views: 0 } } } } } } } } }, { $unwind: "$stats" }, { $replaceRoot: { newRoot: "$stats" } } ]).exec((err, result) => ...)
당신은 간단한 루프를 사용하여 응용 프로그램 논리의 날짜의 정적 목록을 생성 할 수 있습니다. 나는 잘 ($ 범위를 사용)하지만이 집계 파이프 라인을 복잡 하듯이 그 MongoDB가 가능하다고 믿습니다. 내가 그와 당신이 경우에있는 거 잘 알거나하여 MongoDB의 날짜의 배열을 생성하려고 시도하자.
-
==============================
2.귀하의 질문은 2014 년 게시 유사합니다.
귀하의 질문은 2014 년 게시 유사합니다.
해당 게시물에서 제공되는 모든 답변은 유효하며 당신이 당신의 응용 프로그램 코드에없는 일을 생성 할 수있는 경우가 훨씬 더 간단 할 것이다.
당신이 MongoDB의 솔루션을 요구하고 많은 2014로 변경되었습니다 때문에 나는 당신이 3.6 버전으로 사용할 수있는 새로운 통합 파이프 라인을 만들었습니다.
ProductView.aggregate([ -- convert the string date into date type for date calcualtions. can avoid this step if you can store the date as date type in collection {"$addFields":{"createdAt":{"$dateFromString":{"dateString":"$createdAt"}}}}, -- strip the time part so we can add whole milliseconds from epoch to calculate next day {"$project":{ "day":{"$dateFromParts":{"year":{"$year":"$createdAt"},"month":{"$month":"$createdAt"},"day":{"$dayOfMonth":"$createdAt"}}} }}, -- generate two sets of data, one that has count by day, other that has unique days, min day and max day {"$facet":{ "daycounts":[{"$group":{"_id":"$day","count":{"$sum":1}}}], "maxmindays":[ {"$group":{ "_id":null, "days":{"$addToSet":"$day"}, "minday":{"$min":{"$divide":[{"$subtract":["$day",new Date("1-1-1970")]},1000]}}, "maxday":{"$max":{"$divide":[{"$subtract":["$day",new Date("1-1-1970")]},1000]}} }} ] }}, {"$project":{ "data":{ "$let":{ "vars":{"maxminday":{"$arrayElemAt":["$maxmindays",0]}}, "in":{ -- $range - iterate from min date to max date one day at a time "$map":{ "input":{"$range":["$$maxminday.minday",{"$add": ["$$maxminday.maxday", 60*60*24]},60*60*24]}, "as":"r", "in": { -- convert back to milliseconds to get the day "$let":{ "vars":{"current":{"$add": [new Date(0), {"$multiply":["$$r", 1000 ]}]}}, "in":{ -- check if the day is in the collection, if yes lookup view inside the daycount facet to get the matching count, else set the view to zero "$cond":[ {"$in":["$$current","$$maxminday.days"]}, { "date":{"$substr":["$$current",0,10]}, "views":{"$let":{"vars":{"daycount":{"$arrayElemAt":["$daycounts",{"$indexOfArray":["$daycounts._id","$$current"]}]}},"in":"$$daycount.count"}} }, {"date":{"$substr":["$$current",0,10]},"views":0} ] } } } } } } } }}, -- flatten the array of data {"$unwind":"$data"}, -- promote the data to top {"$replaceRoot":{newRoot:"$data"}} ])
-
==============================
3.일부 자바 스크립트와 통합 트릭.
일부 자바 스크립트와 통합 트릭.
먼저 제공된 날짜 범위 사이의 날짜를 찾을 필요가있다.
function getDates(startDate, stopDate) { var dateArray = [] var currentDate = moment(startDate) var stopDate = moment(stopDate) while (currentDate <= stopDate) { dateArray.push(moment(currentDate).format('YYYY-MM-DD')) currentDate = moment(currentDate).add(1, 'days') } return dateArray } const dummyArray = getDates('2018-09-01', '2018-09-05') dummyArray = [ "2018-09-01", "2018-09-02", "2018-09-03", "2018-09-04", "2018-09-05" ]
이제와 데이터베이스에서 사용할 수없는 날짜를 찾을 수 있습니다 집계 아래.
db.collection.aggregate([ { "$match": { productId } }, { "$group": { "_id": { "$substr": ["$createdAt", 0, 10] }, "count": { "$sum": 1 }, "time": { "$avg": "$createdAt" }, }}, { "$sort": { "_id": 1 } }, { "$project": { "date": "$_id", "views": "$count" }}, { "$group": { "_id": null, "data": { "$push": "$$ROOT" }}}, { "$project": { "data": { "$map": { "input": dummyArray, "in": { "k": "$$this", "v": { "$cond": [{ "$in": ["$$this", "$data.date" ] }, 1, 0 ] } } } } }}, { "$unwind": "$data" }, { "$group": { "_id": "$data.k", "count": { "$sum": "$data.v" }}} ])
및 출력 할 것이다
[ { date: '2018-09-01', views: 1 }, { date: '2018-09-02', views: 3 }, { date: '2018-09-03', views: 0 }, { date: '2018-09-04', views: 2 }, { date: '2018-09-05', views: 5 } ]
-
==============================
4.나는 그것이 하나 또는 두 개의 그리고 프로세스 문서의 수가 적을 경우 누락 된 날짜 클라이언트 측을 추가 건의 할 것입니다.
나는 그것이 하나 또는 두 개의 그리고 프로세스 문서의 수가 적을 경우 누락 된 날짜 클라이언트 측을 추가 건의 할 것입니다.
그 존재는 다음과 같은 파이프 라인은 MongoDB를 4.0 이상에서 작동하지만 약간의 노력으로, 우리가 3.6에서 작동 할 수 있습니다 말했다.
[ { $group: { _id: null, dates: { $push: { $let: { vars: { date: { $dateToParts: { date: { $toDate: "$createdAt" } } } }, in: { $toDouble: { $dateFromParts: { year: "$$date.year", month: "$$date.month", day: "$$date.day" } } } } } } } }, { $addFields: { startDate: { $divide: [ { $min: "$dates" }, 1000 ] }, endDate: { $divide: [ { "$max": "$dates" }, 1000 ] } } }, { $addFields: { dates: { $map: { input: { $concatArrays: [ "$dates", { $setDifference: [ { $map: { input: { $range: [ { $toDouble: "$startDate" }, { $toDouble: "$endDate" }, 24*60*60 ] }, in: { $multiply: [ "$$this", 1000 ] } } }, "$dates" ] } ] }, in: { $toDate: "$$this" } } } } }, { "$unwind": "$dates" }, { "$group": { _id: "$dates", views: { $sum: 1 } } }, { "$sort": { _id: -1 } } ]
from https://stackoverflow.com/questions/52235027/fill-missing-dates-in-records by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 노드 - 몽구스 3.6 - 인구 필드 정렬 쿼리 (0) | 2019.12.25 |
---|---|
[MONGODB] 어떻게 즉시 데이터베이스 / 컬렉션을 만들 MongoDB를 수행 (0) | 2019.12.25 |
[MONGODB] MongoDB를에서, 사용자를 포함, 각 대화의 마지막 메시지 목록 (0) | 2019.12.25 |
[MONGODB] 봄의 데이터 몽고에서 MongoDB를의 $ 조회 (0) | 2019.12.25 |
[MONGODB] 몽고 스크립트에 환경 변수를 전달하는 방법 (0) | 2019.12.25 |