Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selecting a random record from Sequelize findAll

I'm currently brute-forcing this, but am confident there is a better solution that uses Sequelize, the code in question (using postgres):

...
then((tile_data) => {
  return Encounter.findAll({
    where: {
      level: tile_data.dataValues.level
    },
    transaction: transaction_data
  }).then((encounter_data) => {
    let encounter = encounter_data[Math.floor((Math.random() * encounter_data.length))].dataValues
    return Battle.create({
      character_id: character_data.dataValues.id,
      encounter_id: encounter.id,
      encounter_hp: encounter.max_hp,
      encounter_mana: encounter.max_mana
    }, {
      transaction: transaction_data
    })
...

Aside from seeming 'ugly', with this code I am loading all ENCOUNTERS into memory just to pluck one element out of the array.

Does anyone know how to do this through Sequelize, ideally without using a raw query?

Thank you

like image 762
smeckydev Avatar asked Feb 09 '17 20:02

smeckydev


3 Answers

You can try this :

Encounter.findAll({ order: Sequelize.literal('rand()'), limit: 5 }).then((encounters) => {
        // single random encounter
    }); 

Don't forget to require the Sequelize 👌

like image 73
Andhika Maheva Wicaksono Avatar answered Oct 27 '22 03:10

Andhika Maheva Wicaksono


I think this solution is the most clear one. You should use a random function from a sequelize instance

const sequelize = new Sequelize(url, opts);

Recommend to use a sequelize-cli to generate initial schema, it automatically exports sequelize variable.

Encounter.findOne({ 
  order: sequelize.random() 
});

Also with this approach u don't need to solve RAND() vs RANDOM() problem if you change a db dialect from postgres to MySQL or back.

like image 19
l2ysho Avatar answered Oct 27 '22 04:10

l2ysho


Encounter.findOne({ order: 'random()' }).then((encounter) => {
    // single random encounter
});

random() should be used in case of PostgreSQL, in case of MySQL you would probably use rand(). You did not specify what database are you using.

Edit

Or if you really want to use .findAll():

Encounter.findAll({ order: 'random()', limit: 1 }).then((encounter) => {
    // single random encounter
}); 
like image 10
piotrbienias Avatar answered Oct 27 '22 05:10

piotrbienias