Search code examples
node.jsmongodbmongoosemomentjsmongoose-schema

Filter document array to return values matching query Mongodb


I have the following app. It was required (FreeCodeCamp) to return a collection of dates exercise and time period (duration) with _id and username matching query in url.

Things i tried are as follows.

  1. Using aggregate to with $match to find _id in query.
  2. Unwind data array with $unwind.

Url:

http://localhost:3000/api/exercise/log21?id=eUyhCDgMB&start=31 December 2018&end=22 December 2018&limit=2
let iniate = new Date(req.query.start);
let one = moment(iniate).format("YYYY-MM-DDT00:00:00.000") + "Z";
let date1 = new Date(one);
console.log(date1);
console.log(typeof(date1));
let iniate1 = new Date(req.query.end);
let two = moment(iniate1).format("YYYY-MM-DDT00:00:00.000") + "Z";
let date2 = new Date(two);
console.log(date2)
console.log(typeof(date2))

app.get('/api/exercise/log21', (req, res) => {
  array.aggregate([{
    $match: {
      '_id': req.query.id
    }
  }, {
    $unwind: "$data"
  }]).then(doc => {
    res.send(doc)
  }).catch(e => {
    res.send(e);
  })
})

JSON returned

[{
    "_id": "eUyhCDgMB",
    "username": "Donald Duck",
    "data": {
      "description": "walking",
      "duration": 2,
      "date": "2019-01-01T00:00:00.000Z"
    },
    "__v": 0
  },
  {
    "_id": "eUyhCDgMB",
    "username": "Donald Duck",
    "data": {
      "description": "Mountain Biking",
      "duration": 3,
      "date": "2019-01-01T00:00:00.000Z"
    },
    "__v": 0
  },
  {
    "_id": "eUyhCDgMB",
    "username": "Donald Duck",
    "data": {
      "description": "Reading",
      "duration": 3,
      "date": "2018-12-31T00:00:00.000Z"
    },
    "__v": 0
  }
]

I need to filter out all the dates not matching the query in url and return dates matching query with username, id, description, duration and matching dates to query. Shown in my code localhost 3000. To get date query from string to date object I am using moment.js. As shown in my code with date1 and date2 variable.

I am trying to set $gte equal to date1 and $lte to $end=date2 If limit is set smaller than dates returned i need to return the amount of dates set in url. Example limit=2. Only return two matching date values.


Solution

  • I finally found a way to set a limit on matching date or dates of document. I am including following code.

    app.get('/api/exercise/log',(req,res)=>{
     array.findById({_id:req.query.id},(err,data)=>{
    		let iniate = new Date(req.query.start);
    				 let one = moment(iniate).format("YYYY-MM-DDT00:00:00.000") + "Z";
    				 let date1 = new Date(one);
    				 console.log(date1);
    				 console.log(typeof(date1));
    	let iniate1 = new Date(req.query.end);
    				 let two = moment(iniate1).format("YYYY-MM-DDT00:00:00.000") + "Z";
    				 let date2 = new Date(two);
    				 console.log(date2)
    				 console.log(typeof(date2))	
      let myLength;
    	   if(req.query.start === undefined && req.query.end === undefined && req.query.limit === undefined && req.query.id !== undefined){
    		 myLength = data.data.length;
    		array.aggregate([
        { $match: {_id: req.query.id}}]).then(data =>{
    		res.send({count:myLength,data})
    	})
    	  }
    	  else if(req.query.start !== undefined && req.query.end !== undefined && req.query.limit !== undefined && req.query.id !== undefined){
    	  array.aggregate([
        { $match: {_id: req.query.id}},
        { $unwind: '$data'},{$match : {"$and" :  [{"data.date" :{$gte : date1} },
        {"data.date" :{"$lte" : date2}}]}}]).limit(Number(req.query.limit)).then(data =>{
    		if(data.length >= Number(req.query.limit)){
    		res.send(data)
    		}else{
    		return  res.send({error:"Document do not match limit requested"})
    	  }
    	})
    	  }
    	 })
    })

    This finally returned required parameters of project , which was needed to complete my project for Free Code Camp. Using following link stackoverflow question how to query data inside an array of the collection using mongoose