How to create Categories and its SubCategory in Prisma ORM using MongoDB - mongodb

type Category {
id: ID! #id
name: String!
}
type SubCategoryLevel1 {
id: ID! #id
name: String!
parentCategory: Category! #relation(link: INLINE)
}
type SubCategoryLevel2 {
id: ID! #id
name: String!
parentCategory: SubCategoryLevel1! #relation(link: INLINE)
}
What if my Category levels are not decided, I'm using Prisma ORM and MongoDB.

Not sure I correctly understand your question. Could you go into a bit more detail what you are trying to do?
Are you trying to do arbitrarily deeply nested self-relations? Then you can do something like this:
type Category {
id: ID! #id
name: String!
subCategory: Category #relation(name:"SubToParent"link: INLINE)
parentCategory: Category #relation(name: "SubToParent")
}
Creating three levels would work with this query:
mutation createCategory {
createCategory(
data: {
name: "firstLevel"
subCategory: {
create: {
name: "secondLevel"
subCategory: { create: { name: "thirdLevel" } }
}
}
}
) {
name
}
}
And querying for categories would give you this response:
query allCategories {
categories {
name
subCategory {
name
}
parentCategory {
name
}
}
}
{
"data": {
"categories": [
{
"name": "firstLevel",
"subCategory": {
"name": "secondLevel"
},
"parentCategory": null
},
{
"name": "secondLevel",
"subCategory": {
"name": "thirdLevel"
},
"parentCategory": {
"name": "firstLevel"
}
},
{
"name": "thirdLevel",
"subCategory": null,
"parentCategory": {
"name": "secondLevel"
}
}
]
}
}
I hope that helps, if not just explain your question in a bit more detail.

Related

PRISMA - How to filter the relation nested after m2m relation?

How to filter a relation nested after m2m relation?
Unfortunately as for 2022-11 in Prisma documentation there isn't any info about that.
Schema.prisma:
model Entity {
id Int #id #default(autoincrement())
name String
service_entity_m2m ServiceEntityM2m[]
}
model Service {
id Int #id #default(autoincrement())
service_entity_m2m ServiceEntityM2m[]
}
model ServiceEntityM2m {
id Int #id #default(autoincrement())
entity_id Int
entity Entity #relation(fields: [entity_id], references: [id])
service_id Int
service Service #relation(fields: [service_id], references: [id])
}
Schema.graphql:
type Entity {
id: ID!
name: String
}
type Service {
id: ID!
service_entity_m2m: [ServiceEntityM2m]
}
type ServiceEntityM2m {
id: ID!
entity: Entity!
service: Service!
}
seeder:
// services
{
id: 1
}
// service_entity_m2m:
{
id: 1,
service_id: 1,
entity_id: 1
},
{
id: 2,
service_id: 1,
entity_id: 2
}
// entities
{
id: 1,
name: "XYZ"
},
{
id: 2,
name: "Test"
}
This code:
context.prisma.service.findMany({
where: { service_entity_m2m: { some: { entity: { name: { contains: "Test" } } } } },
include: { service_entity_m2m: { include: { entity: true } } },
})
returns both entities:
[
{
id: 1,
service_entity_m2m:
[
{
id: 1,
entity: {
id: 1,
name: "XYZ"
}
},
{
id: 2,
entity: {
id: 2,
name: "Test"
}
}
]
}
]
How to write a query that is going to return only one entity with the name "Test": ?
[
{
id: 1,
service_entity_m2m:
[
{
id: 2,
entity: {
id: 2,
name: "Test"
}
}
]
}
]

GraphQL with Mongoose and MongoDB tips on deeply nested objects in arrays

