2

I would like to use OrientDB as a database for .csv files and store these in the original form in a binary field of a record using OrientJS. Additionally, I would like to store a name and a description as Strings. I worked through the documentation and was able to store raw binary records via

 var fs = require('fs');
 var testcsv = fs.readFile('test.csv',
 function(error, data){
    if(error) throw error;
    var binary = new Buffer(data);
    binary['@type'] = 'b';
    binary['@class']='CSV';
    db.record.create(binary);
})

However, I have found no way to store a record with a field of the type "Binary". I tried several ways, all of which do not seem to work. E.g.:

     var fs = require('fs');
     var testcsv = fs.readFile('test.csv',
     function(error, data){
        if(error) throw error;
        var binary = new Buffer(data);
        binary['@type'] = 'b';
        binary['@class']='CSV'; 
        db.record.create({
           '@class': 'Test',
           'file': binary,
           'name': 'X',
           'description': 'Y'
        });
     })

If 'field' is not declared as 'Binary' it gets set to the type 'Embedded' by default and the .csv is "stored". If 'field' is declared as 'Binary' an error is thrown:

Unhandled rejection OrientDB.RequestError: Error on unmarshalling field 'file' in record #22:-1 with value: file: ... 
DB name="mydb"
    at child.Operation.parseError (...node_modules\orientjs\lib\transport\binary\protocol33\operation.js:864:13)
    at child.Operation.consume (...node_modules\orientjs\lib\transport\binary\protocol33\operation.js:455:35)
    at Connection.process (...node_modules\orientjs\lib\transport\binary\connection.js:399:17)
    at Connection.handleSocketData (...node_modules\orientjs\lib\transport\binary\connection.js:290:20)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:176:18)
    at Socket.Readable.push (_stream_readable.js:134:10)
    at TCP.onread (net.js:548:20)

As I tried many other ways I am left clueless. Am I misunderstanding something? Help is greatly appreciated!

NoItAll
  • 21
  • 3

1 Answers1

0

Here is a workaround where binary files are encoded to base64 and then stored as a string property.

Here is an example where I encode a svg file and then decode it again after loading from the database:

// First npm install the following packages
npm install orientjs
npm install await-to-js

Then create a file app.js and run it:

const OrientDBClient = require("orientjs").OrientDBClient;
const to = require('await-to-js').default;

// EXAMPLE FILE: AN SVG IMAGE
var svg = `<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<circle cx="100" cy="100" r="50" stroke="black" stroke-width="5" fill="red" /></svg>`

connect().then(async function(db) {

    // Add class to database
    [err, result] = await to(
        db.session.class.create('Example', 'V')
    );
    if (err) { console.error(err); };

    // Add property image to class
    [err, result] = await to(
        db.session.command('CREATE PROPERTY Example.image STRING').all()
    );
    if (err) { console.error(err); };

    // Add property name to class
    [err, result] = await to(
        db.session.command('CREATE PROPERTY Example.name STRING').all()
    );
    if (err) { console.error(err); };

    // *****************************************************************
    // ********************* USING BASE64 ENCODING *********************
    // *****************************************************************

    // Convert to base64
    var buf = Buffer.from(svg, 'utf-8').toString("base64");

    // Add node to class with image encoded as base64
    [err, result] = await to(
        db.session.insert().into('Example').set({image: buf, name: 'ABC'}).one()
    );
    if (err) { console.error(err); };

    // Retrieve base64 encoded svg from database
    [err, result] = await to(
        db.session.select('image').from('Example').where({name: 'ABC'}).one()
    );
    if (err) { console.error(err); };

    // Output svg XML to the console
    var output = Buffer.from(result.image, 'base64');
    console.log(output.toString('ascii'));
})

async function connect() {
    // Connect to Server
    [err,client] = await to(OrientDBClient.connect({
        host:   'localhost',    // Specify your host here
        port:   '2424'          // Make sure you call the HTTP port
    }));
    if (err) {
        console.log("Cannot reach OrientDB. Server is offline");
        return false;
    }

    // Connect to Database.
    [err,session] = await to(client.session({ 
        name:       'demodb',   // Name of your database
        username:   'admin',    // Username of your database
        password:   'admin'     // Password of your database
    }));
    if (err) {
        console.log("Database doesn't exist.");
        return false;
    }

    // Add handler
    session.on('beginQuery', (obj) => {
        console.log(obj);
    });

    // Check if session opens
    console.log("Successfully connected to database.");
    var graph = {client, session};
    return graph;
}

This code will create a class Example that has properties image and name and will then create a vertex where the svg is saved as a base64 encoded string. It also shows how to retrieve the image again into javascript.

Jean-Paul
  • 19,910
  • 9
  • 62
  • 88