How to query by non-primary key in AWS-amplify graphql schema - indexing

I have a graphql schema in aws-amplify, appsync.
my schema is:
type Project
#model
{
id: ID!
project_number: String!
name: String!
architect: String!
interfaces: [Interface] #connection(name: "ProjectInterfaces")
}
type Interface
#model
{
id: ID!
interface_name: String!
version: String!
release: String!
source_feature: String!
MFT_feature_id: String!
state: String!
source_application: String!
source_env: String!
source_go_live: String!
source_payload: String!
source_payload_format: String!
source_payload_volume: String!
source_protocol: String!
target_application: String!
target_env: String!
target_go_live: String!
target_payload: String!
target_payload_format: String!
target_payload_volume: String!
target_protocol: String!
frequency: String!
authentication: String!
payload_security: String!
transport_security: String!
network_paths: String!
project: Project #connection(name: "ProjectInterfaces")
}
and I want to know if I can search a projects interfaces by project_number instead of id. I added an index on project_name, but it doesn't seem to work. My current query is
query GetProject {
getProject(project_number:"P200") {
name
architect
interfaces{
items{
interface_name
version
release
source_feature
MFT_feature_id
state
source_application
source_env
source_go_live
source_payload
source_payload_format
source_payload_volume
source_protocol
target_application
target_env
target_go_live
target_payload
target_payload_format
target_payload_volume
target_protocol
frequency
authentication
payload_security
transport_security
network_paths
}
}
}
}
Please let me know if this is possible. I would like it so that I can just search by project_name, and then get all the details from interface.

So according to the Amplify docs you would have to add an #index on the field you'd like to query on. I've updated your Project model to have an index on the project_number field.
type Project
#model
{
id: ID!
project_number: String! #index(name: "byProjectName", queryField: "projectByNumber", sortKeyFields: ["id"])
name: String!
architect: String!
interfaces: [Interface] #connection(name: "ProjectInterfaces")
}
Then to query by project_number, use the query name set in the queryField (projectByNumber) in the index:
query projectByNumber($projectNumber: String!) {
projectByNumber(project_number: $projectNumber) {
items {
id
project_number
name
architect
...
}
}
}
Please checkout the docs under Query employee details by employee name to get a better understanding: https://docs.amplify.aws/cli/graphql/examples-and-solutions/#2-query-employee-details-by-employee-name

Related

How To Use The Same GraphQL Query Multiple Times In A Single API Call. Amplify, DynamoDB

The user will input multiple usernames and I would like to search my DynamoDB table for all each user's id in a single API call.
The following is the important portion of the graphql user schema:
type User
#model
#key(name: "byName", fields: ["username"], queryField: "findUsername")
{
id: ID!
email: AWSEmail!
username: String!
firstName: String
lastName: String
createdAt: AWSDateTime
updatedAt: AWSDateTime
}
I would like to create a query which takes the list of usernames and returns each user's user id in a single api call. I am not sure how to dynamically and separately add the usernames to a query. Btw, I am using aws-amplify to help with dynamodb and graphql. This is also a React Native project.
You can run multiple queries and mutations using batch operations in AWS AppSync. Eg: BatchGetItem
type Post {
id: ID!
title: String
}
type Query {
batchGet(ids: [ID]): [Post]
}
Sample query
query get {
batchGet(ids:[1,2,3]){
id
title
}
}
batchGet.request.vtl
#set($ids = [])
#foreach($id in ${ctx.args.ids})
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"Posts": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
batchGet.response.vtl
$util.toJson($ctx.result.data.Posts)
For more details check out this tutorial.
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-dynamodb-batch.html

Building a react-admin data provider for FaunaDB

With Graphcool being sunsetted, I've been trying to get react-admin to work with Fauna, but have not been successful. The Fauna GraphQL grammar is different than Graphcool, and of course when I connect to my Fauna DB, it doesn't recognize any of the resources.
If I build a very simple Fauna DB by uploading the following GraphQL schema:
type Location {
name: String!
address1: String!
address2: String
city: String
state: String
zip: String
}
type Query {
allLocations: [ Location ]
}
The final schema that Fauna creates looks like:
directive #embedded on OBJECT
directive #collection(name: String!) on OBJECT
directive #index(name: String!) on FIELD_DEFINITION
directive #resolver(
name: String
paginated: Boolean! = false
) on FIELD_DEFINITION
directive #relation(name: String) on FIELD_DEFINITION
directive #unique(index: String) on FIELD_DEFINITION
scalar Date
type Location {
city: String
name: String!
zip: String
state: String
_id: ID!
address2: String
address1: String!
_ts: Long!
}
input LocationInput {
name: String!
address1: String!
address2: String
city: String
state: String
zip: String
}
type LocationPage {
data: [Location]!
after: String
before: String
}
scalar Long
type Mutation {
createLocation(data: LocationInput!): Location!
updateLocation(
id: ID!
data: LocationInput!
): Location
deleteLocation(id: ID!): Location
}
type Query {
findLocationByID(id: ID!): Location
allLocations(
_size: Int
_cursor: String
): LocationPage!
}
scalar Time
I'm having a hard time figuring out how to adapt the Graphcool/GraphQL data providers to account for the difference in the Fauna grammar. A couple of differences I've noticed:
Fauna names the IDs _id, but ra-data-graphcool expects them to be id
Fauna create/update mutations expect a single input object that mirrors the type
There are probably also differences in how the Graphcool data provider builds out the gql for getting record lists as well. Has anyone created or modified a data provider for Fauna (or maybe Back4App or other free/inexpensive cloud GraphQL providers)?

