Ordering by multiple columns in Prisma - prisma

I know currently Prisma doesn't support ordering by multiple scalars fields, (see this issue: https://github.com/prisma/prisma/issues/62).
But, I'm wondering if there is someone who found a solution to work around this issue without using executeRaw mutation (raw SQL) because I have many places in my code where I need to order by multiple fields and I don't want to use executeRaw in so many places.
I will appreciate any suggestions. Thank you!

Since Prisma 2.4 this should be basically possible by using array in orderBy:
const users = await prisma.user.findMany({
select: {
email: true,
role: true,
},
orderBy: [
{
email: 'desc',
},
{
role: 'desc',
}
],
})
Find more in docs: https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#sort-user-by-multiple-fields---email-and-role

I don't think there's a solution, In my project, I need random order, increment/decrement, aggregation... use raw finally.

Related

How to target a field in Prisma and get a flat array of values rather than an array of objects

I just started using Primsa 2 so I am still a noob at this but all I am trying to do is create a flat array of strings(Array<number>) based on the values I get from a specific field. Right now when I target that field it gives me an array of objects like this: userIds: [{ issueId: 1, userId: 1 }]
All I want is the value I get from the userId key and the array to return like this userIds: [ 1 ]. I was able to fix this with some formatting code after the query which was done like so:
const issues = project.issues.map(issue => ({ ...issue, userIds: [...issue.userIds.map((id) => id.userId)] }))
const _project = { ...project, issues }
However, this doesn't seem like the most optimal solution. If this is the only way that is fine but I assume with the power that Prisma has for querying, this is something I can do just in the query alone?
For reference, my query currently looks like this:
const project = await prisma.project.findFirst({
where: { id: req.currentUser.projectId },
include: { users: true, issues: { include: { userIds: true } } },
})
Thanks in advance!
Can you show your schema? Perhaps you can model the relation differently. However, unless if you provide a field, userIds, that is a flat array and not a field of a an other relation it will be returned as a list of objects as you have already.

What is the best way to expose total number of Pages in Prisma2 using nexus?

