简体   繁体   中英

MongoDB and node.js: create array by multiple queries in one route

Using node.js, I want to define a route in which for four different categories MongoDB is queried and two documents for each category are returned. The response of the route should thus be an array of four arrays which contain two documents each.

I wrote this code:

router.get("/sample9/all", (req, res) => {
console.log("Call to 9 route was made");
clusters = ["icecream", "chocolate"];
newData = []
clusterFood = clusters.map(cluster =>
dbase
  .db("course1")
  .collection("food")
  .find({ category: cluster })
  .limit(2)
  .toArray((err, results) => {
    newData.push(results);
  })
  );
  res.send(clusters);
  });

This gives a response with an empty object. Could anybody help? I am just getting started with node.js and MongoDB.

You can use aggregation framework for this type of query. Your pipeline comprises of an initial $match stage which filters the collection on the 4 categories passed.

The preceding pipeline stage will be the $group step which then groups the filtered input documents by the category field, create an array with the top level documents from each group and a final pipeline $project stage that reshapes the array to just include two documents using $slice .

Consider running the following pipeline to get the desired result:

Main pipeline:

const pipeline = [
    { '$match': { 
        'category': { '$in': clusters }
    } },
    { '$group': {
        '_id': '$category',
        'docs': { '$push': '$$ROOT' }
    } },
    { '$project': {
        'docs': { '$slice': ['$docs', 2] } 
    } }
];

Using aync/await

router.get("/sample9/all", async (req, res) => {
    console.log("Call to 9 route was made");
    const collection = dbase.db("course1").collection("food");
    const results = await collection.aggregate(pipeline).toArray();

    res.send(results);
});

Using Promises

router.get("/sample9/all", (req, res) => {
    console.log("Call to 9 route was made");
    const collection = dbase.db("course1").collection("food");
    const agg = collection.aggregate(pipeline);

    agg.then(results => res.send(results))
       .catch(err => console.error(err));
});

Using callbacks

router.get("/sample9/all", (req, res) => {
    console.log("Call to 9 route was made");
    const collection = dbase.db("course1").collection("food");
    collection.aggregate(pipeline).toArray((err, results) => {
        if (err) {
            console.error(err);
        }
        else {
            res.send(results)
        }
    });
});

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