0

I've a usecase in which I'll get dynamic field names in an array. I need to pass those fields to the mongo db aggregation query to get the sum of that field values in a given month. I need to remove the timeStamp & deviceId fields in array.

let jsonObj = [
  { name: "heat", value: "HEAT" },
  { name: "humidity", value: "HUMIDITY" },
  { name: "deviceId", value: "DEVICEID" },
  { name: "timeStamp", value: "TIMESTAMP" }
];

let vList = [];
jsonObj.forEach(async data => {
  if (!data.name.match(/time/g) || !data.name.match(/deviceId/g)) {
    vList.push(data.name); //Should exclude timestamp & deviceId (case-insensitive)
  }
});

let variableObj = [];
vList.forEach(async data => {
  let k = "{" + '"$sum":"$' + data + '"}';
  // console.log(k)
  k = JSON.parse(k);
  variableObj.push(data + ":" + k);
});

Then resultant array looks like the following.

[ 'heat:{"$sum":"$heat"}',
  'humidity:{"$sum":"$humidity"}',
  'timeStamp:{"$sum":"$timeStamp"}',
  'deviceId:{"$sum":"$deviceId"}' ]

Am not getting how to remove the single quotes around each item and how to pass them to query.

My query is:

db.collection(templateId).aggregate([
  {
    $match: {
      entryDayTime: {
        $lt: new Date(lastDay),
        $gte: new Date(firstDay)
      }
    }
  },
  {
    $group: {
      _id: "$deviceId",
      Count: { $sum: 1 }
      // Should pass those array elements here like,
      //heat:{"$sum":"$heat"},
      //humidity:{"$sum":"$humidity"}
    }
  },
  { $sort: { entryDayTime: -1 } }
]);

2 Answers 2

2

This should work.

const jsonObj = [
  { name: "heat", value: "HEAT" },
  { name: "humidity", value: "HUMIDITY" },
  { name: "deviceId", value: "DEVICEID" },
  { name: "timeStamp", value: "TIMESTAMP" }
];

const filteredJson = jsonObj.filter(i => i.name !== "deviceId" && i.name !== "timeStamp");

const groupQuery = {
  $group:{
     _id:"$deviceId",
     Count:{$sum:1}
  }
};

filteredJson.forEach(row => {
  groupQuery.$group[row.name] = {"$sum": `$${row.name}`};
});

console.log(groupQuery);

Hope this helps. All you need to do is now, insert the $group with the variable prepared above.

Sign up to request clarification or add additional context in comments.

Comments

1

You could create the whole group object together and pass it onto the $group stage. Also remove those async keywords, the iterations are not asynchronous.

Note: The if clause should have && to exclude both keywords and i flag is for case-insensitivity in regex. And creation of the target object can be completed in the first iteration itself.

let jsonObj = [
  { name: "heat", value: "HEAT" },
  { name: "humidity", value: "HUMIDITY" },
  { name: "deviceId", value: "DEVICEID" },
  { name: "timeStamp", value: "TIMESTAMP" }
];

let groupObject = {
  _id: "$deviceId",
  Count: { $sum: 1 }
};

jsonObj.forEach(data => {
  if (!data.name.match(/timestamp/gi) && !data.name.match(/deviceid/gi)) {
    groupObject[data.name] = { $sum: "$" + data.name };
  }
});

console.log(groupObject);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.