I am switching to Prisma2 using nexus and cannot find a good way to implement pagination - a skip type will work fine. I could find a good way to implement it on the array, so what I ended up is added a computed field total on the type.
export const User = objectType({
name: 'User',
definition(t) {
t.model.id()
t.model.name()
...
t.field('total', {
type: 'Int',
resolve: async (parent, args, ctx, info) => {
let users = await ctx.photon.users.findMany()
return users.length
},
})
It's usable, but I am sure that there is a better way... can anyone give me a hint?
Latest prisma2 has count().
prisma.user.count() gives total number of users and then number of pages is count/limit.
source: https://github.com/prisma/prisma2/blob/master/docs/prisma-client-js/api.md

What exactly is "data" that is passed to responses?

I'm writing a custom response that takes data as an input, and I am finding strange properties being added, namely:
add: [Function: add],
remove: [Function: remove]
When I log out some example data, I get:
[ { books:
[ { id: 1,
title: 'A Game of Thrones',
createdAt: '2015-08-04T04:53:38.043Z',
updatedAt: '2015-08-04T04:53:38.080Z',
author: 1 } ],
id: 1,
name: 'George R. R. Martin',
createdAt: '2015-08-04T04:53:38.040Z',
updatedAt: '2015-08-04T04:53:38.073Z' },
{ books:
[ { id: 2,
title: 'Ender\'s Game',
createdAt: '2015-08-04T04:53:38.043Z',
updatedAt: '2015-08-04T04:53:38.080Z',
author: 2 },
{ id: 3,
title: 'Speaker for the Dead',
createdAt: '2015-08-04T04:53:38.043Z',
updatedAt: '2015-08-04T04:53:38.081Z',
author: 2 } ],
id: 2,
name: 'Orson Scott Card',
createdAt: '2015-08-04T04:53:38.042Z',
updatedAt: '2015-08-04T04:53:38.074Z' } ]
Which looks innocent enough, but results in the strange add and remove functions when I use a custom serializer on it. If I take this data and hard-code it straight into the serializer, those are not present. Apparently something is lurking inside of data that's not being printed to the console.
So, what is data?
Edit: So, I'm still not quite sure what other magical properties live in here, but:
Object.keys(data[0].books))
reveals
[ '0', 'add', 'remove' ]
Which is where those are coming from. Why is this included in the data passed to custom responses? And what else might be hiding in there...
More importantly, how do I strip this gunk out and make data a normal object?
JSON.parse(JSON.stringify(data));
That cleans it up nicely, though it feels like a hack. (Actually, it's definitely a hack.)
I assume your data attribute is returned by a database query. e.g.:
Model.find(...).exec(function (err, data) { ... });
But what are these .add() and .remove() methods?
Here is what you can find in the docs:
For the most part, records are just plain old JavaScript objects (aka POJOs). However they do have a few protected (non-enumerable) methods for formatting their wrapped data, as well as a special method (.save()) for persisting programmatic changes to the database.
We can go deeper:
"collection" associations, on the other hand, do have a couple of special (non-enumerable) methods for associating and disassociating linked records. However, .save() must still be called on the original record in order for changes to be persisted to the database.
orders[1].buyers.add({ name: 'Jon Snow' });
orders[1].save(function (err) { ... });
So these methods (.add(), .remove(), .save()) are useful if you play with "collection" associations.
How to remove them?
You'll need to use .toObject() which returns a cloned model instance stripped of all instance methods.
You might want to use .toJSON() that also returns a cloned model instance. This one however includes all instance methods.

Can I use Sails native query with populate?

I am using the native method of sails-mongo to query a collection. I need to use native to access some of the Mongo geospatial query features.
I would like to use the sails populate syntax to include associated models.
Is there a way to do this?
Here is an example of my existing code:
Trip.native(function(err, collection) {
collection.find(
{
"locationTo": {
"$near": {
"$maxDistance": 80467.35439432222,
"$geometry": {
"type": "Point",
"coordinates": [-117.133655, 32.720519]
}
}
}
}
)
.toArray(function(err, trips) {
console.log("Trips nearby:", trips);
});
});
Here is my Trip model for reference.
var Trip = {
attributes: {
owner: {
model: 'User'
},
title: 'string',
addressFrom: 'string',
locationFrom: 'json', // geoJson
dateTimeDepart: 'datetime',
dateTimeArrive: 'datetime',
dateTimeReturn: 'datetime',
addressTo: 'string',
locationTo: 'json', // geoJson
driver: {
model: 'User'
},
status: {
type: 'string',
defaultsTo: 'PENDING'
}
}
}
Would be helpful if you share the Trip model as well. If the field you wish to populate has type "collection" (not "array"), you should be able to populate it just fine.
Update: Alright, I got your question wrong. There doesn't seem to be any way of populating directly after a native call. There's really not much you can do with a native call as far as Waterline functions are concerned. I would suggest either running another query(Waterline) after you've fetched locationTo or populating the fields yourself since you only need to populate two of them(and that too from the same model). I can't think of anything that would suffice with a single query.
Thanks, I ended up doing it in two queries for now.
First, I build an array of matching ID's via the native query.
var tripIdList = trips.map(function (trip) {
return trip._id
});
Second, I do a normal find query using the ID list. It's not a single query but works well. Thanks for the help
Trip.find(filter)
.where({id: tripIdList})
.populate('driver')
.exec(function (err, trips) {
console.log("Trips:", trips);
}

Update values in array in MongoDB

I'm trying to come up with a way to update the values in an array of objects in mongo. I have a collection which looks like
[
{ CourseName: '',
Sessions: [
{
_id: null, //oops I didn't set this in the import
Name: 'blah',
Location: 'moon'
}]
}
]
Now I need to set the _id field. I tried the documented approach of doing
db.Course.update({'Sessions._id': null}, {$set:{'Sessions.$._id': ObjectId()}}, false, true)
But I ran into this bug http://jira.mongodb.org/browse/SERVER-1055 which meant that I couldn't do it. Is there some syntax which will allow me just to itterate over the collection and update each record by hand? I tried a few things like
db.Course.find().forEach(
function(course)
{
course.Sessions.forEach(function(session)
{
session._id=ObjectId();
course.Save(session); //Don't know how to save a single object
});
});
but they didn't work. I'm looking for some way to just update that value in each session.
I think what you want is:
db.Course.find().forEach(
function(course)
{
course.Sessions.forEach(function(session)
{
session._id=ObjectId();
});
db.Course.save(course);
});
However, you can run into problems saving stuff into a collection you're in the middle of iterating over, so I'd suggest loading a bunch of documents into an array, processing them, loading another batch, etc.