Prisma client query for latest values of each user - javascript

I am new to prisma-client and I want to return the latest value register by each user of a given company.
This is my schema.prisma:
model Locations {
id Int #id #default(autoincrement())
user String
company String
latitude String
longitude String
timestamp String
}
This is what I have tried so far:
const lastLocations = await db.locations.findMany({
where: {
company,
},
orderBy: {
id: 'desc',
},
take: 1,
});
But I need to get 1 value for each user, I solved this previously in sql with:
WITH ranked_messages AS ( SELECT m.*, ROW_NUMBER() OVER (PARTITION BY userID ORDER BY timestamp DESC) AS rn FROM locations AS m ) SELECT * FROM ranked_messages WHERE rn = 1 AND companyID = "${companyID}";`;
But I have no idea how to do proceed in prisma. Is there an "each" method?
I appreciate any help. Thank you.

I solved using distinct option:
const lastLocations = await db.locations.findMany({
where: {
company,
},
distinct: ['user'],
orderBy: {
id: 'desc',
},
});
Thanks.

Related

Sequelize select from select

I want join and filter raw query
const projects = await sequelize.query('SELECT * FROM projects + SQL MAGIC', {
model: Projects,
mapToModel: true,
type: QueryTypes.SELECT,
});
In this query replace projects table with select+magic:
const dinamic_where = {id: 1}
const projects = await Projects.findAll(
where: { ..dinamic_where },
include: [{ model: Organization }],
)
So generated query shall become
SELECT fields,... FROM (SELECT * FROM projects + SQL MAGIC) JOIN organization WHERE organization.id = 1;
bind not suitable because of dinamic_where can contan different number of fields.
If you need to modify FROM part, I think you need to use a little more low level access to Sequelize.
There is a function queryGenerator.selectQuery however this takes string as FROM table name meaning if I do
selectQuery('(...SQL MAGIC)', options, Projects)
This will generate a query string as
SELECT ... FROM '(...SQL MAGIC)' ...
FROM query is taken as a string value which is not a valid SQL.
So, a little hacky workaround.
const customQuery = selectQuery('FROM_TO_BE_REPLACED', options, Projects)
// Use JS string replace to add dynamic SQL for FROM.
// If it is Postgres, double quotes are added by queryGenerator.
// If MySQL, it would be ``
customQuery.replace('"FROM_TO_BE_REPLACED"', '(...SQL MAGIC)')
All in action.
const Model = require("sequelize/lib/model");
const parentOptions = {
where: {
id: 1,
key: 'value'
},
include: [Organization]
};
// This is required when the inline query has `include` options, this 1 line make sure to serialize the query correctly.
Model._validateIncludedElements.bind(Projects)(parentOptions);
const customQuery = sequelize.getQueryInterface()
.queryGenerator
.selectQuery('FROM_TO_BE_REPLACED', parentOptions, Projects);
const fromQuery = '(SELECT * FROM SQL MAGIC)';
const projects = await sequelize.query(customQuery.replace('"FROM_TO_BE_REPLACED"', fromQuery),
{
type: QueryTypes.SELECT
}
);

Prisma client select all rows from a table

how can I select everything from a table with prisma? (SELECT * FROM application)
const applications = prisma.application.findMany({
// Returns all user fields
include: {
posts: {
select: {
age: true,
about_section: true,
user_id: true
},
},
},
})
console.log(applications.age)
Here is how my schema looks:
model application {
application_id Int #id #default(autoincrement())
age String? #db.VarChar(255)
about_section String? #db.VarChar(255)
user_id Int?
users users? #relation(fields: [user_id], references: [user_id], onDelete: Restrict, onUpdate: Restrict, map: "application_ibfk_1")
##index([user_id], map: "user_id")
}
For rows, findMany() without where will return all rows in table:
Get all Records
The following findMany query returns all User records:
const users = await prisma.user.findMany()
For columns/fields, without specifying include or select, prisma has a default:
By default, when a query returns records (as opposed to a count), the
result includes the default selection set:
All scalar fields defined in the Prisma schema (including enums)
None of the relations
For SELECT * FROM application (does not include users relation):
const applications = await prisma.application.findMany();
To futher include users relation in the model:
const applications = await prisma.application.findMany({
include: {
users: true // will include all fields
}
});

Is there a way to update an object in an array of a document by query in Mongoose?

I have got a data structure:
{
field: 1,
field: 3,
field: [
{ _id: xxx , subfield: 1 },
{ _id: xxx , subfield: 1 },
]
}
I need to update a certain element in the array.
So far I can only do that by pulling out old object and pushing in a new one, but it changes the file order.
My implementation:
const product = await ProductModel.findOne({ _id: productID });
const price = product.prices.find( (price: any) => price._id == id );
if(!price) {
throw {
type: 'ProductPriceError',
code: 404,
message: `Coundn't find price with provided ID: ${id}`,
success: false,
}
}
product.prices.pull({ _id: id })
product.prices.push(Object.assign(price, payload))
await product.save()
and I wonder if there is any atomic way to implement that. Because this approach doesn't seem to be secured.
Yes, you can update a particular object in the array if you can find it.
Have a look at the positional '$' operator here.
Your current implementation using mongoose will then be somewhat like this:
await ProductModel.updateOne(
{ _id: productID, 'prices._id': id },//Finding Product with the particular price
{ $set: { 'prices.$.subField': subFieldValue } },
);
Notice the '$' symbol in prices.$.subField. MongoDB is smart enough to only update the element at the index which was found by the query.

