Search code examples
postgresqlexpressknex.js

Async instead of joins - am I cheating?


I have been trying to replicate this async parallel set of queries using json_agg in postgres.

In my heart, although the async approach gets me the results I want, I feel like this is cheating and will cause me pain in the future.

Below I have included the results from my current implementation. How could i achieve the same with json_agg?

Express route

router.get('/', function(req, res) {


  async.parallel({
      records: function(parCb) {
        var query = knex('records').select('title','id').orderBy(knex.raw('RANDOM()')).limit(5)
        query.then(function(results) {
          parCb(null, results);
        });
      },
      collections: function(parCb) {
        var query = knex('collections').select('name','id').orderBy('name')
        query.then(function(results){
          console.log(results)
          parCb(null, results);
        });
      },
    },
    function(err, results) {
      res.render('index.html', {
        title: 'Welcome',
        data: results
      });
    });

});

Output

{ collection: 
   { id: 31,
     slug: 'BAR',
     name: 'Barker',
     long_name: 'Barker',
     copyright: '',
     description: null,
     notes: '',
     createdAt: Tue Jan 05 2016 16:47:35 GMT+0000 (UTC),
     updatedAt: Tue Jan 05 2016 15:32:55 GMT+0000 (UTC) },
  records: 
   [ { title: 'Whiddon Down: general view, Tawton, South',
       id: 12595 },
     { title: 'STOKE IN TEIGNHEAD', id: 13937 },
     { title: 'Teign Estuary', id: 104573 },
     { title: 'Lydford Village', id: 106650 },
     { title: 'Metheral hut circle before submersion by Fernworthy Reservoir',
       id: 1467 } ] }

Solution

  • First and foremost, don't mix the async library and promises. This avoids unnecessary pain.

    If one of the libraries you use is based on promises (like knex), I'd recommend you ditch async, use a proper promise library (one like Bluebird) and work with it.

    var Promise = require('bluebird');
    var knex = require('knex');
    var express = require('express');
    var router = express.Router();
    
    router.get('/', function(req, res) {
      Promise.all([
        knex('records').select('title','id').orderBy(knex.raw('RANDOM()')).limit(5),
        knex('collections').select('name','id').orderBy('name')
      ]).then(function (results) {
        res.render('index.html', {
          title: 'Welcome',
          data: {
            records: results[0],
            collections: results[1]
          }
        });
      });
    });
    

    I'm afraid I can't say a lot about json_agg here, though.