简体   繁体   中英

NodeJS mongoose query and promise

So, I am new to nodejs. I don't just want to solve this problem, but I also want to learn this concept.

1 Prize has Many Winners. Both are separate tables. I first get list of prizes related to a certain id. I loop through those prizes using Promises.all() and then, for each prize, I query for winners.

Here is my code:

router.post("/getResult", function (req, res) {
    const lottery_id = req.body.lottery_id;
    const data = [];

    //Find list of prices for given lottery_id. Note the sorting applied here
    Prize.find({"lotid": lottery_id}).sort({name: 1})
        .then(async function (prizes) {
            try {
                await Promise.all(prizes.map(async (prize) => {
                    //Sorting here works fine as confirmed by this log.
                    console.log(prize.name);

                    await Winner.find({"id": prize._id})
                        .then(function (winners) {
                            data.push({
                                prize: prize,
                                winners: winners
                            });
                        })

                }));

                //Sorting here is completely messed up. 
                // Something wrong with second query "Winner.find() and pushing data
                res.send({success: 1, data: data});
            } catch (err) {
                console.log("Error " + err);
                res.send({success: 0, data: err});
            }


        }).catch(function (err) {
        res.send({success: 0, error: err});
    })
});

The final result that I get doesn't follow the sorting applied to prize. May be, the query Winner.find() for 2nd prize finishes before 1st prize and hence, it is pushed in data before 1st prize.

You are seeing an unexpected sorted result because there is no coordination with how you are pushing values into the data array. prizes.map() does iterate over the prizes array sequentially, however, there is no guarantee that each mapped promise, or more specifically each Winner.find(), will become fulfilled in the same order chronologically.

One way you could fix this is to use the return value of Promise.all(). Here is an example:

router.post("/getResult", async function (req, res) {
  const lottery_id = req.body.lottery_id;

  try {
    const prizes = await Prize.find({ "lotid": lottery_id }).sort({ name: 1 });

    const prizeWinners = await Promise.all(prizes.map(async function(prize) {
      const winners = await Winner.find({ "id": prize._id });
      return {
        prize,
        winners
      };
    }));

    res.send({ success: 1, data: prizeWinners });
  } catch (err) {
    res.send({ success: 0, error: err });
  }
});

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