How to filter documents in $match by the last 36 months in MongoDB aggregation

被刻印的时光 ゝ 提交于 2020-01-16 09:06:11

问题


I want to only obtain documents where this specific field "EffectiveDate" is greater than 36 months ago. I have tried:

"$match" : 
{"member.MemberEnrollmentSpans.MemberEnrollmentSpan.EffectiveDate": {$gte: 
ObjectID.createFromTime(Date.now() - 36*31*24*60*60)}}

But It doesn't seem to like the 'ObjectID.createFromTime' statement, it say my error is at the 'O' position, "Unexpected Character 'O'"

Does $match operator not recognize this or is my syntax wrong ?

var date = new Date();
(date.setMonth(date.getMonth() - 36));
var dateInput = date.toLocaleDateString();


db.getCollection("Members").aggregate(
    [
        { 
            "$match" : {
                "member.MemberInfo.BusinessUnitCode" : "20"
             }
        }, 
        { 
            "$match": { $expr: { $lt: [{ $toDate: dateInput }, 
"$member.MemberEnrollmentSpans.MemberEnrollmentSpan.EndDate"] } } 
        }, 
        { 
            "$unwind" : {
                "path" : 
"$member.MemberEnrollmentSpans.MemberEnrollmentSpan", 
            "preserveNullAndEmptyArrays" : false
            }
        }, 
        { 
            "$project" : {
            "EffDate" : "$member.MemberEnrollmentSpans.MemberEnrollmentSpan.EffectiveDate", 
            "PlanProduct" : "$member.MemberEnrollmentSpans.MemberEnrollmentSpan.PlanProduct", 
            "PlanProductCode" : "$member.MemberEnrollmentSpans.MemberEnrollmentSpan.PlanProductCode", 
            "BenefitPackage" : "$member.MemberEnrollmentSpans.MemberEnrollmentSpan.BenefitPackage", 
            "EndDate" : "$member.MemberEnrollmentSpans.MemberEnrollmentSpan.EndDate"
        }
    }, 
    { 
        "$group" : {
            "_id" : "$_id", 
            "items" : {
                "$addToSet" : {
                    "EffDate" : "$EffDate", 
                    "PlanProductCode" : "$PlanProductCode", 
                    "PlanProduct" : "$PlanProduct", 
                    "BenefitPackage" : "$BenefitPackage", 
                    "EndDate" : "$EndDate"
                }
            }
        }
    }
], 
{ 
    "allowDiskUse" : true
}

);


回答1:


Try this :

In your code :

let date = new Date();
(date.setMonth(date.getMonth() - 36));
let dateInput = date.toLocaleDateString(); // 1/10/2017

Query 1 :

db.yourCollectionName.aggregate([{ $match: { $expr: { $lt: [{ $toDate: dateInput }, "$date"] } } }])

Collection Data :

/* 1 */
{
    "_id" : ObjectId("5e17a6a5627ef7823644a088"),
    "date" : ISODate("2015-08-01T00:00:00.000Z")
}

/* 2 */
{
    "_id" : ObjectId("5e17a6ac627ef7823644a13f"),
    "date" : ISODate("2016-08-01T00:00:00.000Z")
}

/* 3 */
{
    "_id" : ObjectId("5e17a6c0627ef7823644a2d6"),
    "date" : ISODate("2019-12-01T00:00:00.000Z")
}

Result :

/* 1 */
{
    "_id" : ObjectId("5e17a6c0627ef7823644a2d6"),
    "date" : ISODate("2019-12-01T00:00:00.000Z")
}

(Or) as from here getOlderRecordsByMins, you can do this, both would get you same results but getting 36 months to this number 94608103680 is a bit hard, both of these queries are simple & fast enough with less operators being used - but if you think getting 94608103680 through code is easier then this go ahead with this :

Query 2 :

db.yourCollectionName.aggregate([
    { $match: { date: { $gt: new Date(ISODate().getTime() - 94608103680) } } }])



回答2:


I take the approach that 36 months is 3 years. So, the aggregate queries can be one of these:

db.test.aggregate( [
  { 
      $match: { 
          EffectiveDate: { $gt: new Date(new Date().setFullYear(new Date().getFullYear() - 3 ) ) } 
      } 
  }
] )

db.test.aggregate( [
  { 
      $match: { 
          $expr: {
              $gt: [
                  "$EffectiveDate",
                 { $dateFromParts: { 
                        year : { $subtract: [ { $year: ISODate() }, 3 ] } , 
                        month : { $month: ISODate() }, 
                        day: { $dayOfMonth: ISODate() }  
                 } }
              ]
          }
      } 
  }
] )

With the following input documents:

{ "EffectiveDate" : ISODate("2016-12-10T03:42:26.751Z") }
{ "EffectiveDate" : ISODate("2020-01-05T03:42:26.751Z") }
{ "EffectiveDate" : ISODate("2017-08-10T03:42:26.751Z") }
{ "EffectiveDate" : ISODate("2017-01-09T03:42:26.751Z") }
{ "EffectiveDate" : ISODate("2018-05-30T03:42:26.751Z") }

these will be returned:

{ "EffectiveDate" : ISODate("2020-01-05T03:42:26.751Z") }
{ "EffectiveDate" : ISODate("2017-08-10T03:42:26.751Z") }
{ "EffectiveDate" : ISODate("2018-05-30T03:42:26.751Z") }


来源:https://stackoverflow.com/questions/59672412/how-to-filter-documents-in-match-by-the-last-36-months-in-mongodb-aggregation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!