skip to Main Content

So am fetching data with mongoose and i would like to modify the data like apply some date formats. Currently i have

  const count = await UserModel.countDocuments();
  const rows = await UserModel.find({ name:{$regex: search, $options: 'i'}, status:10 })
        .sort([["updated_at", -1]])
        .skip(page * perPage)
        .limit(perPage)
        .exec();
   

  res.json({ count, rows });

The above UserModel is a mongoose model

I would like to modify some of objects like applying date formats before the data is returned while still paginating as above.

Currently i have added the following which works but i have to loop through all rows which will be a performance nighmare for large data.

 res.json({ count, rows:rows.map(el=>({...el,created_at:'format date here'})) });

Is there a better option

2

Answers


  1. As much as I understood your question, If you need to apply some date formats before showing data on frontend, you just need to pass the retrieved date in a date-formating library before displaying it, like in JS:
    const d = new Date("2015-03-25T12:00:00Z");

    However, if you want to get date in formatted form, than you must format it before storing. I hope that answer your question.

    Login or Signup to reply.
  2. I think the warning from @Fabian Strathaus in the comments is an important consideration. I would strongly recommend that the approach you are trying to solve sets you up for success overall as opposed to introducing new pain points elsewhere with your project.

    Assuming that you want to do this, an alternative approach is to ask the database to do this directly. More specifically, the $dateToString operator sounds like it could be of use here. This playground example demonstrates the basic behavior by adding a formatted date field which will be returned directly from the database. It takes the following document:

      {
        _id: 1,
        created_at: ISODate("2022-01-15T08:15:39.736Z")
      }
    

    We then execute this sample aggregation:

    db.collection.aggregate([
      {
        "$addFields": {
          created_at_formatted: {
            $dateToString: {
              format: "%m/%d/%Y",
              date: "$created_at"
            }
          }
        }
      }
    ])
    

    The document that gets returned is:

      {
        "_id": 1,
        "created_at": ISODate("2022-01-15T08:15:39.736Z"),
        "created_at_formatted": "01/15/2022"
      }
    

    You could make use of this in a variety of ways, such as by creating and querying a view which will automatically create and return this formatted field.

    I also want to comment on this statement that you made:

    Currently i have added the following which works but i have to loop through all rows which will be a performance nighmare for large data.

    It’s good to hear that you’re thinking about performance upfront. That said, your query includes a query predicate of name:{$regex: search, $options: 'i'}. Unanchored and/or case insensitive regex filters cannot use indexes efficiently. So if your status predicate is not selective, then you may need to take a look at alternative approaches for filtering on name to make sure that the query is performant.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search