Dynamic key name for mongodb Realm

I'm making a digital Christmas Kalendar for a friend. Every day he can claim a Steam game.
So in mongodb in the user account that I made for him there is a key called codes (object). The structure is as follows:
_id: blbalbalba
codes: {
1 : {
title: GTA V,
code: AISHD-SDAH-HAUd,
claimed_at: ,
},
2 : {
title: Fortnite,
code: HHF7-d88a-88fa,
claimed_at: ,
}
}
Just example data. Now in the client app, when button (door) 7 is pressed/opened I want to insert the current date to the key "claimed_at" in the object with key name "7".
I tried some variations of:
const result = await PrivateUserData.updateOne(
{ id: myID },
{ $set: { "codes.`${door_number}`.date_claimed" : date,
}
}
);
But this doesn't work. What did work was: "codes.5.date_claimed". So a static path. In that case the object with name 5 got it's date_claimed key updated.
But how do I use a dynamic path with a variable instead of a number?
Thanks in advance!
If you know the variable value before calling the query i think both of the bellow can work.
var door_number=5;
var date= new Date("...");
const result = await PrivateUserData.updateOne(
{ id: myID },
{ $set : { ["codes."+door_number+".date_claimed"] : date}}
);
var door_number=5;
var date= new Date("...");
const result = await PrivateUserData.updateOne(
{ id: myID },
{ $set : { [`codes.${door_number}.date_claimed`] : date}}
);
If the dynamic behaviour is based on information on the database, send if you can sample data and expected output, so we know what you need.

Use a Mongo Cursor to build a list with another query

I have two mongo collections.
Enrollment:
{UserID: String, CourseID: String, EducatorFlag: boolean}
Courses
{_id: String, courseName: String}
I'm attempting to generate a list of courseNames when given a UserID. This requires me to find all courses that a User is enrolled in. The following function returns just the CourseID of each course a user is in.
var currentCourses = Enrollment.find(
{ UserId: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 });
I'm unsure of how to take this cursor, and use each item in it to run another query and build a list from the output. Basically for each CourseID in currentCourses I need to do
var result = []
result += Courses.find({_id: CourseID}, {fields: {_id: 0, courseName: 1}});
The goal is simply to print all the courses that a user is enrolled in.
You have several options:
Use the cursor directly with a .forEach()
Use .fetch() to transform the cursor into an array of objects and then manipulate that.
Get an array of _ids of enrollments with .map() and directly search the courses with mongo's $in
Let's just use the first one for now since it's pretty simple:
let courseNames = [];
Enrollment.find(
{ UserId: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 }).forEach((e)=>{
let course = Courses.findOne(e.CourseID, { fields: { courseName: 1 }})
courseNames.push(course.courseName);
});
Note: when selecting fields in a query you can't mix exclusions and inclusions.
Getting an array of _ids and using that with $in is also pretty straightforward:
let courseIdArray = Enrollment.find(
{ UserId: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 }).map((e)=>{ return e.CourseID });
let courseNames = Courses.find(
{ _id: { $in: courseIdArray }}).map((c)=>{ return c.courseName });

Categories

Resources