I am currently following this workflow on the AWS Amplify docs:
https://docs.amplify.aws/lib/datastore/relational/q/platform/js/#many-to-many-relationships
Yet I cannot query my relational join tables. I am confused as to what I have done incorrectly in terms of syntax. This is my code and these are the errors I receive.
// schema.graph.ql
type Icd10 #model #auth(rules: [{allow: public}]) {
id: ID!
Code: String
Description: String
MedicalTests: [MedicalTest] #manyToMany(relationName: "Icd10MedicalTest")
Disease: [Disease] #manyToMany(relationName: "Icd10Disease")
}
type MedicalTest #model #auth(rules: [{allow: public}]) {
AdditionalIcd10: [String]
AdditionalTesting: String
ClinicalUtility: String
Cpt: [String]
DescriptiveMethodology: String
Icd10: [String]
Icd9: [String]
Interpretation: String
Loinc: [String]
Methodology: String
Name: String
Overview: String
PanelTests: [String]
ReferenceRanges: String
References: String
SpecimenCollection: String
SpecimenType: String
Synonyms: [String]
TurnaroundTime: String
createdAt: AWSDateTime!
id: ID!
updatedAt: AWSDateTime!
uuid: String
ratings: [Rating] #manyToMany(relationName: "RatingMedicalTest")
icd10s: [Icd10] #manyToMany(relationName: "Icd10MedicalTest")
}
// TransferData.js
const value = await DataStore.query(MedicalTest,
m => m.Name.eq("11-Dehydro-Thromboxane B2, Urine")
)
console.log(value)
const result = await DataStore.query(Icd10,
m => m.MedicalTests.MedicalTest.id.eq(value.id)
)
console.log("updateIcd10MedicalTest Successful!")
console.log(result)
Error Image
I have attempted to change the input values multiple times as I thought maybe I was wrong in reading how my schema functioned as I'm new to GraphQL.
Related
The following code is throwing the following error:
await this.GuildModel.findOne({ _id: guildId }).exec((guild) => {
console.log(guild);
});
CastError: Cast to ObjectId failed for value "894673322397302784" (type string) at path "_id" for model "GUILD"
{
messageFormat: undefined,
stringValue: '"894673322397302784"',
kind: 'ObjectId',
value: '894673322397302784',
path: '_id',
reason: BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
My _id value in my schema and in my database is of type string, and hence I do not want it to be casted to an ObjectID, my schema:
const GuildSchema = {
_id: { type: String },
prefix: { type: String, default: "!" },
}
After doing some research, I realised that I couldn't use findById as it forces it into using an ObjectID, hence why I used findOne. How would I query by my _id which is of type string.
_id is reserved for ObjectID my MongoDB, use id(not _id) for your own generated ID, and in your query use id also, you should be fine.
I am wondering if it is possible to pass multiple IDs to a useQuery for apollo hook. Or run a single query per ID, and if so how would I go about doing so.
I have the following query
const DECOR_SHEET = gql`
query GetDecorSheet($id: ID!) {
findDecorSheetByID(id:$id){
refIdArray
sheetName
_id
}
}
`;
and the following useQuery hook
const { loading, error, data: sheetData } = useQuery(DECOR_SHEET, {
variables: { id: id },
context: {
headers: {
authorization: cookieBearer,
},
},
});
I have the following IDs 293164663883956749, 293526016787218952 and I would like to return into one object in order to render into a component.
I am using Fauna DB and this is the input graphQL schema
type Catalog {
decor: Boolean
clothing: Boolean
supplies: Boolean
furniture: Boolean
owner: User
}
type Decor {
description: String
pieces: Int
purchaser: String
alterations: Boolean
cost: Int
purchaseDate: Date
category: String
image: String
itemNum: Int
owner: User!
visible: Boolean
}
type DecorSheet {
sheetName: String
refIdArray: String
owner: User!
}
type User {
email: String! #unique
catalog: Catalog
decor: [Decor!] #relation
decorSheet: [DecorSheet!] #relation
}
and this is the generated schema
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
type Catalog {
_id: ID!
decor: Boolean
clothing: Boolean
supplies: Boolean
owner: User
furniture: Boolean
_ts: Long!
}
input CatalogInput {
decor: Boolean
clothing: Boolean
supplies: Boolean
furniture: Boolean
owner: CatalogOwnerRelation
}
input CatalogOwnerRelation {
create: UserInput
connect: ID
disconnect: Boolean
}
scalar Date
type Decor {
purchaseDate: Date
visible: Boolean
image: String
description: String
_id: ID!
alterations: Boolean
cost: Int
pieces: Int
category: String
owner: User!
purchaser: String
itemNum: Int
_ts: Long!
}
input DecorInput {
description: String
pieces: Int
purchaser: String
alterations: Boolean
cost: Int
purchaseDate: Date
category: String
image: String
itemNum: Int
owner: DecorOwnerRelation
visible: Boolean
}
input DecorOwnerRelation {
create: UserInput
connect: ID
}
type DecorPage {
data: [Decor]!
after: String
before: String
}
type DecorSheet {
refIdArray: String
_id: ID!
sheetName: String
owner: User!
_ts: Long!
}
input DecorSheetInput {
sheetName: String
refIdArray: String
owner: DecorSheetOwnerRelation
}
input DecorSheetOwnerRelation {
create: UserInput
connect: ID
}
type DecorSheetPage {
data: [DecorSheet]!
after: String
before: String
}
scalar Long
type Mutation {
updateUser(
id: ID!
data: UserInput!
): User
createUser(data: UserInput!): User!
createDecorSheet(data: DecorSheetInput!): DecorSheet!
createDecor(data: DecorInput!): Decor!
deleteCatalog(id: ID!): Catalog
updateCatalog(
id: ID!
data: CatalogInput!
): Catalog
updateDecor(
id: ID!
data: DecorInput!
): Decor
updateDecorSheet(
id: ID!
data: DecorSheetInput!
): DecorSheet
deleteDecor(id: ID!): Decor
deleteUser(id: ID!): User
createCatalog(data: CatalogInput!): Catalog!
deleteDecorSheet(id: ID!): DecorSheet
}
type Query {
findUserByID(id: ID!): User
findCatalogByID(id: ID!): Catalog
findDecorByID(id: ID!): Decor
findDecorSheetByID(id: ID!): DecorSheet
}
scalar Time
type User {
catalog: Catalog
email: String!
_id: ID!
decor(
_size: Int
_cursor: String
): DecorPage!
decorSheet(
_size: Int
_cursor: String
): DecorSheetPage!
_ts: Long!
}
input UserCatalogRelation {
create: CatalogInput
connect: ID
disconnect: Boolean
}
input UserDecorRelation {
create: [DecorInput]
connect: [ID]
disconnect: [ID]
}
input UserDecorSheetRelation {
create: [DecorSheetInput]
connect: [ID]
disconnect: [ID]
}
input UserInput {
email: String!
catalog: UserCatalogRelation
decor: UserDecorRelation
decorSheet: UserDecorSheetRelation
}
There is an option to query with Fauna's FQL which may have a way of querying multiple IDs I will have to look into that, but would prefer to do this in graphQL with apollo if possible.
Thanks ahead of time
Thanks to support from FaunaDB
The following query and UDF does the trick
Query
type Query {
getMultipleDecors(DecorId: [ID!]): [Decor]
#resolver(name: "get_multiple_decors")
}
udf named get_multiple_decors
Query(
Lambda(
["input"],
Let(
{
data: Map(
Var("input"),
Lambda("x", Get(Ref(Collection("Decor"), Var("x"))))
)
},
Var("data")
)
)
)
If it's always exactly two ids, you can fetch both objects in a single query easily using field aliases:
const DECOR_SHEET = gql`
query GetDecorSheet($firstId: ID!, $secondId: ID!) {
firstDecorSheet: findDecorSheetByID(id: $firstId) {
refIdArray
sheetName
_id
}
secondDecorSheet: findDecorSheetByID(id: $secondId) {
refIdArray
sheetName
_id
}
}
`;
I have been searching for 2 days throughout docs, YouTube and GitHub projects to see if I could solve this problem. I am creating a pizza ordering system of which I have a few different GraphQL types. In this scenario, I have a Topping Type and a Pizza Type. The Pizza Type contains a toppings field which is an array of Topping type.
type Topping {
id: ID!
name: String!
price: Float!
createdAt: String!
}
type Pizza {
id: ID!
location: String!
price: Float!
toppings: [Topping!]!
createdAt: String!
toppingCount: Int!
}
The Mutation is:
createPizza(pizzaInput: PizzaInput): Pizza!
input PizzaInput {
location: String!
price: Float!
toppings: [ID]! # How To Pass Existing Topping IDs Copied From DB?
createdAt: String!
}
Passing an array of IDs when calling the mutation within GraphQL playground results in many different errors relation to the structure of the toppings input.
mutation {
createPizza(pizzaInput: {
location:"Barcelona"
price:12
toppings: { # How To Structure This Input?
create: [
connect:"5faaca3129c74ff103d3ccaf"
connect:"5fab01e8e0a1942d701fd408"
connect:"5faaed887ac3c53010b8075b"
connect:"5fab024de0a1942d701fd409"
]
}
createdAt:"Now"
}){
id
price
location
toppings
createdAt
toppingCount
}
}
Below is the create pizza mutation resolver:
Mutation: {
createPizza: async (
_,
{ pizzaInput: { location, price, toppings, createdAt } }
) => {
const { valid, errors } = validateCreatePizza(location, price);
if (!valid) {
throw new UserInputError("Errors", { errors });
}
const newPizza = Pizza({
location,
price,
toppings,
createdAt
});
console.log(newPizza);
const pizza = await newPizza.save();
return pizza;
}
}
Topping and Pizza Models:
const toppingSchema = new Schema({
name: String,
price: Number,
createdAt: String
});
module.exports = model("Topping", toppingSchema);
const pizzaSchema = new Schema({
location: String,
price: Number,
toppings: [
{
type: Schema.Types.ObjectId,
ref: "toppings"
}
],
createdAt: String
});
module.exports = model("Pizza", pizzaSchema);
Modify your the structure of your input: i. separate each key/value pair passed as argument object, pizzaInput, with commas; ii. make price a float; iii. toppings in the context of your input type is an array of IDs -- update syntax to reflect that - remove create key and comma separate array values (there is no need to further nest the array in an object).
mutation {
createPizza(pizzaInput: {
location: "Barcelona",
price: 12.00,
toppings: [
"5faaca3129c74ff103d3ccaf",
"5fab01e8e0a1942d701fd408",
"5faaed887ac3c53010b8075b",
"5fab024de0a1942d701fd409"
],
createdAt: "Now"
}
}) {
id
price
location
toppings
createdAt
toppingCount
}
}
FWIW, looking at your schema for Pizza type, unless a topping will always present, I would make that type nullable, that is, toppings: [Topping!].
So I have the following in my Prisma datamodel. There's a relationship between the games and the characters, where the characters can appear in multiple games. Also the characters should be able to be listed on the games when the games alone are queried:
type Game {
id: ID! #unique
name: String! #unique
name_ja: String #unique
name_ko: String #unique
name_zh_CN: String #unique
name_zh_TW: String #unique
name_zh_HK: String #unique
characters: [Character]
filters: [GameFilter]
}
type Character {
id: ID! #unique
name: String! #unique
name_ja: String #unique
name_ko: String #unique
name_zh_CN: String #unique
name_zh_TW: String #unique
name_zh_HK: String #unique
games: [Game]
}
I then have this as a mutation for updating characters in my schema. I pass along an array of Game IDs because there's the possibility of multiple games being added within the same mutation:
updateCharacter(
name: String
name_ja: String
name_ko: String
name_zh_CN: String
name_zh_HK: String
name_zh_TW: String
id: ID!
games: [ID]
): Character!
And the following mutation written:
async updateCharacter(parent, args, ctx, info) {
if (!ctx.request.userId) {
throw new Error('You must be logged in');
}
const updates = {...args};
delete updates.id;
delete updates.games;
console.log(args.games);
const res = await ctx.db.mutation.updateCharacter({
data: updates,
games: {
connect: {
id: args.games
}
},
where: {
id: args.id
}
}, info);
return res;
}
And the following mutation written React-side. It's meant to pass along an array of IDs to the mutation (which will be expected because the schema assumes that an array of IDs will be passed along:
const UPDATE_CHARACTER_MUTATION = gql`
mutation UPDATE_CHARACTER_MUTATION(
$name: String!
$name_ja: String!
$name_ko: String!
$name_zh_CN: String!
$name_zh_TW: String!
$name_zh_HK: String!
$id: ID!
$games: [ID]!
) {
updateCharacter(
name: $name
name_ja: $name_ja
name_ko: $name_ko
name_zh_CN: $name_zh_CN
name_zh_TW: $name_zh_TW
name_zh_HK: $name_zh_HK
games: $games
id: $id
) {
id
name
name_ja
name_ko
name_zh_CN
name_zh_TW
name_zh_HK
games {
id
name
}
}
}
`;
I am also passing along the IDs of the games in an array onSubmit within the form to the mutation.
The result is that the mutation passes, but will only update the name fields, and the connection with the Games remains unchanged.
Not sure what I can do to make this mutate properly. I'm not sure whether passing the array directly into the mutation in the connect is what's causing the issue, but I tried mapping through and passing along each game id individually, but had the same result of the connection not updating.
The problem seems to be two-fold.
Regarding not seeing any changes at all:
In the mutation written, games is added to the async request json outside of data, meaning the data will never be found by the request.
Rather than:
data: ...,
games: ...
games must be part of data like such:
data: {
games: ...
}
Regarding wanting to do multiple connects:
GraphQL supports this style of nested updates using the following connect syntax:
connect: [
{ id : /* id from args */ },
{ id : /* another id from args */ },
...
]
I want to query a nested field for multiple variables.
In this case, I want to query RPR, but only return RPR if the label of the nested Region is given. One variable for the nested Region (field: label) works fine, but how can I filter on multiple variables of the same field?
The way I see it, when I call up the query-client (in my case through Apollo), I want to give an array as a variable and let the query in the backend go through that array and return results based on any of the variables given in the array.
The resolver does nothing more then:
rPRs: (root, args, ctx, info) => {
return ctx.db.query.rPRs(args, info);
}
The relevant part of the schema:
type RPR {
id: ID! #Unique
RPRID: String! #Unique
state: String
region: Region!
resource: Resource!
price: Float
theme: String
editionTitle: String
information: String
}
type Region {
id: ID! #Unique
regionID: String! #Unique
label: String! #Unique
name: String! #Unique
aov: Float!
aov_multiplier: Float!
}
The current query to retrieve all 'RPR' with nested regions:
query ADVICE_RESOURCES_QUERY($theme: String, $regio: String) {
rPRs(where: {
theme: $theme,
region: {
label: $regio
}
})
{
RPRID
region {
label
}
}
}
you should be able to use the label_in filter and provide the array of Strings to it. Your where would then look like this:
where: {
theme: $theme,
region: {
label_in: $regio
}
}