Search code examples
node.jsexpressrequestnode-https

Node - Exception thrown when inserting into MongoDB (byte array)


I'm getting the error in my Express + NodeJS app. I'm using an API from CoinAPI.io, and I've had an issue in the past with getting a Byte array as a response from the API. I've looked into the issue and I resolved it in the past with a Buffer.concat, so I can send the front end a json object as a response. Code below:

app.get('/build', function(req, res){
    console.log('Building the database...');

    // make client connect to mongo service
    MongoClient.connect(url, function(err, db) {
        if (err) throw err;
        console.log("SUCCESS: Database created");
        let dbo = db.db('lab5');

        // Craft request header
        const options = {
            "method": "GET",
            "hostname": "rest.coinapi.io",
            "path": "/v1/assets",
            "headers": {'X-CoinAPI-Key': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'}
        };

        // Send request to CoinAPI.io
        const request = https.request(options, response => {
            let chunks = [];
            response.on("data", chunk => {
                chunks.push(chunk);
            });
            response.on('end', () => {
                let json = Buffer.concat(chunks);

                // Insert into the database
                dbo.collection('crypto').insertMany(json, function(insertErr, insertRes) {
                    if (insertErr) throw insertErr;
                    console.log("Number of documents inserted: " + insertRes.insertedCount);
                    db.close();
                });
                console.log('End of request stream')
            });
        });

        request.end();

        // print database name
        console.log("NOTE: db object points to the database : "+ db.databaseName);
        db.close();
    });
    res.end();
})

This worked before, but now I have to instead insert the data I retrieve into a MongoDB database. So, I try to do an insertMany on the body object I'm creating out of the Buffer.concat. But now I get the following error.

MongoError: docs parameter must be an array of documents

I did a console.log(json) before the collection insert, and body dumps into the console the byte array that I just did the concat on, and I don't know why.

EDIT: In response to Sohail about using .toJSON(), this is what happened when I tried to convert the buffer to json

let buf = Buffer.concat(chunks);
let json = buf.toJSON();
console.log(json);

And when I console log json...

{
  type: 'Buffer',
  data: [
     91,  10,  32,  32, 123,  10,  32,  32,  32,  32,  34,  97,
    115, 115, 101, 116,  95, 105, 100,  34,  58,  32,  34,  78,
     80,  88,  83,  34,  44,  10,  32,  32,  32,  32,  34, 110,
     97, 109, 101,  34,  58,  32,  34,  80, 117, 110, 100, 105,
     32,  88,  34,  44,  10,  32,  32,  32,  32,  34, 116, 121,
    112, 101,  95, 105, 115,  95,  99, 114, 121, 112, 116, 111,
     34,  58,  32,  49,  44,  10,  32,  32,  32,  32,  34, 100,
     97, 116,  97,  95, 115, 116,  97, 114, 116,  34,  58,  32,
     34,  50,  48,  49,
    ... 5165802 more items
  ]
}

and I still get the error of inserting a byte array/buffer


Solution

  • You need to convert Buffer object to mongo document object. You could use buffer.toString() method and then parse it with JSON.parse method to convert string to object.

    Try this.

    let buf = Buffer.concat(chunks);
    let json = JSON.parse(buf.toString());
    // Insert into the database
    dbo.collection('crypto').insertMany(json, function (insertErr, insertRes) {
        if (insertErr) throw insertErr;
        console.log("Number of documents inserted: " + insertRes.insertedCount);
        db.close();
    });
    console.log('End of request stream');