Sequelize attributes in findOne returning all fields - node.js

I have
db.User.findOne({
attributes: ['id', 'firstName', 'lastName', 'email', 'phoneNumber', 'createdAt', 'type', 'status'],
where: {
id: id
}
}).then(function(dbUser) {
console.log(dbUser);
});
And it's returning all of the fields, not just the ones I specify in attributes. What am I doing wrong?

According to the docs, you're doing absolutely nothing wrong. I'm seeing similar behavior. Sequelize seems to be going through some growing pains. :\

The code provided works with version 7 at least.
const user = await User.findOne({
attributes : ['id','name','email','contact'],
where: {email:req.body.email}
});
Response from postman
{
"status": "success",
"user": {
"id": 1,
"name": "admin",
"email": "admin#eatanddrink.io",
"contact": "0724466628"
},
}

db.animals.findOne({ },{_id:0, numlegs:1,class:1, name:1}) returns only the specific fields.

Related

Sequelize exclude returns different value

So when I query without attribute: exclude... it returns me the correct user, but when I insert that in the query it returns a completly different user. Here is the code that I'm inserting.
const user = await Users.findOne(
{
attributes: { exclude: ["password", "admin", "createdAt", "updatedAt"] },
},
{ where: { id: req.user.id } }
);
res.json({ user });
Any ideas why is this happening?
Thanks in advance
You'r passing the where condition to the second paramter, but according to the docs: https://sequelize.org/docs/v6/core-concepts/model-querying-finders/#findone
Model.findOne only has one parameter which is the query options.
Move your where condition into the object for the first parameter.
const user = await Users.findOne({
attributes: {
exclude: ["password", "admin", "createdAt", "updatedAt"],
},
where: { id: req.user.id },
});
res.json({ user });

Typeorm relations query builder

I have a little problem figuring out how to get data from a linked table using queryBuilder
Currently i have this code:
const users = await databaseConntection
.getRepository(User)
.createQueryBuilder("user")
.select(["images.author_id", "user.id", "user.username"])
.leftJoinAndSelect(
(queryBuilder) =>
queryBuilder
.select(["title", "updated_at", "author_id"])
.from(Image, "image")
.orderBy({ updated_at: "ASC" })
.take(5),
"images",
"images.author_id = user.id"
)
.andWhere("username LIKE :profile")
.setParameters({
profile: `%${profile}%`,
})
.groupBy("images.author_id")
.take(limit)
.skip(page * limit - limit)
.getRawMany();
Current result:
column "user.id" must appear in the GROUP BY clause or be used in an aggregate function
Expected result:
[
{
"id": 1,
"username": "some username",
"images": [
{
"title": "some image title",
"updated_at": "2021-05-21T03:49:44.299Z",
"author_id": 1
}
...rest 4 images
]
}
...rest users
]
How i can achieve this result using query builder?
Thanks for any helping.
I don't know what is wrong with my code, but i was migrate to prisma orm, and he work like as expected.
Here the code using prisma orm, and this return the expected result (without ids):
const users = await prisma.user.findMany({
where: {
username: {
contains: profile as string,
},
},
select: {
username: true,
images: {
select: {
title: true,
updated_at: true,
},
orderBy: {
updated_at: "asc",
},
take: 5,
},
},
take: limit,
skip: page * limit - limit,
});

Lowdb - push data into an array inside another array

