I have a Node.js API with MongoDB. The ODM is Mongoose. The MongoDB collection is called 'Battery'. It stores data, coming from multiple IoT devices. Each document has a "BAT" array. This array has only a single object. There are about 100000 documents here. A new data is created every 4 minutes. There are multiple "SID" values such as "S044","S067",etc. There may be 10 to 2000 unique "SID" values. Each "SID" belongs "BID" values starts from 1 to "BYC/BXC" value. Below shows how they appear as a JSON data. In below example "BYC/BXC" value is 12. Then for "SID":"S044", there should be 12 unique documents which have "BID" value from 1 to 12 (It is better to use the latest document for a particular "SID" to calculate "BYC/BXC" value and need to retrieve latest documents for that "SID". Each "SID" has different "BYC" and "BXC" values. "BXC" and "BYC" values are unique for a particular "SID".

 {
            "TS": "1680047000007",
            "SID": "S044",
            "BAT": [
                {
                    "BID": 9,
                    "FOC": 1,
                    "BXC": 100,
                    "BYC": 1200
                }
            ]
        },
        {
            "TS": "1680000605007",
            "SID": "S044",
            "BAT": [
                {
                    "BID": 7,
                    "FOC": 1,
                    "BXC": 100,
                    "BYC": 1200
                }
            ]
        },....more

Currently I have created a query as below;

const getLatestBats = async (all_SIDs) => {
  const distinctSIDs = await Battery.distinct("SID", { SID: { $in: all_SIDs } });

  const latestDocuments = [];

  for (const SID of distinctSIDs) {
    const batteryDoc = await BAT.findOne({ SID })
      .select("BAT")
      .sort({ TS: -1 });

    if (batteryDoc && batteryDoc.BAT && batteryDoc.BAT.length > 0) {
      const { BYC, BXC } = batteryDoc.BAT[0];
      const BatCount = BYC / BXC;

      const documents = await Battery.aggregate([
        { $match: { SID, "BAT.BID": { $in: [...Array(BatCount)].map((_, index) => index + 1) } } },
        { $sort: { TS: -1 } },
        { $group: { _id: "$BAT.BID", document: { $first: "$$ROOT" } } },
        { $replaceRoot: { newRoot: "$document" } },
        { $project: { _id: 0, __v: 0 } },
     
      ]);

      latestDocuments.push(...documents);
    }
  }

  return { data: latestDocuments};
};


router.get('/', async (req, res) => {
  try {    
<-----all_SIDs come through a middleware---->
  const batteries = await getLatestBats(all_SIDs);
    res.json(batteries);

} catch (error) {
  console.error(error);
  res.status(500).json({ message: 'Server error' });
  }
});

module.exports = router;

. But, it takes about 8 seconds to return the response and also it required to create a const latestDocuments = []; array to store matching documents. But, it is not a good practice because can not use pagination(limit,page) for this array. I need to build a query or aggregation with overcoming these issues.

These are two documents from the collection (to get idea of the schema model).

_id 6483ea992dae73e915e14575
TS "1686366869373"
SID "CM045"
BAT Array 0 Object
   BID 1
   BXC 100
   BYC 500
__v 0

_id 6483ea9f2dae73e915e14578
TS "1686366879348"
SID "CM045"
BAT Array 0 Object
   BID 4
   BXC 100
   BYC 500
__v 0
0

There are 0 best solutions below