The $elemMatch projection operator would come in handy for this:
Project
.where('task.taskName', 'DB create') // or where('task.taskName').equals('DB create').
.select({_id: 0, task: {$elemMatch: {'taskName': 'DB create'}})
.exec(function(err, docs){
var tasks = docs.map(function(doc){ return doc.task[0]; });
console.log(tasks[0].taskName); // 'DB create'
console.log(tasks[0].timetakeninhrs); // '3'
});
In the above, the where() method acts as a static helper method of the Mongoose model that builds up a query using chaining syntax, rather than specifying a JSON object. So
// instead of writing:
Project.find({ 'task.taskName': 'DB create' }, callback);
// you can instead write:
Project.where('task.taskName', 'DB create');
// or
Project.where('task.taskName').equals('DB create');
and then chain the select() method to project the 'task' array field using $elemMatch. In the exec() method (which executes the query asynchronously), you need to pass in a callback which follows the pattern callback(error, results). What results is depends on the operation: For findOne() it is a potentially-null single document, find() a list of documents, count() the number of documents, update() the number of documents affected, etc. In this case this returns an array of documents in the format:
[
/* 0 */
{
"task" : [
{
"taskName" : "DB create",
"timetakeninhrs" : "3"
}
]
},
/* 1 */
{
"task" : [
{
"taskName" : "DB create",
"timetakeninhrs" : "9"
}
]
}
/* etc */
]
In your callback you can do a bit of data manipulation to get an object that only has those properties you specified, hence the use of the native JavaScript map() function to create a new array of objects with those fields