Is it possible to modify a graphql input model to reference an object using a composite key instead of id? - graphql

I have two models in my schema. 1) Tree - that uses ID as a primary key and 2) Attribute -that uses has a composite key. I would like to create a third table 3) TreeAttributes - that will reference 1st and 2nd objects, but when mutating I would like to reference the second object with a composite key.
I couldn't find anything like this in aws or Graphql documentations. I'm wondering if this is even possible?
Current schema looks something like this:
type Tree #model {
id: ID!
address: String!
description: String
attributes: [TreeAttributes] #connection (name: "treeAttributes")
}
type Attribute #model (subscriptions: null) #key(fields: ["name", "value"]) {
name: String!
value: [String]!
description: String
active: Boolean
trees: [TreeAttributes] #connection (name: "attributeTrees")
id: ID
}
type TreeAttributes #model(queries: null) {
id: ID!
tree: Tree! #connection (name: "treeAttributes")
attribute: Attribute! #connection (name: "attributeTrees")
}
Currently my input model looks like this:
input CreateTreeAttributesInput {
treeAttributesTreeId: ID!
treeAttributesAttributeId: ID!
}
but instead, i'd like it to look something like this:
input CreateTreeAttributesInput {
treeAttributesTreeId: ID!
treeAttributesAttribute: {
name: String!
value: String!}
}

Please refer to this document to construct many-to-many relationship between your models.
https://docs.amplify.aws/cli/graphql-transformer/directives#field-level-authorization
It is recommended to use new definition of the #connection, you can specify keyName and fields for it.

Related

Laravel lighthouse graphql query by relation table value

Is it possible in Laravel lighthouse GraphQL to query by relation table values?
For example, I have defined two types.
type Translation {
id: ID!
form_group_id: Int!
group: Group #hasOne
translation_key: String!
lv: String
en: String
ru: String
}
type Group {
id: ID!
name: String!
translations: [Translation]! #hasMany
}
and I want to query by group name.
The code below is just an example of the idea.
translation(group.name: String! #eq): Translation #find
I have an idea that this, can be possible with custom resolver, but is there a way using built in eloquent resolvers?
Event tho this is an experimental feature, you can use complex where conditions. This will allow you to fetch whatever type by its relation attributes. We use it on our application, and for the use we have, this is working as expected :)

GraphQl One-Direction Relationship

I'd like my user to have a list of workouts (they can be active, completed, todo). Do I have to make a link from Workout to user in order to make this work? Is there no other way? Having a link back seems weird because I'd have a loop user>workout>user>workout...
I'm not sure if this is supposed to be done in graphql, I'm new to graphql. I currently have the following schema:
type User {
email: String #unique
fullName: String
birthDate: Date
weight: Int
height: Int
country: String
trainingFrequency: Int
trainingGoal: String
isOnboarded: Boolean
workouts: [Workout]
}
type Workout {
name: String!
state: State!
}
enum State {
ACTIVE
TODO
COMPLETED
}
type Query {
allUsers: [User!]!
findUserByEmail(email: String!): User
}
With Fauna, a two way relationship is always created for you when you use the #relation directive. In a one-to-many relationship a reference will be stored in all of the many-side Documents (Workout type in your case). Traversing the graph from the one-side (User type) to the many-side is made possible with an Index that is automatically generated for you.
Yes, you can query (nearly) infinitely cyclically, but in practice, there is no benefit to it.
Make sure you include the #relation directive.
type User {
email: String #unique
fullName: String
birthDate: Date
weight: Int
height: Int
country: String
trainingFrequency: Int
trainingGoal: String
isOnboarded: Boolean
workouts: [Workout] #relation
}
type Workout {
name: String!
state: State!
owner: User! #relation
}

Is there a scalar type for arrays and maps in graphql for schemas in AWS amplify?

I was learning to use AWS amplify with React, and the API it uses is a GraphQL API that leverages AWS AppSync. I'm very new to graphQL and my schema currently is like this. This is the schema inside the amplify app:
type Note #model {
id: ID!
name: String!
description: String
title: String
image: String
}
To give you an example, I want to store an array of objects inside components in the Note type like this:
Code-1
type Note #model {
id: ID!
name: String!
description: String
title: String
image: String
components: []
}
But reading the docs I got to know there aren't any array scalar types. I know that I can create another table and do it like this instead:
Code-2
type Note #model {
id: ID!
name: String!
description: String
title: String
image: String
components: [elements!]!
}
type elements #model {
id: ID!
item: String!
}
But I don't want this as it creates a new table. I just want one table containing id, name, description, title, image and a components array where you can store objects in like shown above in Code-1. Is there any possible way to do this? Also whats the role of "#modal" in the schema?
Checked out the AWS docs and found out that I could use AWSJSON for lists/arrays like [1, 2, 3] and maps like {"upvotes": 10}, so now my schema is:
type Note #model {
id: ID!
name: String!
description: String
title: String
image: String
components: AWSJSON
}
Here is the link to know more about it AWS Scalar Types

