Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequelize return array with Strings instead of Objects

Sometimes i only want to select a single value from multiple rows.

Lets imagine i have an account model which looks like this:

Account

  • Id
  • Name
  • Age

And i would only like to select the names.

You would write something like this:

AccountModel.findAll({
        where: {
            Age: {
                $gt : 18
            }
        },
        attributes: ['Name'],
        raw : true
    });

But this would return in an array with objects.

[{Name : "Sample 1"}, {"Name" : "Sample 2"}]

I would like to get an array with only names like this:

["Sample 1", "Sample 2"]

Is it possible to achieve this with Sequelize? I've searched trough the documentation but couldn't find it.

like image 903
Jamie Avatar asked Nov 06 '15 21:11

Jamie


3 Answers

2020 Solution

Hi folks, you can easily do your pure "pluck" method:

const someVariable = [
  ... ( await AccountModel.findAll({
    where: {
        Age: {
            $gt : 18
        }
    },
    attributes: ['Name'],
    raw : true
  })),
].map(account => account.Name);
like image 132
Fábio BC Souza Avatar answered Sep 21 '22 11:09

Fábio BC Souza


Using Sequelize 3.13.0 it looks like it isn't possible to have find return a flat array of values rather than an array of objects.

One solution to your problem is to map the results using underscore or lodash:

AccountModel.findAll({
    where: {
        Age: {
            $gt : 18
        }
    },
    attributes: ['Name'],
    raw : true
})
.then(function(accounts) {
  return _.map(accounts, function(account) { return account.Name; })
})

I've uploaded a script that demonstrates this here.

As a quick note, setting raw: true makes the Sequelize find methods return plain old JavaScript objects (i.e. no Instance methods or metadata). This may be important for performance, but does not change the returned values after conversion to JSON. That is because Instance::toJSON always returns a plain JavaScript object (no Instance methods or metadata).

like image 13
cfogelberg Avatar answered Oct 17 '22 11:10

cfogelberg


Here is a nice ES6 version of cfogelberg's answer using lambda expressions (Array.prototype.map() only works in IE9+ and lambda (arrow) functions have no IE support):

AccountModel.findAll({
    where: {
        Age: {
            $gt : 18
        }
    },
    attributes: ['Name'],
    raw : true
})
.then(accounts => accounts.map(account => account.Name));

Snippet (does not work in ie):

Here is a baby snippet I used for proof of concept. If it doesn't work, you are using one of the unsupported browsers mentioned above (and you shouldn't be making db calls directly from the browser anyway):

let objArray=[{key:1},{key:2},{key:3}];
console.log("Not IE friendly:");
console.log(objArray.map(obj => obj.key));
console.log("IE friendly (might even be ES3 if you change \"let\" to \"var\"):");
let names = [];
for(let i=0 ; i<objArray.length ; i++){
    names[i] = objArray[i].key
}
console.log(names)
like image 12
ThisGuyCantEven Avatar answered Oct 17 '22 12:10

ThisGuyCantEven