How to create a GraphQl resolver for Appsync for "most likes" - aws-appsync

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
}
}
}
}

Related

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

get github issues by their ids through graphql endpoints

I am trying to get the list of issues by their ids from Github using graphql, but looks like I am missing something or its not possible.
query ($ids:['517','510']!) {
repository(owner:"owner", name:"repo") {
issues(last:20, states:CLOSED) {
edges {
node {
title
url
body
author{
login
}
labels(first:5) {
edges {
node {
name
}
}
}
}
}
}
}
}
The above query is giving me response as below,
{
"errors": [
{
"message": "Parse error on \"'\" (error) at [1, 14]",
"locations": [
{
"line": 1,
"column": 14
}
]
}
]
}
Kindly help me identify if its possible or that I am doing something wrong here.
You can use aliases in order to build a single request requesting multiple issue object :
{
repository(name: "material-ui", owner: "mui-org") {
issue1: issue(number: 2) {
title
createdAt
}
issue2: issue(number: 3) {
title
createdAt
}
issue3: issue(number: 10) {
title
createdAt
}
}
}
Try it in the explorer
which gives :
{
"data": {
"repository": {
"issue1": {
"title": "Support for ref's on Input component",
"createdAt": "2014-10-15T15:49:13Z"
},
"issue2": {
"title": "Unable to pass onChange event to Input component",
"createdAt": "2014-10-15T16:23:28Z"
},
"issue3": {
"title": "Is it possible for me to make this work if I'm using React version 0.12.0?",
"createdAt": "2014-10-30T14:11:59Z"
}
}
}
}
This request can also be simplified using fragments to prevent repetition:
{
repository(name: "material-ui", owner: "mui-org") {
issue1: issue(number: 2) {
...IssueFragment
}
issue2: issue(number: 3) {
...IssueFragment
}
issue3: issue(number: 10) {
...IssueFragment
}
}
}
fragment IssueFragment on Issue {
title
createdAt
}
The request can be built programmatically, such as in this example python script :
import requests
token = "YOUR_TOKEN"
issueIds = [2,3,10]
repoName = "material-ui"
repoOwner = "mui-org"
query = """
query($name: String!, $owner: String!) {
repository(name: $name, owner: $owner) {
%s
}
}
fragment IssueFragment on Issue {
title
createdAt
}
"""
issueFragments = "".join([
"""
issue%d: issue(number: %d) {
...IssueFragment
}""" % (t,t) for t in issueIds
])
r = requests.post("https://api.github.com/graphql",
headers = {
"Authorization": f"Bearer {token}"
},
json = {
"query": query % issueFragments,
"variables": {
"name": repoName,
"owner": repoOwner
}
}
)
print(r.json()["data"]["repository"])
I don't think you can fetch for issues and pass in an array of integers for their ids.
But you can search for a single issue by id like so (this works for me)
query ($n: Int!) {
repository(owner:"owner", name:"repo-name") {
issue (number: $n) {
state
title
author {
url
}
}
}
}
where $n is {"n": <your_number>} defined.
If you have an array of ids, then you can just make multiple queries to GitHub.
Sadly, with this approach, you cannot specify what the state of the issue to be. But I think the logic is that once you know the issue Id, you shouldn't care what state it is, since you have that exact id.

GitHub Graphql : Getting sponsor tier information for the sponsors of a user

I am using the GitHub graphql for getting the sponsor information of a user. While I am able to get the sponsors for a particular user, I am unable to get the sponsorship-tier information for the sponsors. The graphql query that I have written is as follows:
{
user(login: <<loginID>>) {
name
sponsorshipsAsMaintainer(first: 1) {
totalCount
nodes {
createdAt
privacyLevel
tier {
createdAt
name
description
}
sponsor {
login
}
}
}
}
}
The results i get for a user are as follows. Ideally, in the query I was hoping to get the tier information but the result returns a null for the tier field.
{
"data": {
"user": {
"name": "XXX",
"sponsorshipsAsMaintainer": {
"totalCount": 11,
"nodes": [
{
"createdAt": "2020-02-16T10:39:14Z",
"privacyLevel": "PUBLIC",
"tier": null,
"sponsor": {
"login": "XXX"
}
}
]
}
}
}
}
Any help or information to get the tier information for a sponsor would be appreciated. Thank you very much.
To date tier is still null and I haven't figured out what's the issue with that.
However I managed to fetch the tiers information using the following query:
query getTiers($login: String!) {
user(login: $login) {
sponsorshipsAsSponsor(first: 1) {
nodes {
sponsorable {
sponsorsListing {
tiers(first: 5) {
nodes {
id
}
}
}
}
}
}
}
}
I'm using the following query to look up sponsors, and I only get tier information for my own tiers. I assume the viewer's databaseId must match the sponsorable databaseId to see this information
query {
user(login: "${login}") {
sponsorshipsAsSponsor(first: 100) {
nodes {
privacyLevel
tier {
monthlyPriceInDollars
}
sponsorable {
... on User {
databaseId
}
... on Organization {
databaseId
}
}
}
}
}
}
Here is a user that is sponsoring three other projects besides mine (I replaced the other project's databaseIds)
{
"data": {
"user": {
"sponsorshipsAsSponsor": {
"nodes": [
{
"privacyLevel": "PUBLIC",
"tier": {
"monthlyPriceInDollars": 3
},
"sponsorable": {
"databaseId": 220908 <--- Me
}
},
{
"privacyLevel": "PUBLIC",
"tier": null,
"sponsorable": {
"databaseId": 1
}
},
{
"privacyLevel": "PUBLIC",
"tier": null,
"sponsorable": {
"databaseId": 1
}
},
{
"privacyLevel": "PUBLIC",
"tier": null,
"sponsorable": {
"databaseId": 1
}
}
]
}
}
}
}

How to create Categories and its SubCategory in Prisma ORM using 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.

swift firebase retrieve all object that the child of the object have the same key

Below is my firebase and code , I would like to retrieve all activities which have the User John key inside User.
let ref = FIRDatabase.database().reference().child("activities/")
ref.queryOrderedByChild("User").queryEqualToValue("John").observeSingleEventOfType(.Value,
withBlock:{
(snapshot) in
for record in snapshot.children
{
}
})
This is not working because in your query you are trying to take all the activities having an attribute User == "John" when the real value of User is an Object like this:
{
"John": {
"age": 21
}
}
To solve this issue you should change your data structure creating a node where you save all your users, and keep in users/userID/activities only the id of the activities. For example, this would be a nicer way to structure your data:
{
"activities": {
"cycling": {
"users": {
"user1": true,
"user2": true
}
},
"running": {
"users": {
"user1": true
}
}
},
"users": {
"user1": {
"name": "John",
"age": 21,
"activities": {
"cycling": true,
"running": true,
}
},
"user2": {
"name": "Tim",
"age": 20,
"activities": {
"cycling": true
}
}
}
}
Then you can use
Let me know if this helped ;)