Is it possible in GraphQL to query for records missing a certain relationship?
E.g.
Type Foo
- id
Type Bar
- id
- foo_id
How can I search for Foo which don't have any Bar associated?
I think I found the answer.
query FooMissingBar {
foo(where: { _not: { bar: {} } }) {
id
}
}
Related
My schema defines an Employee type that has 15 or so fields on it. It's then used multiple times in other areas:
type Employee {
active: Boolean!
name: String
id: Int!
...
}
type Room {
owner: Employee!
delegate: Employee
}
99% of the time, I want the same three fields when returning data on an employee. So I end up writing a query like this:
query {
rooms {
owner: {
name
id
active
}
}
}
which is repetative when something has multiple employees. Is there a way to define some type of transformation so that instead I'd do something like:
query {
rooms {
owner: #commEmpFields
}
}
My initial thought was to create a custom ObjectType<Employee> but then I realized that I didn't know how to map that to the query.
Say I have the following query:
foo {
id
bar
baz #client
}
I can (in fact, I must) create a resolver to generate the local baz property. So I control its data type.
Now, what if I wanted to alter the data type of bar, a remote property?
I want to make bar a BigNumber instead of a string. Imagine something like this:
resolvers: {
bar: {
return new BigNumber(bar);
},
baz: { ... }
}
Is this possible?
TLDR; In most situations, you can't, so add a bit of redundancy by creating a local property with the correct data type.
Basic Query
Doesn't work 😞
query Foo {
id
bar
baz {
id
}
}
If you add a resolver like this:
export default {
Foo: {
bar: ({ bar }) => new BigNumber(bar),
}
}
It will NOT work.
Basic Query with #client
Works 😊
query Foo {
id
bar
baz {
id
}
qux #client
}
Just by adding another property, say qux, that has the #client directive, you will fire the bar resolver defined above.
Complex Query with Fragments
Doesn't work 😞
If you rewrite the query like this:
fragment Baz on Foo {
id
}
query Foo {
id
bar
qux #client
...Baz
}
It will NOT work anymore, even with the #client directive.
My environment:
apollo-cache-inmemory#^1.6.3
apollo-client#^2.6.4
apollo-link-http#^1.5.16
graphql#^14.5.8
graphql-tag#^2.10.1
And I was connecting to a blockchain subgraph hosted on thegraph.com. YMMV.
I have added a resources table to my schema, connecting to a Plants table:
type Resource #model
{
id: ID!
name: String!
Plants: [Plant] #connection(name: "ResourcePlant")
}
Ran amplify push, and all resources were created properly.
Now I wanted to add a Resource, and link it to all Plants properly.
Do you know how is the sintaxe I should use to run the recently created mutation createResource in order to add the items on Plant I want to include to that resource?
I tried to run like this:
mutation CreateResource {
createResource (input: {
name: "Plant",
Plants : {
items :
{ id: "f9a0468e-da74-41d5-8287-1cb6a76b25a5" }
}
}
) {
name,
Plants {
items {
id
}
nextToken
}
}
}
This was the error message:
Validation error of type WrongType: argument 'input' with value
'ObjectValue{objectFields=[ObjectField{name='name',
value=StringValue{value='Plant'}}, ObjectField{name='Plants',
value=ObjectValue{objectFields=[ObjectField{name='items', value=ObjectValue{objectFields=[ObjectField{name='id',
value=StringValue{value='f9a0468e-da74-41d5-8287-1cb6a76b25a5'}}]}}]}}]}'
contains a field not in 'CreateResourceInput': 'Plants' # 'createResource'
How did you define Plant?
And have you checked this example? https://aws-amplify.github.io/docs/cli-toolchain/graphql#connection
Ok, after some headache, I found what was missing in my model. For me so far it has proved to be the best way of doing this relationship...
I have added on my Plant type, on schema definition, a field named plantResourceId (other than the one used for the #connection directive). What I found out was that, by convention, when inserting/updating a record on "Plant" and adding the resource "id" field content of the resource I want to "connect" to that plant, it will automatically be retrieved when "Resources" is queried, for each item - what is better: Out-of-the-box from codegen.
Insert example
mutation CreatePlant {
createPlant(input:{
name: "MyPlant",
plantResourceId: "id-for-connected-resource"
}) {
name,
plantResourceId
}
}
Query example to retrieve items:
query listPlantsOnResource {
listResources(filter: {
name: {
contains: "myfilter"
}
}) {
items {
id
name
Plants
{
items {
id
name
description
}
}
}
}
}
It worked very well!
Thanks all who contributed!
I query some type from graphql schema, and for a specific field, I want to get it with the enum description instead of the enum value.
type Gigi {
a: SomeEnum!
b: Int!
}
enum SomeEnum {
"Bla"
BLA
"Foo"
FOO
}
I want to get the 'Gigi.a' field, with the description of the enum.
For example:
{
a: "Bla"
b: 5
}
Does anyone know if this is possible?
Descriptions of types, fields and enum values exist for documentation purposes only and are therefore only accessibly through an introspection query:
query {
__type(name: "SomeEnum") {
enumValues {
name
description
}
}
}
Also note that there is nothing in the spec that requires enum values to be in all caps, so you can have an enum like:
enum SomeEnum {
Bla
Foo
}
Let's say I have a table t1 that is foreign key'd to another table t2. For simplicity, t2 only has columns 'name' and 'id' which are both unique. I store the id in t1.
My problem is I want to write a mutation where I know the name but I don't know the id when I go to store something in t1. Is there a way to query inside of my mutation so that it converts the value in my statement?
Perhaps a plugin I can add to my project?
I end up with something like this where I pass in a known name but I want to store the id
mutation addT1(
$knownT2Name: String!,
) {
createT1 (
input: {
t1: {
id: $component
# Is there a way to convert this to the id inside the query
# Or do I need to query for the id with the name first then pass that in?
t2_id: $knownT2Name
}
}
) {
t1 {
id
t2_id
}
}
}
This is a simple example. The reason I don't want to query for the id with the name is in actuality t1 is foreign key'd to a myriad of other tables with the same situation and I don't want to do 9+ queries just to convert each string to an integer id.
I would much rather be able to do something like this:
mutation addT1(
$knownT2Name: String!,
) {
createT1 (
input: {
t1: {
id: $component
t2_id: t2Byt2(name: $knownT2Name) { id }
}
}
) {
t1 {
id
t2_id
}
}
}
Where t2Byt2(name: $knownT2Name) { id } would be a sub-query that passes the name and gets the id, then stores the id in 't2_id'
I'm looking at a nested mutations plugin for postgraphile (Here's the GitHub)but I haven't had any traction. It's not quite what I'm looking for.
For the simple relationship I believe you want something like: (using the nested mutations plugin). This only works on CREATE. No luck with an UPSERT.
mutation addT1($t1Name: String!, $t2Name: String!) {
createT1(
input: {
T1: {
name: $t1Name,
t2ToT2: { connectByT2: { name: $t2Name } }
}
}
) {
t1 {
t1Id
name
t2ByT2 {
name
}
}
}
}