Search code examples
javascriptnode.jsmongodbexpressmongoose

Mongoose is there a way to get whole document in .distinct()


I have this code right here which works and distincts all of them with same "manga" but it only returns the "manga" part, not the whole object:

router.get("/lasttw", async (req, res) => {
  const ChapterDocs = await ChapterModel
    .find({})
    .sort({
      createdAt: -1
    })
    .distinct("manga");
  res.json(ChapterDocs)
})

Is there a way around for geting the whole object without a second query for each "manga" ?

This is the model that should be distincted and returned:

const ChapterSchema = new mongoose.Schema({
    number:{type:Number},
    url:{type:String},
    manga:{type:String},
    fansub:{type:String},
}, { timestamps: true })

Edit: this code returnes

["64a451dfdafa6462651d3ee6","64a4524edafa6462651d3f0c"]

but i also need chapter url, fansub and else.

this is the format i want them to be not just "manga" field :

{"_id":"64a4871b1c1c012a3ac15ff8"
 ,"number":2
 ,"url":"https://asurascanstr.com/olimposun-oyuncusu-bolum-2/"
 ,"manga":"64a4524edafa6462651d3f0c"
 ,"fansub":"AsuraScans"
 ,"createdAt":"2023-07-04T20:54:51.371Z"
 ,"updatedAt":"2023-07-04T20:54:51.371Z","__v":0}

Solution

  • Apparently you have to use .aggregate to do stuff like this i found it after some digging. Here is the code :

    router.get("/lasttw", async (req, res) => {
        try {
            const latestChapters = await ChapterModel.aggregate([
                { $sort: { createdAt: -1 } }, // Sort by createdAt in descending order
                { $group: { _id: "$manga", chapter: { $first: "$$ROOT" } } }, // Group by manga and get the first document (latest chapter) for each manga
                { $replaceRoot: { newRoot: "$chapter" } }, // Replace the root to get the complete chapter documents
            ]);
    
            res.json(latestChapters);
        } catch (error) {
            console.error(error);
            res.status(500).json({ error: 'An error occurred while fetching the latest chapters.' });
        }
    });
    

    i hope it help anyone trying to do something like this.

    1. We use the aggregate function to perform a series of operations on the ChapterModel collection.

    2. We first sort the documents in descending order based on the createdAt field using $sort.

    3. Then we group the sorted documents by the "manga" field using $group. For each manga, we use $first to get the first document (which will be the latest chapter).

    4. Next, we use $replaceRoot to replace the root of each document with the chapter document itself.

    5. The latestChapters array will contain the latest chapter document for each unique manga.

    6. The try-catch block is used to handle any potential errors that may occur during the process.

    I tried to explain it as best as i can. Hope it helps