How to access arguments on child resolver from parent call in AWS Appsync - aws-appsync

I have two types: Todo and Comment.
type Todo {
id: ID!
name: String
description: String
priority: Int
status: TodoStatus
comments: [Comment]
}
type Comment {
todoid: ID!
commentid: String!
content: String
}
Then I have a Query getTodo but the thing is I want to include a content arg that filters the comment (child) if the string passed is in the content of Comment.
getTodo(id: ID!, content: String!): Todo
I have tried attaching a resolver to comments (under Todo). If I add a filter here, how will I be able to get the ctx.args.content which was passed in getTodo(id: ID!, content: String!).
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
## Provide a query expression. **
"expression": "todoid = :id",
"expressionValues" : {
":id" : {
"S" : "${ctx.args.id}"
}
}
},
"filter": {
"expression": "contains(content, :content)",
"expressionValues" : {
":content": {
"S": "${ctx.args.content}"
}
}
}
}
Or if I remove this filter and leave it like this:
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
## Provide a query expression. **
"expression": "todoid = :id",
"expressionValues" : {
":id" : {
"S" : "${ctx.args.id}"
}
}
}
}
How will I modify getTodo Resolver to fetch comments (with content that contains the string passed)?
Can I do it like this (accessing if comments.content contains the content string args passed):
{
"version" : "2017-02-28",
"operation" : "Query",
"query" : {
## Provide a query expression. **
"expression": "id = :id",
"expressionValues" : {
":id" : {
"S" : "${ctx.args.id}"
}
}
},
"filter": {
"expression": "contains(comments.content, :content)",
"expressionValues" : {
":content": {
"S": "${ctx.args.content}"
}
}
}
}

The GraphQL arguments you are accessing via $ctx.args are available at the field level. So when you access them when resolving the Post.comments field, you get back all the arguments on that field and that field only.
So to get the content string argument you could update your Todo type to:
type Todo {
id: ID!
name: String
description: String
priority: Int
status: TodoStatus
comments(content: String): [Comment]
}
Another way, if you don't want to expose the content argument on the Post.comments field and keep the argument on the Query.getTodo field, you could pass the arguments via the source. In your Query.getTodo resolver you could return the content field as part of the todo result. You would then be able to access it inside the Todo.comments resolver via $ctx.source.content.

Related

Spring REST Docs - parts not documented:

I have a springBoot 2.1.9.RELEASE application that uses Spring REST Docs.
I have this payload
{
"hostel" : [ {
"bookingHostelIdentifier" : {
"internalMasterIdentifier" : {
"id" : "987654321"
}
}
}, {
"bookingHostelIdentifier" : {
"customerIdentifier" : {
"id" : "23456789"
}
}
}, {
"bookingHostelIdentifier" : {
"internalMasterIdentifier" : {
"id" : "87654321"
}
}
} ]
}
which I documented like this
fieldWithPath("hostel[]").description("The list of hostels"),
fieldWithPath("hostel[].name").description("The list of hostels"),
fieldWithPath("hostel[].bookingHostelIdentifier").description("The list of hostels"),
fieldWithPath("hostel[].bookingHostelIdentifier.internalMasterIdentifier.id").description("The list of hostels"),
fieldWithPath("hostel[].bookingHostelIdentifier.customerIdentifier.id").description("The list of hostels")
but I got this Exception
org.springframework.restdocs.snippet.SnippetException:
Fields with the following paths were not found in the payload:
[hostel[].bookingHostelIdentifier.internalMasterIdentifier.id, hostel[].bookingHostelIdentifier.customerIdentifier.id]
As the internalMasterIdentifier and the customerIdentifier fields are not always present in a bookingHostelIdentifier, you should mark those fields or the id fields that are nested beneath them as optional.
fieldWithPath("hostel[].bookingHostelIdentifier.internalMasterIdentifier.id").optional().description("The list of hostels"),
fieldWithPath("hostel[].bookingHostelIdentifier.customerIdentifier.id").optional().description("The list of hostels")

Referencing for mongoose

