69

I'm using the sequelize ORM to fetch data from a PSQL DB. However, when I retrieve something, a whole bunch of data is given. The only data I want is inside 'dataValues'. Of course, I can use object.dataValues. But, is there any other good solutions?

I'm using Sequelize 4.10

Gijo Varghese
  • 10,153
  • 20
  • 69
  • 112

6 Answers6

118

Yes you can

Model.findAll({
 raw: true,
 //Other parameters
});

would return just the data and not the model instance

Shivam
  • 3,084
  • 1
  • 14
  • 20
  • 4
    Can I apply that to all queries globally? – Gijo Varghese Sep 24 '17 at 00:08
  • 8
    You can define it while creating the connection. Something like `const sequelize = new Sequelize('connectionUri', { define: { raw: true } });`. From the docs [here](http://docs.sequelizejs.com/manual/installation/getting-started.html#application-wide-model-options) – Shivam Oct 03 '17 at 05:05
  • 21
    Please not this does not work with eager loading nested entities. – Sanket Berde Aug 30 '18 at 08:24
  • 8
    To apply to all queries, use `var sequelize = new Sequelize('database', 'username', 'password', {query:{raw:true}})` as mentioned in https://stackoverflow.com/a/26228558/1802726. – Raniere Silva Jun 10 '20 at 13:10
  • While i'm writing this comment this answer has 55 upvotes, then why it is in last thread ?, it must be on top list. I think Stack Overflow need to change it's algorithm. – TMA Jun 12 '20 at 12:25
  • 1
    You should have some disclaimer while picking raw – Sulthan Allaudeen Apr 13 '21 at 10:10
44

Sequelize wraps all it's return values in a virtual object that contains meta data. If you have an object and you just want the undecorated data values, you can unwrap them like so:

Model.findById(1).then(data => {
  console.log(data.get({ plain: true }));
});

Additionally if you just want to print out the object you can use the .toJSON method.

Model.findById(1).then(data => {
  console.log(data.toJSON());
});
C Deuter
  • 813
  • 1
  • 7
  • 14
  • 1
    I like the `data.get` answer you gave, it's almost exactly what I want. But do you know if there's a way that one could specify the `data.get` (or the `plain:true`, or anything else, really) part in the `find`'s options? E.g. instead of doing what you did, rather something like `Model.findOne({ plain:true, ... }).then(...)` ? Because the way I see it, if you're only going to filter out the data you want *inside* the `.then()`, you might as well save yourself some time and just do `data.dataValues` instead of `data.get(...)`. – SeriousLee Jan 01 '19 at 10:42
  • 1
    @PrintlnParams See Shivam's answer for details on that, if you want to do that globally see this answer https://stackoverflow.com/a/26228558/3803506 The method I described is more if you want to use the object for instance methods, etc but you want to encapsulate the implementation details before passing on the values, or for logging. `data.dataValues` works as well but be careful of mutability, also keep in mind that `dataValues` is sequelize's internal implementation which may change. – C Deuter Feb 15 '19 at 00:56
18

Finally I found answer after searching a lot. you should do something like this

const users = await db.users.findAll({})
   .map(el => el.get({ plain: true })) // add this line to code

source: github issue

Masoud Tavakkoli
  • 900
  • 12
  • 33
7

To clarify Masoud Tavakkoli's answer (which is not immediately clear on that github answer): using element.get({ plain: true }) returns an array of objects with each attribute key:value pairs.

If you just want an array of one specific attribute's values (eg user ids) instead of objects, you can use something like this:

const users = await User.findAll({
    attributes: ["id"], 
    where: {} // Your filters here
}).map(u => u.get("id")) // [1,2,3]

Nika Kasradze's answer actually achieves the same outcome as a middle-step; using the JSON stringifier generates the same array output. It's possible this is faster than mapping, but I'm not sure.

const users = await User.findAll({
    attributes: ["id"], 
    where: {} // Your filters here
})
const userIds = JSON.stringify(users)) // [1,2,3]
defraggled
  • 660
  • 5
  • 11
6

This is how I solved mine

    let rows = await database.Book.findAll(options);
    rows = JSON.stringify(rows);
    rows = JSON.parse(rows);

Note that the query has 'include childModel' i could've used 'raw:true' if it just one model. Stringifying the result clears out the '_previousDataValues' e.t.c and give you plain object, now parse the stringified obect back to json. Took me a long time before I could figure this out.

Ahmed Adewale
  • 2,615
  • 21
  • 17
3

The problem occurs only when I log it using:

console.log(Model.findAll());

If I save it to a variable, I can directly access objects inside without using "dataValues"

Gijo Varghese
  • 10,153
  • 20
  • 69
  • 112
  • This works on JS, but on typescript, the following error will trigger: "error TS2551: Property 'dataValues' does not exist on type 'Model'. Did you mean 'getDataValue'?" For this cases Masoud Tavakkoli answer solve the problem. – Yuri Santos Aug 14 '20 at 18:07