$match $sort data

Hello everyone.
I have, for example, 7 documents:

{  
"_id": {    "$oid": "1"  },
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 10, "day": 2  }
}
{  
"_id": {    "$oid": "2"  },
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 10, "day": 5  }
}
{  
"_id": {    "$oid": "3"  },
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 8, "day": 21  }
}
{  
"_id": {    "$oid": "4"  },
"firstName": "Danica",
"lastName": "Taylor", 
"birthday": { "month": 8, "day": 12  }
}
{  
"_id": {    "$oid": "5"  },
"firstName": "Daniel",
"lastName": "Johnson", 
"birthday": { "month": 6, "day": 14  }
}
{  
"_id": {    "$oid": "6"  },
"firstName": "Pamela",
"lastName": "Giesen", 
"birthday": { "month": 4, "day":22  }
}
{  
"_id": {    "$oid": "7"  },
"firstName": "Alicia",
"lastName": "Travis", 
"birthday": { "month": 2, "day": 18  }
}

I need to sort them by selected month and day, for example, “month”: 8 “day”: 12. The output should be:

{  
"_id": {    "$oid": "3"  },
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 8, "day": 21  }
}
{  
"_id": {    "$oid": "1"  },
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 10, "day": 2  }
}
{  
"_id": {    "$oid": "2"  },
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 10, "day": 5  }
}
{  
"_id": {    "$oid": "7"  },
"firstName": "Alicia",
"lastName": "Travis", 
"birthday": { "month": 2, "day": 18  }
}
{  
"_id": {    "$oid": "6"  },
"firstName": "Pamela",
"lastName": "Giesen", 
"birthday": { "month": 4, "day":22  }
}
{  
"_id": {    "$oid": "5"  },
"firstName": "Daniel",
"lastName": "Johnson", 
"birthday": { "month": 6, "day": 14  }
}

Is there a chance to do only in $match? I know how to filter them but only to the highest month. Thank you in advance, I am verry newbie in this.

Some clarifications are needed.

The document _id:4 which has month:8 day:12 is not in the output. Is that what you want?

Your sort in not clear. What I understand is that the months higher or equal to the specified to comes first and sorted and then then one lower that the specified to come after but also sorted.

What about the month equals but day lower than specified day. You removed month:8 day:12 from output, what about if you had month:8 day:11?

The document _id:4 which has month:8 day:12 I forgot to write him in an output. As you said if someone selects the 10th month and 3rd day in a month it should be sorted to the higher months till the 12th month after that should start from the 1st to 10th month and 2nd day in that month. Basically a circle. I need to list birthdays from the selected month and sort them from specified month this year to specified month next year. If someone selects the 8th month and 12th day in a month, it should sort customers this way:

{  
"_id": {"$oid": "4"},
"firstName": "Danica",
"lastName": "Taylor", 
"birthday": { "month": 8, "day": 12  }
}
{  
"_id": { "$oid": "3"},
"firstName": "Mie",
"lastName": "Ragnar", 
"birthday": { "month": 8, "day": 21  }
}
{  
"_id": {"$oid": "1"},
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 10, "day": 2  }
}
{  
"_id": {"$oid": "2"},
"firstName": "John",
"lastName": "Doe", 
"birthday": { "month": 10, "day": 5  }
}
{  
"_id": {"$oid": "7"},
"firstName": "Alicia",
"lastName": "Travis", 
"birthday": { "month": 2, "day": 18  }
}
{  
"_id": {"$oid": "6"},
"firstName": "Pamela",
"lastName": "Giesen", 
"birthday": { "month": 4, "day":22  }
}
{  
"_id": {"$oid": "5"},
"firstName": "Daniel",
"lastName": "Johnson", 
"birthday": { "month": 6, "day": 14  }
}
{  
"_id": {"$oid": "9"},
"firstName": "Brandan",
"lastName": "Kendall", 
"birthday": { "month": 8, "day": 5  }
}

I have been listed users but only to the 12th month (the highest number), I don`t know with $match and $sort how to do that. Thank you in advance.

I would try the following approach using the aggregation framework.

I would set a new field passed_birthday to 1 to all birthday that comes before the specified month and day and would set it to 0 to the others.

I would then sort using passed_birthday:1,birthday.month:1,birthday.day:1. Documents with passed_birthday 0 will be listed first ordered by month and day and documents with passed_birthday 1 will be listed after.

Untested first draft

specified_month = 8
specified_day = 12
set__passed_birthday = { "$set" : {
  "birthday_passed" : { "$cond" : {
    "if" : { "$or": [
         { "$lt" : [ "$birthday.month" , specified_month ] } ,
         { "$and" : [
           { "$eq" : [ "$birthday.month" , specified_month ] } ,
           { "$lt" : [ "$birthday.day" , specified_day ] }
         ] }
      ] }
    "then" : 1
    "else" : 0 } }
}}

sort_stage = { "$sort" : {
  "passed_birthdat" : 1 ,
  "birthday.month" : 1 ,
  "birthday.day" : 1
} }

pipeline = [ set__passed_birthday , sort_stage ]

collection.aggregate( pipeline )

Modified version following testing:

specified_month = 8

specified_day = 12

// I had passed_birthday, birthday_passed and other misspelling so I renamed it
// to __passed

// Some missing , after the 'if:' and 'then:'

set_stage = { "$set" : {
  "__passed" : { "$cond" : {
    "if" : { "$or": [
         { "$lt" : [ "$birthday.month" , specified_month ] } ,
         { "$and" : [
           { "$eq" : [ "$birthday.month" , specified_month ] } ,
           { "$lt" : [ "$birthday.day" , specified_day ] }
         ] }
      ] } ,
    "then" : 1 ,
    "else" : 0 } }
}}

sort_stage = { "$sort" : {
  "__passed" : 1 ,
  "birthday.month" : 1 ,
  "birthday.day" : 1
} }

// added unset_stage to cleanup temporary field __passed.

unset_stage = { "$unset"  : [ "__passed" ] }

pipeline = [ set_stage , sort_stage , unset_stage ]

collection.aggregate( pipeline )

// Result when applied on original collection
{ _id: 4,
  firstName: 'Danica',
  lastName: 'Taylor',
  birthday: { month: 8, day: 12 } }
{ _id: 3,
  firstName: 'John',
  lastName: 'Doe',
  birthday: { month: 8, day: 21 } }
{ _id: 1,
  firstName: 'John',
  lastName: 'Doe',
  birthday: { month: 10, day: 2 } }
{ _id: 2,
  firstName: 'John',
  lastName: 'Doe',
  birthday: { month: 10, day: 5 } }
{ _id: 7,
  firstName: 'Alicia',
  lastName: 'Travis',
  birthday: { month: 2, day: 18 } }
{ _id: 6,
  firstName: 'Pamela',
  lastName: 'Giesen',
  birthday: { month: 4, day: 22 } }
{ _id: 5,
  firstName: 'Daniel',
  lastName: 'Johnson',
  birthday: { month: 6, day: 14 } }

Thank you for your fast reply. I will try this and send you feedback.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.