I'm basicaly trying to do a inventory for each user, to do this i used Lowdb to help me out with the data.
My current structure is like this:
{
"users": [
{
"id": "450453034724491266",
"tag": "Briggs#4992",
"inventory": [
{"itemID": "1320488779", "rarity": "rare"},
{"itemID": "1674364779", "rarity": "common"},
]
},
{
"id": "272659147974115328",
"tag": "Zytekaron#0572",
"inventory": [
{"itemID": "1320488779", "rarity": "rare"},
{"itemID": "1674364779", "rarity": "common"},
]
}
]
}
what I have in mind is something like
//get 'users', find the id and then write inside the inventory array (which i dont know how to)
db.get('users')
.find({ id: 'id' })
Tested this code snippet and it is working perfectly.
// Get your user
let inventory = db
.get('users')
.find({ id: '272659147974115328' })
.get('inventory')
.value();
// Do something to your user's inventory
inventory.push({ itemID: '9999999', rarity: 'common' });
// Update the user with the modified inventory
db.get('users')
.find({ id: '272659147974115328' })
.assign({ inventory })
.write();
two quick answers:
get the object by the id. modify->replace-save;
you can do an assign like: object.assign({inventory:[newInventory]}).write();
where object is your user you just got from the db.
It should be possible to use push directly:
db
.get('users')
.find({ id: '272659147974115328' })
.get('inventory')
.push({ itemID: '9999999', rarity: 'common' })
.write();

How to remove associations from the output in Sequelize?

I have a classMethod defined for the Model User
// model user.js
classMethods: {
associate: function(models) {
User.belongsToMany(models.project, {through: 'user_project', foreignKey: 'user_id', otherKey: 'project_id'})
}
}
From a route in Express i then query for the projects of this user and output it as JSON
user.getProjects({
attributes: ['id', 'title'],
})
.then(function(projects) {
res.json(projects)
})
This works fine, except for the fact the output also contains the user_project property which I would like to hide/omit/remove
[
{
"id": 8,
"title": "Some project",
"user_project": {
"created_at": "2017-02-16T22:52:48.000Z",
"updated_at": "2017-02-16T22:52:48.000Z",
"project_id": 8,
"user_id": 5
}
},
//etc.
I have tried various exclude and include statements, but the output always contains it.
Is there a way to not have this show up in the output?
I stumbled upon the solution.
To remove the attributes from the joined table you can use joinTableAttributes, like so:
user.getProjects({
attributes: ['id', 'title'],
joinTableAttributes: []
})
.then(function(projects) {
res.json(projects)
})
By doing that, it will remove the (see OP) output of the user_project table, and the result is:
[
{
"id": 8,
"title": "Test Project",
},
{
"id": 4,
"title": "Another one",
}
]
You should try the following
user.getProjects({
attributes: ['id', 'title'],
through: {
attributes: []
}
})
.then(function(projects) {
res.json(projects)
})
The only way it works for me is to define the DefaultScope of the middle table as
{ attributes: [] }
I am using Sequelize#5
I am using sequelize: "^6.18.0", joinTableAttributes doesn't work for me .
I just use like :
user.getProjects({
attributes: ['id', 'title'],
through: {
attributes: []
}
})

Populating nested properties with Mongoose

In the API I'm trying to write with Node and Mongoose, the following query:
User.findOne({username: req.params.username}, "-_id -__v")
.populate({path: "songs", select: "-_id -__v"})
.populate({path: "following", select: "-_id username email"})
.exec(function(err, user) {
res.send(user);
});
returns the following JSON:
{
"email": "alice#alice.org",
"username": "alice",
"following": [
{
"username": "john",
"email": "john#john.org"
}
],
"songs": [
{
"slug": "dvorak-cello-concerto",
"artist": "5403e825cc9c45e9c55c4e7d",
"title": "Cello Concerto"
}
]
}
In the songs schema, I've setup artist as the following:
artist: {type: Schema.Types.ObjectId, ref: 'User'}
What is the best way to also populate the 'artist' property in every song that's populated in the initial query, rather than just its _id which references the user that song belongs to?
I figured out a way to do this, but please correct me if there's a better/cleaner way of doing it.
User.findOne({username: req.params.username}, "-_id -__v")
.populate({path: "songs", select: "-_id -__v"})
.exec(function(err, user) {
Songs.populate(user, {
path: 'songs.artist',
select: '-_id username',
model: 'User'
}, function (err, user) {
res.send(user);
});
});
Also, I'm only returning the 'username' value for the user which is all I need, but 'artist' still ends up being an object with that one property. If anybody knows how to return that value just as a string.
I'd love to know how.

Resources