Create Connected object in GraphQL via Mutation

What is the best practice to create an object via mutation connected to another object.
Using the following schema:
type Question #model {
id: ID!
text: String!
answers: [Answer] #connection(name: "QuestionAnswers")
}
type Answer #model {
id: ID!
text: String!
question: Question #connection(name: "QuestionAnswers")
}
The following (and variants of it) fail:
mutation CreateAnswer {
createAnswer(input: {
text:"Yes",
question: {
id: "9d38c759-6b64-4c1f-9e0e-d3b95a72b3a8"
}
})
{
id
}
}
Serverside code:
mutation CreateAnswer($input: CreateAnswerInput!) {
createAnswer(input: $input) {
id
text
question {
id
text
answers {
nextToken
}
}
}
}
With the above, receiving the following error:
"Validation error of type WrongType: argument 'input' with value
'ObjectValue{objectFields=[ObjectField{name='text',
value=StringValue{value='3'}}, ObjectField{name='question',
value=ObjectValue{objectFields=[ObjectField{name='id',
value=StringValue{value='9d38c759-6b64-4c1f-9e0e-d3b95a72b3a8'}}]}}]}'
contains a field not in 'CreateAnswerInput': 'question' #
'createAnswer'"
Seems that this may be a naming convention in AppSync. The below worked for me:
mutation createAnswer {
createAnswer (input: {
text: "5"
answerQuestionId: "9d38c759-6b64-4c1f-9e0e-d3b95a72b3a8"
}) {
id
}
Adding answer to QuestionId was what was needed.

Sequelize and Graphql reverse lookup

I have two Models:
River.associate = models => {
River.hasMany(models.Fish, { as: 'Fishes' });
};
Fish.associate = models => {
Fish.belongsTo(models.River);
};
type River {
id: ID!
name: String!
alternative: String!
geojson: JSON
fishes: [Fish]
}
type Fish {
id: ID!
name: String!
}
How would I findAll Rivers given a list of Fish ID's? Im not sure how the query must look for this for graphql and sequelize?
type Query {
river(id: ID!): River
**rivers(fishIds: ARRAY): River ??????**
fishes: [Fish]
}
Query: {
rivers: (_, { fishIds }) => {
return River.findAll({
where: {
fishes: fishIds
}
});
},
}
You can specify WHERE clauses for each of the models you include. Moreover, doing so will convert the eager load to an inner join (which is what you want), unless you explicitly set the required param to false.
That means you should be able to do something like:
River.findAll({ include:
[
{
model: Fish,
where: { id: fishIds }
},
],
})

RealmJS:How to write sorted fetch query where inner object is Key-Value?

Product has many details like: productName, manufactured date, manufacturer name, product type etc. But I need to support flexibility of having no defined schema for product details. To achieve this below is the Realm-JS schema.
import Realm from 'realm';
export default class ProductModel extends Realm.Object { }
ProductModel.schema = {
name: 'ProductModel',
properties: {
productAttributes: { type: 'list', objectType: 'ProductDetailsModel' },
ID: { type: 'string', optional: true },
}
};
import Realm from 'realm';
export default class ProductDetailsModel extends Realm.Object { }
ProductDetailsModel.schema = {
name: 'ProductDetailsModel',
properties: {
attributeName: { type: 'string', optional: true },
attributeValue: { type: 'string', optional: true },
}
};
This flexibility is yielding in complexity of writing sort query. I need to be able to sort based on Product Attribute values. Let us say 'Product Name' is on attribute of Product, I need to fetch Product sorted by 'Product Name' in 'A-Z' or reverse order.
var productList = realm.objects('ProductModel').sorted(<Some query string>)
Please help me to write query to fetch the ProductModel from DB based on some values(productName or manufacturer name etc..) sorted order?
P.S. Other option which I am aware is get the realm objects and sort using Array.sort.
Update 1:
When I try to do sort with below query:
let item = this.realm.objects('ProductModel').filtered("productAttributes.attributeName = " + "\"" + "serialNo" + "\"")
.sorted('productAttributes.attributeValue', false);
I am getting below error
Cannot sort on key path 'productAttributes.attributeValue': property 'ProductModel.productAttributes' is of unsupported type 'array'.