i'm currently trying to reference a collection called items with the structure below
packageSchema = schema({
recipient: String,
contents: [{item :{type: mongoose.Schema.Types.ObjectId,
ref: 'items', required : true}, amount: String}]
Below is my code for getting one package via its id
getOnePackage : function(id,callback)
{
packageModel.findById(id,callback)
.populate('contents')
}
So when i call the above function i'm expecting to get this result
{
recipient : Dave
contents : [
{item : {
_id:5d2b0c444a3cc6438a7b98ae,
itemname : "Statue",
description : "A statue of Avery"
} ,amount : "2"},
{item : {
_id:5d25ad29e601ef2764100b94,
itemname : "Sugar Pack",
description : "Premium Grade Sugar From China"
} ,amount : "5"},
]
}
But what i got from testing in Postman is this :
{
recipient : Dave,
contents : []
}
May i know where did it went wrong? And also how do i prevent mongoose from automatically insert an objectId for every single element in the contents array....
Because element in contents array is object with item field so your populate should be:
.populate('contents.item')

Camel Rest-DSL (api-doc) - Potential bug

I've been using Rest-DSL (Camel v2.18.1) and trying to set up my own RestOperationResponseMsgDefinition so as to have a useful API doc. By setting a class to the responseModel to tell which object will be returned in case of success, its structure is properly shown in the API doc. However, if I create a class that has that object within, all endpoints which mention it as their outputType/responseModel stop showing the correct structure in the API doc and put "string" instead. Like this:
My outputType/responseModel:
class Address {
private Integer id;
private String descr;
}
API-doc snippet:
"/addresses" : {
"get" : {
"produces" : [ "application/json" ],
"responses" : {
"200" : {
"description" : "Success.",
"schema" : {
"$ref" : "#/definitions/Address"
}
}
...
In Swagger-UI, the response example value is shown as:
{
"id": "string",
"descr": "string"
}
Everything is alright till I create any class having an Address object within! For instance:
class Store {
private Integer id;
private String name;
private Address address;
}
Now, for the same endpoint mentioned before, I get...
"/addresses" : {
"get" : {
"produces" : [ "application/json" ],
"responses" : {
"200" : {
"description" : "Success.",
"schema" : {
"type" : "string",
"format" : "com.mycompany.integration.domain.Address"
}
}
...
And the following in Swagger-UI as example value:
"string"
Has anybody ever passed through and solved this? This seems a bug, though...

MongoDB: Finding a value where object name contains url

We are using learninglocker and I am trying to query its mongodb. learninglocker puts escaped urls as object names, which makes them more difficult to search. I am returning 0 results when I would expect to return several.
My find is as follows:
{"statement.object.definition.extensions.http://activitystrea&46;ms/schema/1&46;0/device.device_type": "app"}
I assume that this should be escaped somehow, however, am unsure how.
http://activitystrea&46;ms/schema/1&46;0/device
Sample object:
"statement": {
"version" : "1.0.0",
"actor" : { },
"verb" : { },
"context" : { },
"object" : {
"definition" : {
"extensions" : {
"http://activitystrea&46;ms/schema/1&46;0/device" : {
"device_type" : "app"
}
}
}
}
}

Designing REST API(s), more complicated objects or more requests?

I have problem with REST API(s) for front-end GUI and am wondering which approach is better. Are there any design patterns for these types of problems?
uri: /users/list
response: [
{
id: "1",
name "Aaa",
surname "Bbb",
contactDetails: {
telephone: "111-111-111"
email: "mail#mail.pl"
}
},
...
]
OR
uri: /users/list
response: [
{
id: "1",
name "Aaa",
surname "Bbb"
},
...
]
uri: /emails/list?userIds=1,..
response: [
{
userId: "1",
email: "mail#mail.pl"
}
]
uri: /telephones/list?userIds=1,..
response: [
{
userId: "1",
telephone: "111-111-111"
}
]
and it's the same for a single user:
uri : users/{id}
uri : users/{id}/emails
uri : users/{id}/telephones
============== Extended class model =================================
Below I paste JSON classes designed for question needs.
SystemPart : {
id : "sp2",
name : "UserAdministration",
parentSystemPart : {
id : "sp1",
name : "Administration",
...
}
...
}
SystemPermission : {
permissionType : "MODERATOR",
systemParts : [ // list of SystemPart
{
id : "sp1",
name : "UserAdministration",
parentSystemPart:{...}
},
...
],
...
}
User: {
id : "u1",
name : "a",
surname : "b",
contactDetails : {
telephone : "111-111-111"
email : "mail#mail.com"
},
identityCard : {
idType : "Id",
number : "321"
}
systemPermissions : [ // list of SystemPermission
{
permissionType : "MODERATOR",
systemParts : [...]
},
...
]
}
MapPoint : {
id : "mp1",
x : 11.11,
y : 22.22,
createdBy : { // User
id : "u1",
...
systemPermission : [...]
}
}
GUI client would like to show map point data with only it's author name, and surname
and now api for list of MapPoints
/map-points/list?x=11.00&y=22.00&d=5.0
other part of GUI would like to get list of users with its permissions
/users/list?page=0&size=5
In my opinion problem is in map-points list api which JSON is to big
I'd go with the first approach. The User class is pretty small and I don't see any benefits to calling the service separately for contact details.
Ensure that the client can filter the results based on every parameter, that way it is easy for the user of your API to get exactly what he/she wants.
For e.g. /users/list will get back everything which is perfect if there are relatively small number of users in the list and it's better to eagerly cache them all to improve client's performance.
uri: /users/list
response: [
{
id: "1",
name "Aaa",
surname "Bbb",
contactDetails: {
telephone: "111-111-111"
email: "mail#mail.pl"
}
},
...
]
If the number of users are significantly large, make sure the list can be filtered down to a small quantity based on every(or at least the significant ones like last name) parameter and the client can call your service for specific users and lazily load them as and when needed.
uri: /users/list?surname=Bbb
or
uri: /users/list?id=1
should get back:
response: [
{
id: "1",
name "Aaa",
surname "Bbb",
contactDetails: {
telephone: "111-111-111"
email: "mail#mail.pl"
}
}
]