简体   繁体   中英

Sequelize - How can I return JSON objects of the database results only?

So I'm wanting to have the database results returned and nothing else. At the moment I'm getting returned a large chunk of JSON data (Like below):

But I'm only needing the [dataValues] attribute. I don't want to have to use the this bit of JSON to retrieve it: tagData[0].dataValues.tagId .

I just noticed: When it finds and DOESN'T CREATE , it will return the JSON for the database results, but when it DOESN'T FIND and creates, it returns the un-needed JSON blob (Like below) Is there a way around this?

[ { dataValues:
     { tagId: 1,
       tagName: '#hash',
       updatedAt: Fri Dec 25 2015 17:07:13 GMT+1100 (AEDT),
       createdAt: Fri Dec 25 2015 17:07:13 GMT+1100 (AEDT) },
    _previousDataValues:
     { tagId: 1,
       tagName: '#hash',
       createdAt: Fri Dec 25 2015 17:07:13 GMT+1100 (AEDT),
       updatedAt: Fri Dec 25 2015 17:07:13 GMT+1100 (AEDT) },
    _changed:
     { tagId: false,
       tagName: false,
       createdAt: false,
       updatedAt: false },
    '$modelOptions':
     { timestamps: true,
       instanceMethods: {},
       classMethods: {},
       validate: {},
       freezeTableName: true,
       underscored: false,
       underscoredAll: false,
       paranoid: false,
       whereCollection: [Object],
       schema: null,
       schemaDelimiter: '',
       defaultScope: null,
       scopes: [],
       hooks: {},
       indexes: [],
       name: [Object],
       omitNull: false,
       sequelize: [Object],
       uniqueKeys: [Object],
       hasPrimaryKeys: true },
    '$options':
     { isNewRecord: true,
       '$schema': null,
       '$schemaDelimiter': '',
       attributes: undefined,
       include: undefined,
       raw: true,
       silent: undefined },
    hasPrimaryKeys: true,
    __eagerlyLoadedAssociations: [],
    isNewRecord: false },
  true ]

Instead of getting the big blob like the above I only need the RAW json results (Like below):

{ tagId: 1,
       tagName: '#hash',
       updatedAt: Fri Dec 25 2015 17:07:13 GMT+1100 (AEDT),
       createdAt: Fri Dec 25 2015 17:07:13 GMT+1100 (AEDT) },

I've used the following javascript. I did try add raw: true , but it didn't work?

    // Find or create new tag (hashtag), then insert it into DB with photoId relation
module.exports = function(tag, photoId) {
    tags.findOrCreate( { 
        where: { tagName: tag },
        raw: true
    })
    .then(function(tagData){
        // console.log("----------------> ", tagData[0].dataValues.tagId);
        console.log(tagData);
        tagsRelation.create({ tagId: tagData[0].dataValues.tagId, photoId: photoId })
        .then(function(hashtag){
            // console.log("\nHashtag has been inserted into DB: ", hashtag);
        }).catch(function(err){
            console.log("\nError inserting tags and relation: ", err);
        });
    }).catch(function(err){
        if(err){
            console.log(err);
        }
    });

}

Edit:

So I've investigated a bit and it seems that the big JSON blob is only returned when Sequelize is creating and not finding.

Is there a way around this or not?

Edit 2:

Okay so I've found a workaround, which could be turned into a re-usable function. But if there's something built into Sequelize , I'd prefer to use that.

var tagId = "";

// Extract tagId from json blob
if(tagData[0].hasOwnProperty('dataValues')){
    console.log("1");
    tagId = tagData[0].dataValues.tagId;
} else {
    console.log("2");
    console.log(tagData);
    tagId = tagData[0].tagId;
}

console.log(tagId);
tagsRelation.create({ tagId: tagId, photoId: photoId })

Edit 3:

So, I don't think there is an "Official" sequelize way of achieving this so I simply wrote a custom module which returns the JSON data that's needed. This module can be customised and extended to suit various situations: If anyone has any suggestions to how the module can be improved feel free to comment :)

In this module we're returning a Javascript Object. If you want to turn it into JSON just stringify it using JSON.stringify(data) .

// Pass in your sequelize JSON object
module.exports = function(json){ 
    var returnedJson = []; // This will be the object we return
    json = JSON.parse(json);


    // Extract the JSON we need 
    if(json[0].hasOwnProperty('dataValues')){
        console.log("HI: " + json[0].dataValues);
        returnedJson = json[0].dataValues; // This must be an INSERT...so dig deeper into the JSON object
    } else {
        console.log(json[0]);
        returnedJson = json[0]; // This is a find...so the JSON exists here
    }

    return returnedJson; // Finally return the json object so it can be used
}

Edit 4:

So there is an official sequelize method. Refer to the accepted answer below.

Though poorly documented, this does exist in Sequelize.

Couple Ways:

1. For any response object that resulted from a query, you can extract only the data you want by appending .get({plain:true}) the the response like so:

Item.findOrCreate({...})
      .spread(function(item, created) {
        console.log(item.get({
          plain: true
        })) // logs only the item data, if it was found or created

Also make sure you are using the spread callback function for your type of dynamic query promise. And note that you have access to a boolean response, created , which signifies whether or not a create query was executed.

2. Sequelize provides the raw option. Simply add the option {raw:true} and you will receive only the raw results. This will work on an array of results, the first method should not, as get will not be a function of an array.

If you want to work only with the values of an instance try to call get({plain: true}) or toJSON()

tags.findOrCreate( { 
    where: { tagName: tag }
})
.then(function(tagData){
     console.log(tagData.toJSON());
})

Updated:

Use data.dataValues

db.Message.create({
    userID: req.user.user_id,
    conversationID: conversationID,
    content: req.body.content,
    seen: false
  })
  .then(data => {
    res.json({'status': 'success', 'data': data.dataValues})
  })
  .catch(function (err) {
    res.json({'status': 'error'})
  })

Now easier to read with async/await syntax

module.exports = async function(tagName) {
  const [tag, created] = await Tag.findOrCreate({
    where: {tagName},
    defaults: {tagName}
  });
  return tag.get({plain:true});
}

sequelize-values is an npm-module which helps you do this. It has methods which easily prints the values on both single item and list of results (array) https://www.npmjs.com/package/sequelize-values

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM