having an array with unique names, how can i update the elemets of those names using prisma(in nextjs).
I mean something Like:
const arr=['Joe', 'Mark'];
const update=await prisma.user.updateMany({
where: {
name: //What should i put to update both Joe and Mark?
},
data: {
notifications: {push: "Hello"}
}
});
I'm using PSQL and i don't know if it matters.
Try this:
const arr=['Joe', 'Mark'];
const update=await prisma.user.updateMany({
where: {
name: {in: arr}
},
data: {
notifications: {push: "Hello"}
}
});
"in" will check if name matches anything in that array.
Here is the list of other filters: https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#filter-conditions-and-operators
I just want to change the value of a key of all the objects inside an array
What I want actually -
The object which I queried from the database is -
{
_id: 61389277fa5c742caf959885,
title: 'What is GRE?',
forumTab: 'GRE',
askedAt: 2021-09-08T10:37:43.979Z,
askedBy: {
_id: 60f0a6a9b4259f7ef9c49cc8,
}
}
I want to add more key-value pairs in the askedBy key by again querying the database for the User with the given _id
Now, the user object which is queried is -
{
role: 'student',
_id: 60f0a6a9b4259f7ef9c49cc8,
firstName: 'Rishav',
lastName: 'Raj'
}
Finally I want to return the below object in response -
{
_id: 61389277fa5c742caf959885,
title: 'What is GRE?',
forumTab: 'GRE',
askedAt: 2021-09-08T10:37:43.979Z,
askedBy: {
_id: 60f0a6a9b4259f7ef9c49cc8,
role: 'student',
firstName: 'Rishav',
lastName: 'Raj'
}
}
I am creating a new array questionsToSend and pushing the object with updated key-value pairs which I am getting after querying the database for each elements in the questions array, I have created functions for respective query that I need to render in sequence, even after rendering the functions in proper sequence why the new array questionsToSend is not populating with the objects before returning the response?
router.get("/questions", async (req, res) => {
if (!req.query.forumTab) return res.status(400).send("something went wrong");
const page = parseInt(req.query.page) - 1;
const perPage = parseInt(req.query.perPage);
let questionsToSend = [];
const func0 = async (callback) => {
const questions = await Question.find({ forumTab: req.query.forumTab })
.sort({ askedAt: -1 })
.limit(perPage)
.skip(perPage * page);
console.log("xxxxxxx");
callback(questions);
};
const func1 = async (questions, callBack) => {
questions.forEach(async (question) => {
const askedUserData = await User.findById(question.askedBy._id);
if (!askedUserData) {
const index = questions.indexOf(question);
questions.splice(index, 1);
return;
}
questionsToSend.push({
..._.pick(question, [
"_id",
"title",
"askedAt",
"tags",
]),
askedUserData,
});
console.log(questionsToSend);
});
console.log("yyyyyyyy");
callBack();
};
func0(
(questions) =>
func1(questions, async () => {
console.log("zzzzzzzz");
res.status(200).send(questionsToSend);
})
);
});
We can use aggregation to achieve this
Question.aggregate([
{
$match: { forumTab: req.query.forumTab }
},
{
$lookup: {
from: 'users',
localField: 'askedBy._id',
foreignField: '_id',
as: "user"
}
},
{ $unwind: "$user"},
{ "$addFields": {
"askedBy": {
"$mergeObjects": ["$askedBy", "$user"]
}
}
},
{ $project: { "user" : 0} },
{ $sort: {"askedAt": -1}},
{ $skip: perPage * page},
{ $limit: perPage},
])
$match is used to apply filter
$lookup is used to do a join on a collection. I have assumed the collection name is users.
$lookup returns the matched result as an array. Converting it to object using $unwind since we get only one back.
$addFields with $mergeObjects is merging the existing askedBy field and newly user field
Removing the user field from the result set with $project.
And then sort, skip and limit.
I need to make a select from MySQL with the selection values in an array. I have data like this:
const CompaniesRelation = [{CompanyId: ""},{CompanyId: ""},{CompanyId: ""},{CompanyId: ""},{CompanyId: ""}];
With Companies Relation I need to select/find, I need to get all the information for each CompanyId's:
const Companies: Array<Company> = await getRepository(Company).find({ where:{ CompanyId: CompaniesRelation[0].CompanyId, IsActive: true} });
I'm using TypeOrm in Angular. I need to select the information for each object into CompaniesRelation. I need to use fewest selects to DB, in other words, foreach is not the way.
For the final result I need to have an array with all the information of each company in Companies Relation, like this:
[{CompanyId: "", Name: "", fk:""},{CompanyId: "", Name: "", fk:""},{CompanyId: "", Name: "", fk:""}]
How you use WHERE x IN explained in find options for find*, and adding WHERE expression for QueryBuilder.
First get your Company Ids into an array of integers:
const companyIds = [1, 2, 3];
or
const companySel = [{ CompanyId: 1 }, { CompanyId: 2 }, { CompanyId: 3 }];
const companyIds = companySel.map(a => a.CompanyId);
Then you can use the In operator with find
import {In} from "typeorm";
const companyList = await getRepository(Company)
.find({ where: { CompanyId: In (companyIds ) } });
Or you can use the TypeOrm QueryBuilder with "IN" (note the :... syntax)
const companyList = await getRepository(Company)
.createQueryBuilder()
.where("CompanyId IN (:...ids )", { ids: companyIds ) })
.getMany();
Hey I was wondering how do I use findById for a schema inside an array? For example, I have the following Schema:
const GameSchema = new mongoose.Schema({
users: [
{
user: { type: mongoose.Schema.ObjectId, ref: 'User' },
role: {
type: String,
required: true,
enum: ['user', 'moderator', 'creator'],
default: 'user',
},
},
]
}]
I want to find the user with a mongoose function like findById, such as the following:
const user = await game.users.findById({ user: req.user.id })
It doesn't seem to work since users is not a mongodb model. I know I can find the user by using find() like the following:
const user = await game.users.find(
(gameUser) => gameUser.user == req.user.id
)
The only problem is that the type of gameUser and req.user.id is not the same and I can't use '==='. Is there some way to go through the array and use the mongoose function findById?
As docs explains, findById method:
Finds a single document by its _id field
So you have to use findOne() instead of findById().
Also, to return only one field from the entire array you can use projection into find.
Check this example. This query find an object by its id (i.e. user field) and return only the object, not the whole array.
db.collection.find({
"users": { "$elemMatch": { "user": 1 } }
},
{
"users.$": 1
})
Using mongoose you can do:
yourModel.findOne(({
"users": { "$elemMatch": { "user": 1 } }
},
{
"users.$": 1
})).then(result => {
console.log(result)
}).catch(e => {
// error
})
I am looking for group by queries through Sequelize and cannot seem to find any documentation.
SELECT column, count(column)
FROM table
GROUP BY column
issue: https://github.com/sequelize/sequelize/issues/348
User.findAll({
group: ['field']
})
i use sequelize#2.0.0-dev9
I think you looking for something like this:
Table.findAll({
attributes: ['column1',
sequelize.fn('count', sequelize.col('column2'))],
group: ["Table.column1"]
}).success(function (result) { });
Update: Newer versions of Sequelize uses .then instead of .success.
Table.findAll({
attributes: ['column1',
sequelize.fn('count', sequelize.col('column2'))],
group: ["Table.column1"]
}).then(function (result) { });
Group by with count sequelize ORM
'field' - custom user input, you can rename this string, it's your field(column) in database
'count' - reserved sequelize keyword string need for get count in sequelize
'cnt' - custom user input, you can rename this string, it's your output count
Sequelize version 3.25.0
User.findAll({
attributes: ['field', [sequelize.fn('count', sequelize.col('field')), 'cnt']],
group: ['field'],
})
Try this -
Table.count(
{
attributes: ['column'],
group: 'column',
}
Example: how to add an convenient alias to the grouped function column.
I did this as a separate response mostly because it wouldn't format well in a comment... otherwise I would have just added it to Sampat's answer.
function getSumsBySomeId() {
const criteria = {
attributes: ['some_id', [sequelize.fn('sum', sequelize.col('some_count')), 'some_count_sum']],
group: ['some_id'],
raw: true
};
return Table.getAll(criteria);
}
YIELDS:
{ some_id: 42, some_count_sum: 100 },
{ some_id: 43, some_count_sum: 150 }
...
etc.
Your code should look something like these using ES6 standard.
Table.findAll({ attributes: ['column1', sequelize.fn('count', sequelize.col('column2'))], group: ["Table.column1"] }).then( (result) => { })
**Try this*
Table.findAll({
group: ['column']
})
You need to use row.get('count') to get the count, row.count won't work
The API mentioned at in this answer is correct, but there were a few tricks I was missing in order to actually get the count results out.
As mentioned at: How do I select a column using an alias you need to use .get() for attribute aliased columns for some reason.
And another thing: you need to use parseInt to get an integer out of PostgreSQL count: Postgres sequelize raw query to get count returns string value due to bigint shenanigans.
Minimal runnable example also demonstrating ORDER BY, WHERE and HAVING:
main.js
#!/usr/bin/env node
// https://cirosantilli.com/sequelize-example
const assert = require('assert')
const { DataTypes, Op } = require('sequelize')
const common = require('./common')
const sequelize = common.sequelize(__filename, process.argv[2])
;(async () => {
const UserLikesPost = sequelize.define('UserLikesPost', {
userId: {
type: DataTypes.INTEGER,
},
postId: {
type: DataTypes.INTEGER,
},
}, {})
await UserLikesPost.sync({force: true})
await UserLikesPost.create({userId: 1, postId: 1})
await UserLikesPost.create({userId: 1, postId: 2})
await UserLikesPost.create({userId: 1, postId: 3})
await UserLikesPost.create({userId: 2, postId: 1})
await UserLikesPost.create({userId: 2, postId: 2})
await UserLikesPost.create({userId: 3, postId: 1})
await UserLikesPost.create({userId: 4, postId: 1})
// Count likes on all posts but:
// - don't consider likes userId 4
// - only return posts that have at least 2 likes
// Order posts by those with most likes first.
const postLikeCounts = await UserLikesPost.findAll({
attributes: [
'postId',
[sequelize.fn('COUNT', '*'), 'count'],
],
group: ['postId'],
where: { userId: { [Op.ne]: 4 }},
order: [[sequelize.col('count'), 'DESC']],
having: sequelize.where(sequelize.fn('COUNT', '*'), Op.gte, 2)
})
assert.strictEqual(postLikeCounts[0].postId, 1)
assert.strictEqual(parseInt(postLikeCounts[0].get('count'), 10), 3)
assert.strictEqual(postLikeCounts[1].postId, 2)
assert.strictEqual(parseInt(postLikeCounts[1].get('count'), 10), 2)
assert.strictEqual(postLikeCounts.length, 2)
await sequelize.close()
})()
common.js
const path = require('path');
const { Sequelize } = require('sequelize');
function sequelize(filename, dialect, opts) {
if (dialect === undefined) {
dialect = 'l'
}
if (dialect === 'l') {
return new Sequelize(Object.assign({
dialect: 'sqlite',
storage: path.parse(filename).name + '.sqlite'
}, opts));
} else if (dialect === 'p') {
return new Sequelize('tmp', undefined, undefined, Object.assign({
dialect: 'postgres',
host: '/var/run/postgresql',
}, opts));
} else {
throw new Error('Unknown dialect')
}
}
exports.sequelize = sequelize
package.json:
{
"name": "tmp",
"private": true,
"version": "1.0.0",
"dependencies": {
"pg": "8.5.1",
"pg-hstore": "2.3.3",
"sequelize": "6.5.1",
"sqlite3": "5.0.2"
}
}
and PostgreSQL 13.4 on Ubuntu 21.10. GitHub upstream.
Generated PostgreSQL query:
SELECT
"postId",
COUNT('*') AS "count"
FROM
"UserLikesPosts" AS "UserLikesPost"
WHERE
"UserLikesPost"."userId" != 4
GROUP BY
"postId"
HAVING
COUNT('*') >= 2
ORDER BY
"count" DESC;
JOIN + GROUP BY + aggregate
See: Sequelize query with count in inner join
To create a query like
SELECT key, COUNT(ref) FROM MyModel GROUP BY key
You can do this as follows
const results = await MyModel.findAll({
attributes: ['key', [Sequelize.fn('COUNT', Sequelize.col('ref')), 'count']],
group: ['key']
});
Optionally you can cast the result to something like (MyModel & { count: number })[]
Finally, to extract the count for each row, you'll need to use the getDataValue function. e.g.
results.map(r => r.getDataValue('count'))