Saturday, 22 April 2017

Using knex SELECT query results for another SELECT query

I am trying to run a PostgreSQL query with Knex and then use the results to run another query.

exports.buildBuoyFeaturesJSON = function (conditionA, conditionB) {
var query = null;

var selectedFields = knex.select
(
    knex.raw('t_record.id AS id'),
    ...
    knex.raw('t_record.latitude AS latitude'),
    knex.raw('t_record.longitude AS longitude')
)
    .from('t_record')
    .then(function (response) {
        var geometry_array = [];
        var rows = response.rows;
        var keys = [];

        for (var key = 0; key <= rows.length - 1; key++) {
            var geometry =
                {
                    "id" : rows[key].id,
                    "type" : "Feature",
                    "geometry" : rows[key].geometry,
                    "properties" : {
                        ...
                        "sensors" : []
                    }
                };
            keys.push(rows[key].id);
            geometry_array.push(geometry);
        }
        getMeasurementsAndSensors(keys, geometry_array);
    });
};

The latter function uses some of the results from the previous function. Due to asynchronous nature of Knex, I need to call the second function from inside the first function's .then() statement:

function getMeasurementsAndSensors (keys, geometry_array) {
        var query = knex
            .select
            (
                't_record_id',
                'i_sensor_id',
                'description',
                'i_measurement_id',
                't_sensor_name',
                't_measurement_name',
                'value',
                'units'
            )
            .from('i_record')
            ...
            .whereRaw('i_record.t_record_id IN (' + keys + ')')
            .orderByRaw('t_record_id, i_sensor_id ASC')
            .then(function (response) {

        var rows = response.rows;
        var t_record_id = 0;
        var i_sensor_id = 0;
        var record_counter = -1;
        var sensor_counter = -1;

        for (var records = 0; records <= rows.length -1; records++) {
            if (t_record_id !== rows[records].t_record_id) {
                t_record_id = rows[records].t_record_id;
                record_counter++;
                sensor_counter = -1;
            }

            if (i_sensor_id !== rows[records].i_sensor_id) {
                i_sensor_id = rows[records].i_sensor_id;

                geometry_array[record_counter].properties.sensors[++sensor_counter] =
                {
                    'i_sensor_id' : rows[records].i_sensor_id,
                    't_sensor_name' : rows[records].t_sensor_name,
                    'description' : rows[records].description,
                    'measurements' : []
                };
            }

            geometry_array[record_counter].properties.sensors[sensor_counter].measurements.push
            ({
                    'i_measurement_id': rows[records].i_measurement_id,
                    'measurement_name': rows[records].t_measurement_name,
                    'value': rows[records].value,
                    'units': rows[records].units
            });
        }
        //wrapping features with metadata.
        var feature_collection = GEOGRAPHY_METADATA;
        feature_collection.features = geometry_array;

        JSONToFile(feature_collection, 'buoy_features');
    });

}

Currently I save end result to a JSON file because I couldn't get Promises to work. JSON is later used to power a small OpenLayers application, hence the JSON-ification after getting results.

I am quite sure that getting the data from a database, saving it to file, then accessing it from another process and using it for OpenLayers is a very redundant way to do it, but so far, it is the only one that works. I know there are a lot of ways to make these functions work better, but I am new to promises and don't know how to work with them outside of most basic functions. Any suggestions how to make this code better are welcome.



via jjustas

No comments:

Post a Comment