Shrutayu Kale
Shrutayu Kale

Reputation: 35

How to get data from array in mongoose?

I am new to mongoose node.js and mongoDB, I have a db Schema like

Project:{
    projectName:"String",
    projectManager:"String",
    task:[{
           taskName:"String",
           timetakeninhrs:"String"
    }]
};

So what I want is to get only the details of task with particular task name. I am writing sql script so that you can know what I want :

Select taskname,timetakeninhrs from project where taskName ='DB create';

Upvotes: 3

Views: 7174

Answers (2)

aitnasser
aitnasser

Reputation: 1246

i create this example that can help you:

var async=require('async');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var uri = 'mongodb://localhost/myDb';
mongoose.connect(uri);

// define a schema
var ProjectSchema = new Schema({
    projectName: "String",
    projectManager: "String",
    task: [{
        taskName: "String",
        timetakeninhrs: "String"
    }]
});

// compile our model
var Project = mongoose.model('Project', ProjectSchema);

// create a documents
var Project01 = new Project({
    projectName: "Project01",
    projectManager: "Manager01",
    task: [{
        taskName: "tsk01_Project01",
        timetakeninhrs: "1111-1111"
    }, {
        taskName: "tsk02_Project01",
        timetakeninhrs: "1111-2222"
    }, {
        taskName: "tsk03_Project01",
        timetakeninhrs: "1111-3333"
    }, {
        taskName: "tsk04_Project01",
        timetakeninhrs: "1111-4444"
    }]
});

var Project02 = new Project({
    projectName: "Project02",
    projectManager: "Manager02",
    task: [{
        taskName: "tsk01_Project02",
        timetakeninhrs: "2222-1111"
    }, {
        taskName: "tsk02_Project02",
        timetakeninhrs: "2222-2222"
    }, {
        taskName: "tsk03_Project02",
        timetakeninhrs: "2222-3333"
    }, {
        taskName: "tsk04_Project02",
        timetakeninhrs: "2222-4444"
    }]
});

//delete existing documents and create them again
Project.remove({}, function() {
    Project01.save(function() {
        Project02.save(function() {
            //for example we find taskName: "tsk03_Project02"
            Project.find({'task': {$elemMatch: {taskName: "tsk03_Project02"}}},'task.taskname task.timetakeninhrs',function(err, docs) {
                if (!err) {
                    console.log(docs);
                }
            });
        });
    });
});

Upvotes: 1

chridam
chridam

Reputation: 103365

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

Upvotes: 1

Related Questions