0

I am trying to query MongoDB hosted on the atlas (free tier). I am using nextjs for building api. I tried to host it in vercel (formerly known as zeit). The code works fine in local. On deploying to the cloud (vercel), it doesn't works.

var MongoClient = require('mongodb').MongoClient;

// serverless function for proverbs of the day
export default async (req, res) => {
  return new Promise((resolve) => {
    let databaseString = process.env.DATABASE_URL;
    MongoClient.connect(
      databaseString,
      { useUnifiedTopology: true },
      async function (err, client) {
        if (err) {
          console.error(err);
          throw err;
        }

        var db = client.db('database_name');

        var start = new Date();
        start.setHours(0, 0, 0, 0);

        var end = new Date();
        end.setHours(23, 59, 59, 999);

        let result;
        try {
          // query 1 : doesn't works
          result = await db
            .collection('proverbs')
            .findOne({ createdAt: { $gt: start, $lt: end } });

          // query 2 : works
          // result = await db.collection('proverbs').findOne({'id': 11 })
        } catch (err) {
          console.error(err);
        } finally {
          client.close();
        }

        res.send(result);
        return resolve();
      },
    );
  });
};

i tried two query : query 1 and query 2

in local both query 1 and 2 works

in vercel cloud server query 1 doesn't works query 2 works

i want to make the query 1 work. where am I going wrong?

2
  • It could be related to a time difference on the Vercel servers that run your functions. What exactly do you mean by "it doesn't work", you don't get any results? I would start debugging by logging start, end and result in production and compare with localhost. Commented Jun 3, 2020 at 10:57
  • @MaximOrlov The issue is that it doesn't return any results. Commented Jun 3, 2020 at 11:23

2 Answers 2

2

The issue is likely coming from a timezone difference between your machine and the Vercel servers. It's recommended to use UTC times as much as you can to avoid these type of problems.

In your case, simply using setUTCHours instead of setHours should give you the same results in production as localhost.

Sign up to request clarification or add additional context in comments.

5 Comments

setting to setUTCHours doesn't work in both local and production. I have no clue, how should I debug it.
So you're getting the same results between prod and local? That means the code works :). As to why you're not getting the expected results, probably because the createdAt of your documents is not within the date range of the query. Inspect those documents in MongoDB Atlas. How did you add the proverbs, manually, imported, someone can add it through a POST?
No. I am not getting results. I inserted data using nodejs scripts. I am using the same database (hosted in the atlas) both for local and production. The query doesn't return any result in production (but it works in locally). Do you really think, it's because of setHours?
setHours is the reason you were getting different results between prod and local. The reason you're getting no results now is simply because there are no documents in the DB that match the query. The code works as intended. You need to look into your data in MongoDB Atlas and have a look at the createdAt timestamps.
Thank you for your help. You were right (partly). I'll be updating my solution which I have found out with your help. Please check my answer why I couldn't mark your answer as accepted
0

The issue is likely coming from a timezone difference between your machine and the Vercel servers as answered by @Maxim Orlov. But I cannot upvote his answer as setting setHours to setUTCHours doesn't solve the problem. The following is what I've found out:

The solution

old: this doesn't work

result = await db
            .collection('proverbs')
            .findOne({ createdAt: { $gt: start, $lt: end } });

new: this work

result = await db
            .collection('proverbs')
            .findOne({ createdAt: { $gte: start, $lt: end } });

// also using setUTCHours instead of setHour is recommended, since UTC time is used.

Explanation

I've many documents has a timestamp of the following format - 2020-06-01 00:00:00.000 - 2020-06-02 00:00:00.000 - so on.

Case 1: Why the code is giving a result in local?

  1. local machine timezone is set to +05:30
  2. data is stored in mongodb (atlas) using UTC time say 2020-06-03 00.00.00 in UTC.
  3. in local machine time is 2020-06-03 11:00:00 (which is +05:30)
  4. let start = new Date.setHours(0,0,0,0) which is 2020-06-02 18:30:00.000
  5. let end = new Date.setHours(23, 59, 59, 999) which is 2020-06-03 18:29:59.999
  6. result = await db .collection('proverbs') .findOne({ createdAt: { $gt: start, $lt: end } });
  7. createdAt (2020-06-03 00:00:00.000) > start (2020-06-02 18:30:00.000) and createdAt (2020-06-03 00:00:00.000) < end (2020-06-03 18:29:59.000). which is (true and true), hence true, therefore result is returned.

Case 2: Why the code is not giving a result in production (vercel server)?

  1. vercel machine timezone is set to +00:00
  2. data is stored in mongodb (atlas) using UTC time say 2020-06-03 00.00.00 in UTC.
  3. in vercel machine time is 2020-06-03 05:30:00 (which is +00:00 i.e UTC)
  4. let start = new Date.setHours(0,0,0,0) which is 2020-06-03 00:00:00.000
  5. let end = new Date.setHours(23, 59, 59, 999) which is 2020-06-03 23:59:59.999
  6. result = await db .collection('proverbs') .findOne({ createdAt: { $gt: start, $lt: end } });
  7. createdAt (2020-06-03 00:00:00.000) > start (2020-06-03 00:00:00.000) and createdAt (2020-06-03 00:00:00.000) < end (2020-06-03 23:59:59.000). which is (false and true), hence false, there no result is returned.

Note:

  • server time is set to UTC
  • therefore setHour and setUTCHour will give the same time
  • to avoid the issue of timezone difference between your machine and the Vercel servers, always use UTC

1 Comment

I think you mean to say $gt in the first example. Glad you found the issue 👍🏼

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.