GraphQL query to cross reference data - graphql

Please find a basic simplified problem and a question below:
Monopoly Example
Data Types:
USER
name
houses (one-to-many)
STREET
name
HOUSE
street (one-to-one)
Note that in my data model there is no reference between user and streets (maybe monopoly wasn't the best example -.-)
Question:
A user can have several houses on different streets. How can I query a list of streets that a specific user has houses on?
Wanted Result:
{
"data": {
"User": {
"name": "The Hat",
"streets": [
{
name: "Bow Street"
},
{
name: "Oxford Street"
},
{
name: "Park Lane"
},
]
}
}
}
Is that possible?

Fetching relational data like that is typically handled by having nested fields in your query. The ability to traverse the data graph in a query is one of GraphQL's biggest benefits.
In general, this article about GraphQL APIs is a helpful resource to understand how it works.
Let's look at some different possible queries.
Query a list of streets that a specific user has houses on
query {
allStreets(filter: {
house: {
user: {
id: "user-id"
}
}
}) {
name
}
}
Here we make use of a relational filter passed in as an argument to query the streets that are related to a hours that is related to a specific user, which results in:
{
"data": {
"allStreets": [
{
"name": "Bow Street"
},
{
"name": "Oxford Street"
},
{
"name": "Park Lane"
}
]
}
}
We can see that we get back a list of streets. We could also include the house field in the allStreets query to obtain that information as well.
Query a specific user object and a list of streets that it has houses on
query {
User(id: "user-id") {
name
houses {
street {
name
}
}
}
}
Here we specify a user by id, so the top-level object of the result is a single user object. Additionally, we are getting back a list of streets that user has houses on:
{
"data": {
"User": {
"name": "The Hat",
"houses": [
{
"street": {
"name": "Bow Street"
}
},
{
"street": {
"name": "Oxford Street"
}
},
{
"street": {
"name": "Park Lane"
}
}
]
}
}
}
What's notable is that the structure of the response follows the structure of the query precisely.

Related

Incorrectly selected data in the query

Only articles that contain the EmailMarketing tag are needed.
I'm probably doing the wrong search on the tag, since it's an array of values, not a single object, but I don't know how to do it right, I'm just learning graphql. Any help would be appreciated
query:
query {
enArticles {
title
previewText
tags(where: {name: "EmailMarketing"}){
name
}
}
}
result:
{
"data": {
"enArticles": [
{
"title": "title1",
"previewText": "previewText1",
"tags": [
{
"name": "EmailMarketing"
},
{
"name": "Personalization"
},
{
"name": "Advertising_campaign"
}
]
},
{
"title": "title2",
"previewText": "previewText2",
"tags": [
{
"name": "Marketing_strategy"
},
{
"name": "Marketing"
},
{
"name": "Marketing_campaign"
}
]
},
{
"title": "article 12",
"previewText": "article12",
"tags": []
}
]
}
}
I believe you first need to have coded an equality operator within your GraphQL schema. There's a good explanation of that here.
Once you add an equality operator - say, for example _eq - you can use it something like this:
query {
enArticles {
title
previewText
tags(where: {name: {_eq: "EmailMarketing"}}){
name
}
}
}
Specifically, you would need to create a filter and resolver.
The example here may help.

graphQL filter array containing ALL

I am quite new to graphQL, and after searching the whole afternoon, i didn't found my answer to a relative quite simple problem.
I have two objects in my strapi backend :
"travels": [
{
"id": "1",
"title": "Bolivia: La Paz y Salar de Uyuni",
"travel_types": [
{
"name": "Culturales"
},
{
"name": "Aventura"
},
{
"name": "Ecoturismo"
}
]
},
{
"id": "2",
"title": "Europa clásica 2020",
"travel_types": [
{
"name": "Clasicas"
},
{
"name": "Culturales"
}
]
}
]
I am trying to get a filter where I search for travels containing ALL the user-selected travel_types.
I then wrote a query like that :
query($where: JSON){
travels (where:$where) {
id # Or _id if you are using MongoDB
title
travel_types {name}
}
And the parameter i try to input for testing :
{
"where":{
"travel_types.name_contains": ["Aventura"],
"travel_types.name_contains": ["Clasicas"]
}
}
This should return an empty array, because none of the travels have both Aventura and Clasicas travel-types.
But instead it returns the travel with id=2. It seems that only the second filter is taken.
I searched for a query which would be like Array.every() in javascript, but i wasn't able to find.
Does someone has an idea how to achieve this type of filtering ?
Thank you very much,

GraphQL - How to get field types from the retrieved schema?

Knowing the schema (fetched via getIntrospectionQuery), how could I get the type of a particular field?
For example, say I run this query:
query {
User {
name
lastUpdated
friends {
name
}
}
}
and get this result:
{
"data": {
"User": [
{
"name": "alice",
"lastUpdated": "2018-02-03T17:22:49+00:00",
"friends": []
},
{
"name": "bob",
"lastUpdated": "2017-09-01T17:08:49+00:00",
"friends": [
{
"name": "eve"
}
]
}
]
}
}
I'd like to know the types of the fields and construct something like this:
{
"name": "String",
"lastUpdated": "timestamptz",
"friends": "[Friend]"
}
How could I do that without extra requests to the server?
After retrieving the schema, you can build it into a JSON object (if your graphql framework does not do it already for you).
Using a JSON parser, you can retrieve the the types of each field.
I will not enter into the detail, as it would depend on the technology your are using.

Strapi GraphQL query: "start" argument wouldn't work

I am running into a very strange problem with my queries in Strapi (version 3.0.0-alpha.26.2). I have a users collection with 3 documents that I'm trying to fetch via GraphQL. To fetch all users the query is:
users {
firstName
}
This returns the following:
{
"data": {
"users": [
{
"firstName": "Arnold"
},
{
"firstName": "Bill"
},
{
"firstName": "Vin"
}
]
}
}
3 names. Now, say, I wished to retrieve only the first 2 users. For such pagination use-cases, there's two arguments one could pass in a Strapi query: start (defines the index to start at) and limit (defines the number of elements to return). So now the query would be:
users(start: 0, limit: 2) {
firstName
}
This returns the first two names as expected:
{
"data": {
"users": [
{
"firstName": "Arnold"
},
{
"firstName": "Bill"
}
]
}
}
But what if I want the last 2 users here, i.e. Bill and Vin? Should be as straightforward as:
users(start: 1, limit: 2){
firstName
}
But this still returns Arnold and Bill, while you'd expect the following:
{
"data": {
"users": [
{
"firstName": "Bill"
},
{
"firstName": "Vin"
}
]
}
}
No matter what value I use for start, it always starts at the 0th item. You could do start: 200 (when there are only 3 items in the users collection) and it'd still return the exact same result! What sorcery is this??
The issue can be reproduced at https://dev.schandillia.com/graphql.

How to simplify graphql response

For example my graphql's query is:
products {
name,
price,
brand {
name
}
}
Which produces this response:
{
"data": {
"products": [
{
"name": "Black Dress",
"price": 520,
"brand": {
"name": "Coach"
}
}
]
}
}
Can this
"brand": {
"name": "Coach"
}
be simplified to this somehow?
"brandName": "Coach"
Currently, without any additional dependencies and if you don't want to update schema, you cannot control the shape of the object returned by GraphQL if you like to control the shape that can be possible by graphql-leveler.
The graphql-leveler will provide a method call _get through which you can manage the shape of your object you can do simply:
{
brandName: _get(products: 'brand.name')
}
Note: to use graphql-leveler, simply add graphql-leveler to your dependencies, require LevelerObjectType, and use it instead of GraphQLObjectType. Done!

Resources