8

In my node.js app I retrieve values from mongodb server and want to convert them to a CSV file.The parent element is easily accessed from the database and displayed in the CSV file but the sub element is not displayed and can't be accessed..

JSON structure:

"name" : "fhj",
"age" : "23",
"gender" : "female",
"sec" : "b",
"username" : "9886666",
"language" : "HINDI",
"method" : "method2",
"timeSlot" : {
    "id" : 2,
    "fromTime" : 12,
    "toTime" : 15
}

mycode:

db.users.find(function(err,values){
if(err||!values.length)
   console.log("ERROR !!!!");
else
{ 
   var i=1;
   str='[';
   values.forEach(function(user){
     if(i==values.length)
         str=str+'{ "name" : "' + user.username + '","age" : "'+ user.age +'","gender":"'+user.gender+'","sec":"'+user.sec+'","username":"'+user.username+'","language":"'+user.language+'","method":"'+user.method+'","Timeslot":"'+user.timeslot+'"}';
     else{
       str = str + '{ "name" : "' + user.username + '","age" : "'+ user.age +'","gender":"'+user.gender+'","sec":"'+user.sec+'","username":"'+user.username+'","language":"'+user.language+'","method":"'+user.method+'","Timeslot":"'+user.timeslot+'"},' +'\n';
       i++;
     }
   });
   str = str.trim();
   str = str + ']';
   var obj=JSON.parse(str);
   json2csv({data: obj, fields: ['name', 'age','gender','sec','username','language','method','Timeslot']}, function(err, csv) {
      if (err) 
          console.log(err);
      fs.writeFile('./files/user.csv', csv, function(err) {
         if (err) 
             throw err;
         console.log('File saved');
      });
   });
 }  
});

All the values are displayed except the sub element of timeslot. How can I access the sub element of the JSON from the database and display all the values in a CSV file???

Setily
  • 814
  • 1
  • 9
  • 21
Subham
  • 1,414
  • 4
  • 17
  • 34
  • Can you provide the user.csv file created . i have faced a similar issues with the json2csv module. For inner nested objects/arrays it doesnot support complex structures . – Saleem Ahmed Aug 04 '16 at 12:49
  • @SaleemAhmed you have to manually create the csv for nested json. – Subham Aug 04 '16 at 12:51

8 Answers8

4

An easy way of accessing the nested elements can be found on the answer of following thread (Accessing nested data structures).

A nested data structure is an array or object which refers to other arrays or objects, i.e. its values are arrays or objects. Such structures can be accessed by consecutively applying dot or bracket notation.

As we can see timeSlot is an object, hence we can access its properties using dot notation. The items property is accessed as follows:

timeSlot.id

Alternatively, we could have used bracket notation for any of the properties, especially if the name contained characters that would have made it invalid for dot notation usage:

var item_name = timeSlot['id'];

Once you have all the data you need, the creation of the CSV-file should be quite straightforward :)

Community
  • 1
  • 1
trolologuy
  • 1,900
  • 4
  • 21
  • 32
1

Try like below

    db.users.find(function(err, users){
        if (err || !users.length) 
            return console.log(err || 'Users not found');

        // List of column to export to cvs
        var columns = ['name', 'age', 'gender', 'sec', 'username', 'language', 'method', 'timeSlot'];   

        var text = users.reduce(function(text, user){
            // user is object e.g. {name : "fhj", age : "23", .. }
            // If user is json then `user = JSON.parse(user, columns);`

            // convert user to csv-line
            text += columns.reduce(function(line, col){
                // I'm don't know how timeSlot must be save => save as json
                line += (type user[col] == 'object') ? JSON.stringify(user[col], ['id', 'fromTime', 'toTime']) : user[col];
                line += ';';
                return line;
            }, '') + '\n';

            return text;
        }, '');

        fs.writeFile('./files/user.csv', text, function(err) {
            if (err) 
                throw err;

            console.log('File saved');
        });
    });
Aikon Mogwai
  • 4,954
  • 2
  • 18
  • 31
0

Try to use user.timeslot.fromTime && make a key/value for each sub element

Islam Ahmed
  • 539
  • 1
  • 5
  • 17
0

Try like this. This will merge all data from timeSlot object into single string. You can format that string as much as you want. Code add in forEach loop.

var strToAdd = "";
for (var k in timeSlot) {
strToAdd += k + timeSlot[k] + "->";
}

...+"Timeslot":"'+strToAdd+'"....

Hope this helps.

Mykola Borysyuk
  • 3,373
  • 1
  • 18
  • 24
0

It seems the issue is that in your forEach loop where you are iterating over the variable values you are accessing the property timeslot of user instead of the value timeSlot of user. Remember case sensitivity matters!

Here is a fiddle which demonstrates that changing the case of the object property in lines 24 and 25 solves the issue

In the linked example I am also stringifying that object so that I can write it to the document and see the output clearly. I would recommend against that because you might run into issues parsing it later. Instead you should construct a string by accessing properties of that object.

Anyway, the reason you had an error was because of case sensitivity issues in your original code. I hope this helps.

rdgd
  • 1,451
  • 2
  • 18
  • 33
0

When you read structured data (here: JSON) and want to convert it into flattened data (here: csv), you have to decide how to execute the flattening.

In other words - your csv target structure could be the following:

name, age, gender, sec, username, language, method, timeSlot_id, timeSlot_fromTime, timeSlot_toTime
"fhb","23","female","b","9886666","HINDI","method2",2,12,15

Once you decided that you want to flatten the structure given in timeSlot this way, you can use the remarks from @Aikon Mokwai just without the stringify - use the array notation as described by @trolologuy to read the structure:

var timeSlot_id = timeSlot['id]';
var timeSlot_fromTime = timeSlot['fromTime'];
var timeSlot_toTime = timeSlot['toTime'];

Subsequently, whoever reads the csv has to understand that you flattened the data but does not have to parse any structure since you really provide flat data records (as csv likes it best).

Hope it helps!

dr. rAI
  • 1,773
  • 1
  • 12
  • 15
0

Hi use async foreach loop to achieve above. Here is details how it works.

Async loop in nodejs

Love-Kesh
  • 777
  • 7
  • 17
0
var json= {
"name" : "fhj",
"age" : "23",
"gender" : "female",
"sec" : "b",
"username" : "9886666",
"language" : "HINDI",
"method" : "method2",
"timeSlot" : {
    "id" : 2,
    "fromTime" : 12,
    "toTime" : 15
 }
};
console.log(json.timeSlot['id']);
console.log(json.timeSlot['fromTime']);
console.log(json.timeSlot['toTime']);

enjoy :)

see jsfiddle

Tarik FAMIL
  • 439
  • 5
  • 9