Date comparison in an Atlas Function using collection.aggregate() and $geoNear

I have collection, as described below…

in my collection:

_id: ObjectId
locations: Array
          location: Object  (embedded)
               type: "Point"
               coordinates: Array
                 [ longitude, latitude ]
          dates: Array
               start_date: Date
               note: String

I have successfully gotten the $geoNear part of the aggregate() working well now, but am confused about how to do date comparisons to further filter down the results.

My function arguments are longitude, latitude, max distance, and a date to be used. What I am wanting to do in the aggregate is simple,

$geoNear, which is working fine for me

  • match records where start_date < date passed as argument to function
    OR
  • match records where start_date > date passed as argument, AND note != “” (empty)

I don’t seem to be able to do date comparisons, no matter where or what methods I’ve used. This includes:

  • using the query field in the $geoNear aggregate stage (always the first in the pipeline)

  • using $match as the next stage in the pipeline (after the $geoNear without a query field set

I’ve tried using $expr with $gte as this is recommended in what I’ve read. I’ve also tried $cmp with no success.

Here is the function and what I’m calling the function with, using the Atlas App Services Function Editor and Console:

From Atlas App Services Function Editor Console, I am testing with:

context.functions.execute("location_date", -80.130, 26.393, 10000, new Date("2023-02-01"), new Date("2023-02-28"))

exports = async function(longitude, latitude, searchRadius, startDate) {
  var serviceName = "mongodb-atlas";
  // Update these to reflect your db/collection
  var dbName = "<my_database>"; // example, actual database name differs
  var collName = "<my_collection>"; // example, actual collection name differs

  // Get a collection from the context
  var collection = context.services.get(serviceName).db(dbName).collection(collName);

  // used to process results from the query
  var findResult;
  
  // set a date to the beginning of the year from the date sent in
  var yearStartDate = new Date(startDate)
  yearStartDate.setMonth(0);
  yearStartDate.setDate(1); 
  yearStartDate.setHours(0);
  yearStartDate.setMinutes(0);
  yearStartDate.setSeconds(0);
    
  // 
  // starting query here
  try {   
      findResult = await collection.aggregate([
        { // begin pipeline for geoNear, always comes first for any aggregate pipeline
          "$geoNear": {
            "near": {
              "type": "Point", 
              "coordinates": [ longitude, latitude ]
              }, // end near
            "includeLocs": "locations.location",
            "distanceField": "locations.distance",
            "maxDistance": searchRadius,
            "spherical": true
          } // end $geoNear
        }, // end 1st pipeline
        {  // THIS DOESN'T SEEM EVALUATE THE DATE COMPARISONS 
          "$match": {
            "$expr": {
              "$gte": [ "locations.stella_event_dates.end_date", startDate ]
            }
          }
        }, // end 2nd pipeline
        { // define fields we're excluding from being in the findResult
          "$project": {
            "event_name": 1,
            "locations": 1,
          } // end $project
        }, // end 2nd pipeline
        {  // for now, helping with the testing, by confirming date passed as arg is valid
          "$addFields": {
            "startDate": startDate.toDateString()
            }
        } // end 3rd pipeline
    ]
    ); // end .toArray().then()
  } catch(err) {
    console.log("Error occurred while executing find:", err.message);
    return { error: err.message };
  }
  // To call other named functions:
  // var result = context.functions.execute("function_name", arg1, arg2);
  return { result: findResult };
};

What is the best way to compare dates in this function, (what am I doing wrong?)

Thanks

Managed to get this working using the $geoNear “query” field. Completely flummoxed as to why it wasn’t working for me the first try, likely a typo on my part, this is now a closed issue.

1 Like

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