I can't find any answers or tips on how to work with deeply nested data with GraphQL and Mongoose. I would've thought this is a fairly common thing to do, but the docs are also pretty vague when it comes to stuff like this.
Here's how my data should look like. It is basically and a collection of invoices. Each invoice data for that invoice like customer name, invoice number, etc. It also contains an array of sections. Each section has data about that section like the type of products, color of products, etc. Each section itself contains an array of invoiceLines, and they all contain a product that takes properties from the section it is contained in, and also has it's own data.
Pseudo code:
{
"invoices": [
{
"_id": "123456",
"invoiceNumber": "i2022-123",
"customer": "John Doe",
"date": "2022-11-02",
"sections": [
{
"type": "phones",
"color": "red",
"invoiceLines": [
{
"product": "iPhone",
"year": "2022"
},
{
"product": "Samsung",
"year": "2021"
}
]
},
{
"type": "tablets",
"color": "black",
"invoiceLines": [
{
"product": "iPad",
"year": "2022"
},
{
"product": "Samsung tablet",
"year": "2021"
}
]
}
]
},
{
"Another": "Invoice"
}
]
}
My GraphQl queries look like so:
const query = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
getInvoices: {
type: new GraphQLList(ProjectType),
resolve(parent, args) {
return Project.find();
}
},
getInvoice: {
type: ProjectType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Project.findById(args.id);
}
}
}
});
Question #1: How would I query a specific section or an invoice line? they all have MongoDB IDs, but for some reason I can't use that to query them.
const { Project } = require('../../models/Project');
const { SectionType, SectionInputType } = require('../TypeDefs/SectionType');
const ProjectType = require('../TypeDefs/ProjectType');
const mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
// Add a Project
addProject: {
type: ProjectType,
args: {
date: { type: GraphQLString },
invoiceNumber: { type: GraphQLNonNull(GraphQLString) },
customer: { type: GraphQLNonNull(GraphQLString) },
},
resolve(parent, args) {
const project = new Project({
date: args.date,
invoiceNumber: args.invoiceNumber,
customer: args.customer,
sections: [],
})
return project.save()
}
},
// Add a Section
addSection: {
type: SectionType,
args: {
// MongoDB ID for the project the section belongs to
id: { type: GraphQLID },
section: { type: SectionInputType }
},
async resolve(parent, args) {
const newSection = args.section;
return await Project.updateOne({ _id: args.id }, {
$push: { sections: newSection }
})
}
},
}
});
I'm using $push to add a section to the invoice.sections and that works perfectly because I can get a hold of the invoice by the MongoDB ID.
Question #2: In that case how would I be able to add invoice lines to these sections that I add with this method, since I'm not able to get a hold of the sections by their respective _id.
I guess my main issue is that I'm not able to get a hold of nested MongoDB IDs.
Any help would be appreciated, or any pointers to good resources for GraphQL and Mongoose.
P.S. Yes, I'm new to GraphQL, but I like the concept of it so I wanted to explore it.
I've tried resources from YouTube and from graphQL docs, but pretty much everything is vague when it comes to a problem like this. I would think the deeply nested data like this is a common occurrence, but I can't find proper resources

Unable to filter an array inside of a related model with Prisma 2

I'm trying to check if the provided value exists inside of an array. I've been trying to figure this one out and from what I gathered, I have to use has. The array I'm trying to filter is inside of a related model. I tried looking for a solution, but couldn't find much on this subject. Am I doing something wrong? Is it at all possible to filter an array inside of a related model?
Here's my schema. Job and Company models are related, and inside Company we have a parking array.
model Company {
id Int #id #default(autoincrement())
name String #db.VarChar(200)
state String #db.VarChar(30)
parking String[]
...
createdAt DateTime #default(now())
updated_at DateTime #updatedAt
##map(name: "company")
}
model Job {
id Int #id #default(autoincrement())
type String
company Company #relation(fields: [company_id], references: [id])
company_id Int
createdAt DateTime #default(now())
updated_at DateTime #updatedAt
UserJobs UserJobs[]
##map(name: "job")
}
Below, I'm trying to find many jobs which match various values. One of the values I'm trying to match is inside of an array in the related Company model. Here's what I tried:
const jobs = await prisma.job.findMany({
where: {
AND: [
{
type: {
contains: req.body.type,
}
},
{
company: {
state: {
contains: req.body.state
}
}
},
...
{
company: {
parking: {
has: req.body.parkingState
}
}
}
]
},
include: {
company: true,
}
})
If you want to match a single value in a list has should be used, but if you want to match multiple values in a list then you would need to use hasEvery or hasSome depending upon your use case.
Here is the query which matches a single value in a list
const jobs = await prisma.job.findMany({
where: {
AND: [
{
type: {
contains: 'Software Engineer',
},
},
{
company: {
state: {
contains: 'CA',
},
},
},
{
company: {
parking: {
has: 'Employee',
},
},
},
],
},
include: {
company: true,
},
});
console.log(JSON.stringify(jobs, null, 2));
}
Here is the response for the above query:
[
{
"id": 1,
"type": "Software Engineer",
"company_id": 1,
"createdAt": "2022-02-28T08:53:03.949Z",
"updated_at": "2022-02-28T08:53:03.950Z",
"company": {
"id": 1,
"name": "Apple",
"state": "CA",
"parking": [
"Admin",
"Manager",
"Employee"
],
"createdAt": "2022-02-28T08:50:50.030Z",
"updated_at": "2022-02-28T08:50:50.031Z"
}
}
]
This is the sample data with which the above query fetched the results.
Job Table:
Company Table:
If you want to match multiple values in parking array you could achieve it by replacing has with hasSome in this manner.
const jobs = await prisma.job.findMany({
where: {
AND: [
{
type: {
contains: 'Software Engineer',
},
},
{
company: {
state: {
contains: 'CA',
},
},
},
{
company: {
parking: {
hasSome: ['Employee', 'Manager'],
},
},
},
],
},
include: {
company: true,
},
});
console.log(JSON.stringify(jobs, null, 2));
}

How to create a GraphQl resolver for Appsync for "most likes"

Im using AWS Appsync with DynamoDB as it data source. I have 2 tables, one for Photos and one for Likes. In a Appsync resolver I want to return only photos with more than 5 likes. How can I achieve this in Appsync
Schema
type Photo {
id: ID!
likes: [LikedPhoto]
}
type LikedPhoto {
id: ID!
username: String!
photoId: String!
}
Query
type Query {
listPhotos(filter: PhotoFilterInput, limit: Int, nextToken: String): PhotoConnection
}
Photo Resolver
Data Source: PhotoTable
{
"version": "2017-02-28",
"operation": "Scan",
"filter": #if($context.args.filter) $util.transform.toDynamoDBFilterExpression($ctx.args.filter) #else null #end,
"limit": $util.defaultIfNull($ctx.args.limit, 20),
"nextToken": $util.toJson($util.defaultIfNullOrEmpty($ctx.args.nextToken, null)),
}
Likes Resolver
Data Source: LikesTable
{
"version": "2017-02-28",
"operation": "Query",
"index": "photoId-index",
"query": {
"expression": "photoId = :photoId",
"expressionValues": {
":photoId": {
"S": "$context.source.id"
}
}
}
}
How can i write a resolver for likes or photos, to only show photos that have more than 5 likes.
How about designing your schema like a document-based to have only PhotoTable.So you can easily filter photos with totalLike.
type Photo {
id: ID!
likedUsername: [String]
totalLike: Int
}
// QUERY RESOLVER
{
"version" : "2017-02-28",
"operation" : "Scan",
"filter" : {
"expression": "totalLike > :totalLike",
"expressionValues": {
":totalLike": {
"N": 5
}
}
}
}

What is the mongoose schema of this json example?

I am working on a Node.js project with MongoDb Database .
I need the schema of this json example :
I am working on a Node.js project with MongoDb Database .
I need the schema of this json example
MongoDb document :
{
"container_number": "ddd",
"container_Date": "2/2/2018",
"scannedProductArray": {
"CCR": [
{
"ScannedDate": {
"$date": "2018-03-28T20:54:57.663Z"
},
"productNumber": "4656874974",
"productType": "CCR"
},
{
"ScannedDate": {
"$date": "2018-03-28T20:55:23.698Z"
},
"productNumber": "4656874974",
"productType": "CCR"
}
],
"CCH": [
{
"ScannedDate": {
"$date": "2018-03-28T21:25:16.202Z"
},
"productNumber": "4656874974",
"productType": "CCR"
},
{
"ScannedDate": {
"$date": "2018-03-28T21:26:08.696Z"
},
"productNumber": "4656874974",
"productType": "CCR"
}
]
}
}
container_number: String,
container_Date: String,
scannedProductArray:{CCR:[ScannedDate: {
date:type:Date,default:Date.now
},
"productNumber:Number,
"productType": "String"],CCH[:[ScannedDate: {
date:type:Date,default:Date.now
},
"productNumber:Number,
"productType": "String"]}
May be this one helps you.
I'd like to define schemas like this:
const Product = {
ScannedDate: {
type: Object,
},
productNumber: {
type: String,
},
productType: {
type: String,
default: 'CCR',
}
};
const Item = {
itemName: {
type: [Product],
},
};
const Container = {
container_number: {
type: String,
},
container_Date: {
type: String
},
scannedProductArray: {
type: Object, // Item
}
};
If the CCR/CCH fields are dynamic, I can just use type: Object rather than a certain structure. And I validate these array items by myself instead of mongoose.