How to combine multiple field in GraphQL Object

I am trying my first Graphql Schema design. Is it possible that single field inside object type refer to a complex object?
enum KeyPrefix {
WS
WK
SI
ENT
}
input generalKey {
keyPrefix:KeyPrefix!
key:Int!
}
type Item
{
pk: generalKey!
data: String!
name: String!
}
It gives me error as below.
The type of Item.pk must be Output Type but got: generalKey!
input is a keyword reserved for describing input to a GraphQL query. Your schema should look like this:
enum KeyPrefix {
(your values)
}
type PrimaryKey {
prefix: KeyPrefix!
key: Int!
}
type Item {
pk: PrimaryKey!
data: String!
name: String!
}
When you define a Query in your GraphQL schema, you will want to use an input, like so:
input PrimaryKeyInput {
prefix: KeyPrefix!
key: Int!
}
type Query {
getItemByPrimaryKey(input: PrimaryKeyInput!): Item
}
This will allow a client to ask for an Item using the same fields you have on PrimaryKey.

AWS-Amplify API module: how to make GraphQL fields unique?

AWS-Amplify provides a couple of directives to build an GraphQL-API. But I haven't found out how to ensure uniqueness for fields.
I want to do something like in GraphCool:
type Tag #model #searchable {
id: ID!
label: String! #isUnique
}
This is an AWS-Amplify specific question. It's not about how to do this with generic GraphQL. It's very specifically about how to do this with AWS-Amplify's API module. (https://aws-amplify.github.io/docs/js/api)
Hey thanks for the question. This is not yet possible by default using the amplify-cli but you could do this yourself using pipeline resolvers and an extra index on your DynamoDB table. The steps to do this are as follows:
Create a GSI on the table where the label is the HASH KEY.
Create a pipeline resolver on the Mutation.createTag field in your schema. You can turn off the auto-generated Mutation.createTag mutation by changing your #model definition to #model(mutations: { update: "updateTag", delete: "deleteTag" }).
Create a function named LookupLabel that issues a Query against the new GSI where the label = $ctx.args.input.label. If this returns a value, throw an error with $util.error("Label is not unique"). If it returns no values then continue.
Create a function named CreateTag that issues a PutItem against the Tag table.
Add those two functions in order to your pipeline resolver.
You can read more about pipeline resolvers here https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html.
As of writing amplify does not yet support custom & pipeline resolvers but you can read more about the feature here https://github.com/aws-amplify/amplify-cli/issues/574 as it will be supported in the future. For now you can add the resolver manually in the AWS AppSync console or via your own CloudFormation template that targets the id of the API created by Amplify. It would also be helpful if you create an issue here (https://github.com/aws-amplify/amplify-cli/issues) and tag this as a feature request because it would be possible to automate this with an #unique directive but this would need to be planned.
Thanks
Update: now you can use #primarykey and #index annotations:
https://docs.amplify.aws/cli/migration/transformer-migration/#what-is-changing
basic:
profile #model {
name
email #primaryKey - has to be unique
other
}
so if you needed something like:
profile #model {
name
email: String! #hasOne
other
}
email #model {
email: String! #primaryKey
}
if you are on an older version see below
I will eventually be testing this out to see if this works but you might be able to do something like rename the id to a string!
so...
type Tag #model #key["id"] {
id: String!
}
or:
type Customer #model #key(fields: ["email"]) {
email: String!
username: String
}
this second one is taken directly from the docs: https://docs.amplify.aws/cli/graphql-transformer/key#designing-data-models-using-key
The docs were updated recently so hopefully they are easier for everyone to understand.
If you need a more advanced workflow with allot of keys, and stuff like that then you just have to separate things out and make more types for example:
type Customer #model {
id: String!
email: Email! #hasOne
username: String
}
type email #model #key(fields: ["email"]) {
email: String!
}

Resources