How to Generate A Slug on AppSync Mutation - aws-appsync

I have a mutation to create a new Event. However I want to be able to reference/get that Event using a friendly id or slug instead of the DynamoDB primary key of id. Ideally this would use the city field from the input to generate the slug. However each slug must be unique per author
How can I generate a friendly slug in my mutation that is based on the city name and unique (per author) ?
Schema
type Event {
id: ID!
subtitle: String!
city: String!
author: String!
created: AWSDateTime
}
mutation.CreateEvent
#set( $attribs = $util.dynamodb.toMapValues($ctx.args.input))
#set( $attribs.author = $util.dynamodb.toDynamoDB($ctx.identity.username))
#set( $attribs.created = $util.dynamodb.toDynamoDB($util.time.nowFormatted("yyyy-MM-dd HH:mm:ssZ")))
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($util.autoId()),
},
"attributeValues": $util.toJson($attribs),
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id",
},
},
}
```

Related

GraphiQL Mutation: How can I ignore other objects in query variables

Currently having hard time setting up my end points clerk to hasura.
I am absolute new to this platform specially at GraphiQL and just following documentations and youtube video
What I am trying to do is import/insert specific data i neeed only from clerk. Here's the sample query variables:
{
"data": {
"birthday": "",
"created_at": 1654012591514,
"email_addresses": [
{
"email_address": "example#example.org",
"id": "idn_29w83yL7CwVlJXylYLxcslromF1",
"linked_to": [],
"object": "email_address",
"verification": {
"status": "verified",
"strategy": "ticket"
}
}
],
"external_accounts": [],
"external_id": "567772",
"first_name": "Example",
"gender": "",
"id": "user_29w83sxmDNGwOuEthce5gg56FcC",
"last_name": "Example",
"last_sign_in_at": 1654012591514,
"object": "user",
"password_enabled": true,
"phone_numbers": [],
"primary_email_address_id": "idn_29w83yL7CwVlJXylYLxcslromF1",
"primary_phone_number_id": null,
"primary_web3_wallet_id": null,
"private_metadata": {},
"profile_image_url": "https://www.gravatar.com/avatar?d=mp",
"public_metadata": {},
"two_factor_enabled": false,
"unsafe_metadata": {},
"updated_at": 1654012591835,
"username": null,
"web3_wallets": []
},
"object": "event",
"type": "user.created"
}
What I only need to this object is content inside of the "data" is: created_at, first_name, user_id, updated_at, profile_image_url
The GraphiQL Query I did is:
mutation CreateUser(
$created_at: String,
$first_name: String,
$user_id: String,
$updated_at: String,
$profile_image_url: String
)
{
insert_users_one(object:
{
created_at: $created_at,
first_name: $first_name,
user_id: $user_id,
updated_at: $updated_at,
profile_image_url: $profile_image_url,
}) {
created_at
first_name
user_id
updated_at
profile_image_url
}
}
Which throwing error of:
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$"
},
"message": "unexpected variables in variableValues: object, type, data"
}
]
}
I tried using other method like this:
mutation CreateUser($data: users_insert_input!) {
insert_users_one(object: $data) {
created_at
first_name
user_id
updated_at
profile_image_url
}
}
But it is still having error because of object and type fields
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$"
},
"message": "unexpected variables in variableValues: object, type"
}
]
}
Here's a sample of GraphQL type:
//is this how you break things down?
type Mutation {
data(
created_at: Int
first_name: String
id: String
updated_at: Int
profile_image_url: String
): Data
}
//this is what i will send in the database, things that I only need
type Verification {
status: String
strategy: String
}
type EmailAddresses {
email_address: String
id: String
object: String
verification: Verification
linked_to: [String]
}
type Data {
birthday: String
created_at: Int
external_id: String
first_name: String
gender: String
id: String
last_name: String
last_sign_in_at: Int
object: String
password_enabled: Boolean
primary_email_address_id: String
primary_phone_number_id: String
primary_web3_wallet_id: String
profile_image_url: String
two_factor_enabled: Boolean
updated_at: Int
username: String
web3_wallets: [String]
phone_numbers: [String]
external_accounts: [String]
email_addresses: [EmailAddresses]
}
type AutogeneratedMainType {
object: String
type: String
data: Data
}
I was expecting based on documents, It will ignore aren't included data.
Visit Github Discussions here
Context about the error
This is error you are receiving is based on this graphql spec - https://spec.graphql.org/June2018/#sec-Input-Objects . More over there is also a different spec for validation against variables here - https://spec.graphql.org/June2018/#sec-All-Variables-Used
TLDR; Using variable which isn’t defined in operation, will result into “unexpected variableValues” error. In your case apart from data , you have type and object as variables in your query variables object which is not defined in operation itself. Remember that query variables is an “object” expecting the variable key-values in it.
Workaround
Cleanest way to do this is to sanitize your object (which you will pass in query variables) by either creating a new object from it and passing data to it or either you remove the unnecessary fields from it which are not defined in operation. You could just delete the properties of that object. Consider yourObject containing data,type and object fields. Then you can do delete yourObject.type and delete yourObject.object. And then pass it.
This workaround is intended for client side code. But there's no exception for graphiQL explorer as that error would be thrown upon undefined variables in operation. If trying via graphiQL explorer, you would manually need to not pass those variables in query variables scope.
Conclusion
This behavior is in compliant with this graphql spec and not with Hasura directly, so we would suggest you to go through those graphql spec links and understand the aspect of it.

GORM don't create many2many associations

I have model:
type Book struct {
gorm.Model
Title string `json:"title"`
Author string `json:"author"`
Description string `json:"description"`
Category string `json:"Category"`
Publisher string `json:"publisher"`
AuthorsCard []*AuthorsCard `gorm:"many2many:book_authorscard; "json:"authorscard"`
}
type AuthorsCard struct {
gorm.Model
Name string `json:"name"`
Age int `json:"age"`
YearOfBirth int `json:"year"`
Biography string `json:"biography"`
}
After db.AutoMigrate(&models.Book{}, &models.AuthorsCard{})
I have a creation function:
func TestCreate() {
var testbook = models.Book{
Title: "Test",
Author: "tst",
AuthorsCard: []*models.AuthorsCard{
{
Age: 23,
Name: "test",
YearOfBirth: 1999,
Biography: "23fdgsdddTEST",
},
},
Description: "something",
}
db.Preload("AuthorsCard").Find(&models.Book{})
db.Create(&testbook)
}
despite That AuthorsCard has some data in it, I receive this as a response:
{
"ID": 78,
"CreatedAt": "2022-06-23T13:10:58.01629+03:00",
"UpdatedAt": "2022-06-23T13:10:58.01629+03:00",
"DeletedAt": null,
"title": "Test",
"author": "tst",
"description": "something",
"Category": "",
"publisher": "",
"authorscard": null
}
As you can see "authorscard" is null.
How can I save "authorscard" to the database?
I used Gorm + postgresql and also I sent a few request with postman, results are the same - Authors card is null
The code is working when it's called in the correct order:
func TestCreate() {
db := getDB()
db.AutoMigrate(&Book{}, AuthorsCard{})
var testbook = Book{
Title: "Test",
Author: "tst",
AuthorsCard: []*AuthorsCard{
{
Age: 23,
Name: "test",
YearOfBirth: 1999,
Biography: "23fdgsdddTEST",
},
},
Description: "something",
}
// 1. Create your testbook.
db.Create(&testbook)
// 2. Store it into a variable:
var b1 *Book
db.Preload("AuthorsCard").Find(&b1)
fmt.Println(b1.AuthorsCard[0].Age)
fmt.Println(b1.AuthorsCard[0].Name)
fmt.Println(b1.AuthorsCard[0].YearOfBirth)
fmt.Println(b1.AuthorsCard[0].Biography)
}
prints:
23
test
1999
23fdgsdddTEST
Also your JSON export might fail since you pass a pointer to AuthorCard and the marshalling not always works properly in those cases. However, GORM does the right job here.
Static check also gave me some hints here:
type Book struct {
gorm.Model
Title string `json:"title"`
Author string `json:"author"`
Description string `json:"description"`
Category string `json:"Category"`
Publisher string `json:"publisher"`
AuthorsCard []*AuthorsCard `gorm:"many2many:book_authorscard" json:"authorscard"` // wrong space
}

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 set property of a model from a property of a `population` field in mongoose?

I have a Post and its author property is set to User by using ref. Suppose there is a country field in User, how to make Post schema to have a country property as well which value is from User.country after population.
const Post = new Schema({
text: String,
author: {
type: ObjectId,
ref: 'User'
},
// How to set the virtual property country which is from User.country?
});
I know there is a Populate Virtuals in Mongoose, but it seems it just another way of populating, it won't pick up one of the properties, but the whole referenced record. Or maybe I get it wrong?
I know I can refer the country from Post.author.country, but I want a Post.country as well.
How to solve this?
Could I do this at the schema level?
If you use Populate Virtuals you can do the following :
var schemaOptions = {
toObject: {
virtuals: true
},
toJSON: {
virtuals: true
}
};
var PostSchema = new Schema({
text: String,
id: false,
author: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}, schemaOptions);
PostSchema.virtual('country').get(function() {
return this.author.country;
});
Using :
Post.find({}).populate('author').exec(function(error, data) {
console.log(JSON.stringify(data));
});
it gives :
[{
"_id": "59d924346be5702d16322a67",
"text": "some text",
"author": {
"_id": "59d91f1a06ecf429c8aae221",
"country": "France",
"__v": 0
},
"__v": 0,
"country": "France"
}]
Check this gist for a full example

Mongodb onetoone accessing related data

Given the following schemas:
Schemas.Book = new simpleSchema({
"name": {
type: String
},
"publisher: {
type: Schemas.Publisher
}
});
Schemas.Publisher = new simpleSchema({
"name": {
type: String
}
});
If I do a find query on the Book schema, how can I return the one to one related Publisher please?
eg: db.book.find({}); currently returns:
{ "_id": ObjectId("objectid"), "name": "Book 1", "publisher": ObjectId("pubObjectId") }
I need to resolve the publisher.name. Hope that is clear enough.
Mongo doesn't provide JOIN operation, so you need to make it in your application. Something like:
var PublisherId = db.book.findOne({'name':'Book 1'})["publisher"]
var PublisherName= db.publisher.findOne({'_id': PublisherId })["name"]