简体   繁体   中英

Using for loop with MongoDB queries result are continuously different value

I want to create line chart with chart.js and it needs data with an array.

And I want to create a chart of post views by date. The range was set based on one week, and counters collection was created in MongoDB.

One week is 7 days so I use for loop to query seven times and get each counter value. The results are fine. And there is no problem with frontEnd side but sometime server send wrong data.

DB Data

{
    "_id": {
        "$oid": "5f91359ee04cf21abc1920d8"
    },
    "repoName": "NodeJSK",
    "repoNumber": 96127950,
    "userName": "writingdeveloper",
    "userNumber": 6832586,
    "viewDate": "2020-10-22",
    "__v": 0,
    "count": 2
},
{
    "_id": {
        "$oid": "5f9135a8e04cf21abc1920da"
    },
    "repoName": "Projects",
    "repoNumber": 98097935,
    "userName": "writingdeveloper",
    "userNumber": 6832586,
    "viewDate": "2020-10-22",
    "__v": 0,
    "count": 2
},
{
    "_id": {
        "$oid": "5f9135aae04cf21abc1920db"
    },
    "repoName": "Udacity-Front-End-Web-Developer-Nanodegree",
    "repoNumber": 100840518,
    "userName": "writingdeveloper",
    "userNumber": 6832586,
    "viewDate": "2020-10-21",
    "__v": 0,
    "count": 2
},
{
    "_id": {
        "$oid": "5f9135ace04cf21abc1920dc"
    },
    "repoName": "HYCU-Department-of-Computer-Engineering",
    "repoNumber": 101602788,
    "userName": "writingdeveloper",
    "userNumber": 6832586,
    "viewDate": "2020-10-20",
    "__v": 0,
    "count": 2
},
{
    "_id": {
        "$oid": "5f9135afe04cf21abc1920dd"
    },
    "repoName": "ZzapCord",
    "repoNumber": 108807703,
    "userName": "writingdeveloper",
    "userNumber": 6832586,
    "viewDate": "2020-10-19",
    "__v": 0,
    "count": 3
},
{
    "_id": {
        "$oid": "5f9135bfe04cf21abc1920e2"
    },
    "repoName": "Scrimba-React-Chat-App",
    "repoNumber": 141670388,
    "userName": "writingdeveloper",
    "userNumber": 6832586,
    "viewDate": "2020-10-18",
    "__v": 0,
    "count": 1
}


I set the viewDate data to String.

DB Schema

const counterSchema = new Schema({
  count : Number,
  userName: String,
  userNumber: Number,
  repoName: String,
  repoNumber: Number,
  type: Number,
  viewDate: {
    type: String,
    default: Date.now()
  }
});

Server Side Code

router.get(`/:userId/admin/getchartdata`, (req, res, next) => {
  let userId = req.params.userId;
  let chartArray = [];
  let chartData = [];

  for (let i = 0; i < 7; i++) {
    let d = new Date();
    d.setDate(d.getDate() - i);
    chartArray.push(d.toISOString().substr(0, 10).replace('T', ''));
    // console.log(chartArray[i])
    Counter.aggregate([{
        $match: {
          userName: userId,
          // userNumber: userNumber,
          viewDate: chartArray[i],
        }
      },
      {
        $group: {
          _id: null,
          count: {
            $sum: "$count"
          }
        }
      }
    ], (err, viewData) => {
      if (err) throw err;
      if (viewData.length === 0) {   // When date count value is [] push 0 value.
        viewData = 0;
      } else {
        viewData = viewData[0].count
      }
      chartData.push(viewData)
      console.log(chartData)
    })
  }
})

What I expected

[4,2,2,3,1,0,0] // Seven days count's

But When I refresh page several times, Sometimes, server send a wrong array. like this data

[ 2 ]
[ 2, 1 ]
[ 2, 1, 2 ]
[ 2, 1, 2, 4 ]
[ 2, 1, 2, 4, 3 ]
[ 2, 1, 2, 4, 3, 0 ]
[
  2, 1, 2, 4,
  3, 0, 0
]
GET /favicon.ico 200 2.355 ms - 107781
GET /writingdeveloper/admin/mypage 200 358.972 ms - 28439
Session User Check : writingdeveloper
GET /writingdeveloper/admin/mypage 200 233.784 ms - 28439
GET /writingdeveloper/admin/getchartdata - - ms - -
GET /stylesheets/mypage/mypage.css 304 1.115 ms - -
GET /javascripts/mypage/mypage.js 304 0.615 ms - -
GET /javascripts/mypage/chart.js 304 1.493 ms - -
GET /images/app/Project.png 304 18.291 ms - -
Session User Check : writingdeveloper
[ 2 ]
[ 2, 3 ]
[ 2, 3, 1 ]
[ 2, 3, 1, 4 ]
[ 2, 3, 1, 4, 2 ]
[ 2, 3, 1, 4, 2, 0 ]
[
  2, 3, 1, 4,
  2, 0, 0
]

I don't know why this is happen. But I think the error is from using for loop so that queries are too fast so it sends wrong data.

It there anyway not to use for loop? or make it to one query. I think in one request's and seven queries are the waste of server resources and there could be errors here.

I guess that's because you're running an asynchronous block of code inside a for loop

try using async/await to force the for loop to wait until the asynchronous block of code executes and resolves its result before getting into the next iteration

so you code may look something like

router.get(`/:userId/admin/getchartdata`, async (req, res, next) => { // using async keyword here in the function that encloses the for loop
  try {
    // use try catch in async/await 
    let userId = req.params.userId;
    let chartArray = [];
    let chartData = [];

    for (let i = 0; i < 7; i++) {
      let d = new Date();
      d.setDate(d.getDate() - i);
      chartArray.push(d.toISOString().substr(0, 10).replace('T', ''));
      // console.log(chartArray[i])

      // and using await here
      // assign the result of aggregation to some variable
      let viewData = Counter.aggregate([
        {
          $match: {
            userName: userId,
            // userNumber: userNumber,
            viewDate: chartArray[i],
          }
        },
        {
          $group: {
            _id: null,
            count: {
              $sum: "$count"
            }
          }
        }
      ]);

      if (viewData.length === 0) {   // When date count value is [] push 0 value.
        viewData = 0;
      } else {
        viewData = viewData[0].count
      }

      chartData.push(viewData);

      console.log(chartData); // here you're logging the array after each query

    }

    console.log('After all the queries: ', chartData); // here we log the array after all the queries

  } catch (e) {
    // throw an error
    throw e;
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM