Jamie
Jamie

Reputation: 3051

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

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.

Upvotes: 18

Views: 32647

Answers (4)

ThisGuyCantEven
ThisGuyCantEven

Reputation: 1267

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):

const 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)

Upvotes: 15

F&#225;bio BC Souza
F&#225;bio BC Souza

Reputation: 1220

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);

Upvotes: 8

Li Zheng
Li Zheng

Reputation: 731

arr-pluck works well:

var pluck = require('arr-pluck');

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

Upvotes: 3

cfogelberg
cfogelberg

Reputation: 1488

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).

Upvotes: 17

Related Questions