Exercise Tracker . Cannot search for date range in nested object array in local host mongodb

Exercise Tracker . Cannot search for date range in nested object array in local host mongodb
0
#1

I have created the following objects within a array in my local mongodb database. Having tried the following set up to retrieve the document by date I only get an empty array returned. Here is my code with schema. I am using the following modules in npm shortid,mongoose,moment,cors,bodyParser and express.

const mySchema = new Schema ({
  _id:String,
  username: String,
  data: [{
	_id:false,  
    description : String,
    duration: Number,
    date :{type:Date}
  }]
});

"The user data object with dates of exercises to be completed cannot get date returned in query"

{
"count": 8,
"data": {
"_id": "bB6zWsJD6",
"username": "Timmy",
"data": [
{
"description": "walking",
"duration": 1,
"date": "2018-11-22T00:00:00.000Z"
},
{
"description": "walking",
"duration": 1,
"date": "2018-11-22T00:00:00.000Z"
},
{
"description": "walking",
"duration": 1,
"date": "2018-11-22T00:00:00.000Z"
},
{
"description": "walking",
"duration": 1,
"date": "2018-12-31T00:00:00.000Z"
},
{
"description": "walking",
"duration": 3,
"date": "2018-11-22T00:00:00.000Z"
},
{
"description": "walking",
"duration": 3,
"date": "2018-11-22T00:00:00.000Z"
},
{
"description": "walking",
"duration": 3,
"date": "2018-11-22T00:00:00.000Z"
},
{
"description": "walking",
"duration": 3,
"date": "2018-11-22T00:00:00.000Z"
}
],
"__v": 0
}
}

"using $gt greater than date in database and $lt less than date in database to query date in document"

app.get('/addme15',(req,res)=>{
	
	
	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))			 
	array.find({ "_id.username.data.date": { $gt:date1, $lt:date2 }}, function (err, docs) {
    res.send(docs);
});
})

0 Likes

#2

I had a similar problem with trying to use native mongodb search criteria on array elements while using a similar model to yours, one possible way is to use $elemMatch, https://docs.mongodb.com/manual/reference/operator/query/elemMatch/
the problem with that is it returns only the first match, which means that you have to use $aggregate, making it messy. So I opted to having the exercises in their own separate model but referenced to the user, the native mongodb search criteria had no problem filtering those.

0 Likes

#3

Thanks for replying Dereje1. Following your advice on creating separate model for exercises, I have tried a child schema, but i saves the data the same as when i pushed my exercises into an array. Here is an example of my main schema with child schema.

const dataSchema = new Schema({
	_id:false,
	description : String,
    duration: Number,
    date :{type:Date}
})

const mySchema = new Schema ({
  _id:String,
  username: String,
  data: [dataSchema]
});

As to your second statement “the native mongodb search criteria had no problem filtering those”. I am unsure how to filter without using $gte and $lte with query in url.

I finally got proper date value returned with set limit example url api/exercise/log?id=blahblah&start=greather than query date date&end=less than query date&limit-returned documents
using $aggregate

here is my example

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"})
	  }
	})
	  }
	 })
})
0 Likes