Shouldn't variables be defined on fragment calls in GraphQL? - graphql

I'm new to GraphQL. I was going through the documentation and found something which I feel is odd.
The way to pass data to variables in fragments is to do it through the root query the fragments are part of. The example given in the docs is repeated here for convenience.
query HeroComparison($first: Int = 3) {
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
friendsConnection(first: $first) {
totalCount
edges {
node {
name
}
}
}
}
My question is, why does HeroComparison define the parameter to be passed down to the enclosed fragments and not the fragments directly? We use the variables in the fragments, so shouldn't it be something like this?
query HeroComparison {
leftComparison: hero(episode: EMPIRE) {
...comparisonFields($first: Int = 3)
}
rightComparison: hero(episode: JEDI) {
...comparisonFields($first: Int = 3)
}
}
fragment comparisonFields on Character {
name
friendsConnection(first: $first) {
totalCount
edges {
node {
name
}
}
}
}
Since this is repetitive, we may even do something like
query HeroComparison {
leftComparison: hero(episode: EMPIRE) {
...comparisonFields
}
rightComparison: hero(episode: JEDI) {
...comparisonFields($first: Int = 2)
}
}
fragment comparisonFields on Character {
*var $first: Int
name
friendsConnection(first: $first = 3) {
totalCount
edges {
node {
name
}
}
}
}
My main concern in asking this is what if we wanted the first instantiation of comparisonFields to get the value 3 and the second to get 2 in the same query?
The docs page mentioned nothing to this end.
Also, aren't the second and third approaches better from the standpoint of separation of concerns?

Pros and Cons of your approach are discussed in detail in this issue.

Related

Is there a way to filter out null values for literals and references

If we have an Author with no beacons to Articles and thus WroteArticles was null and we wanted to only return Authors who had non-empty/non-null WroteArticles, how could that be done?
As an example we can use the Weaviate demo site
I've tried filter operations using where and various operators, but I must be missing something obvious. Example of a query I've tried on my own data set below, where I did have a Thing with no beacons.
{
Get {
Things {
Author (where:{
operator:Equal,
path:["WroteArticles"]
valueString:" "
}){
name
WroteArticles {
... on Article {
InPublication {
... on Publication {
name
}
}
}
}
}
}
}
}
You can now do this as follows (also in the documentation):
{
Get {
Things {
Author(
where:{
valueInt: 2
operator:GreaterThanEqual
path: ["WroteArticles"]
}
) {
name
WroteArticles {
... on Article {
title
}
}
}
}
}
}

GraphQl API select specific values

I have the following query :
{
allPeople {
people {
name
filmConnection {
films {
title
}
}
}
}
}
I would like to select all people that have a film connection with the title a new hope. How do i select this specific thing from the API. I could also just get it like this and handle it in the code. But surely there is a better way.
What i'd expect :
{
allPeople {
people {
name
filmConnection {
films {
title : "a new hope"
}
}
}
}
}
That didnt work..
Try out here in this playground :
https://graphql.org/swapi-graphql?query=%7B%0A%20%20allPeople%20%7B%0A%20%20%20%20people%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20filmConnection%20%7B%0A%20%20%20%20%20%20%20%20films%20%7B%0A%20%20%20%20%20%20%20%20%20%20title%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A
graphql queries ... are not for building [sql] queries ;)
this is more for defining shape of required data
parameter CAN BE passed to deeper child (f.e. can be used to filter films)
{
allPeople {
people {
name {
filmConnection {
films(title_eq:"a new hope") {
title
}
}
}
}
}
}
... if API supports this kind of filtering for films
... but it won't filter people - you'll have all people AND filtered films (for all people) because filters won't work on parents.
You CAN have custom API that will be this kind of filtering aware, f.e.
{
allPeople {
people(connectedFilmTitle_eq:"a new hope") {
name {
filmConnection {
films {
title
}
}
}
}
}
}
customized (not automatically gnerated) peolpe resolver can make appriopriate query [on joined tables] and return structure you're asking for.
In that case probably you don't need deeper structures - ...filmConnection { films { title - you know this data earlier (filter parameters).
... but probably you have a many2many relation and cen reverse this query:
{
allFilms {
films(title_eq:"a new hope") {
title {
peoleConnection {
people {
name
}
}
}
}
}
}

GraphQL fallback query if no results

I have the following query:
{
entity(id: "theId") {
source1: media(source: 1){
images{
src, alt
}
}
source2: media(source: 2){
images{
src, alt
}
}
}
}
That give me a result like:
{
"entity": [
{
"source1": {
"images": [{"src": "", "alt": ""}]
},
"source2": {
"images": [{"src": "", "alt": ""}]
}
}
]
}
Is there a way to have a single result of source1 and source2, executing source1 and if it has no result it use source2 as fallback?
You are querying two fields (source1, source2) so something has to come back for both of them (null being a possible option). If you want to check them in a sequence you should probably break the query in two and run them one at the time from the client.
Could you perhaps change so you only query a single source field and have the resolver (on the server) return what makes sense based on what is available, so to speak? Like this:
{
entity(id: "theId") {
source: media(sourcesList: [1, 2]){
images{
src, alt
}
}
}
}
where sourceList is the sources to try, in order. So the resolver (server) can then check if source 1 is available and if not return source 2.
You could also add a field to let the client know which source was actually returned from the proposed list (sourceNumberReturned below would return 1 if source 1 was returned, otherwise 2).
{
entity(id: "theId") {
source: media(sourcesList: [1, 2]){
images{
src, alt
}
sourceNumberReturned
}
}
}

how to query prismic slices and returning data from each slice

I'm trying to use Gatsby's /___graphq debugger and the README file for gatsby-source-prismic says you can return slices. So below I'm returning the slice with a name PrismicProductBodySteps.
{
allPrismicHomePage {
edges {
node {
data {
seo_title
body {
__typename
... on PrismicProductBodySteps {
}
}
}
}
}
}
}
}
Can someone explain to me what ... on PrismicProductBodySteps means ?
In a gatsby component I've seen this as an example.
body {
... on PrismicProductsBodySteps {
...ProductStepsFragment
}
Can anyone explain to me what the ...ProductStepsFragment means ?
PrismicProductBodySteps would be a custom node type name representing a dynamic series of content blocks. That custom node type name is coming from a Prismic data model; yours will likely be different.
According to the gatsby-source-prismic documentation, using custom node type names requires you to figure out what they are first:
The easiest way to get the type of nodes is to use the /___graphql
debugger and run the below query (adjust the document type and field
name).
{
allPrismicPage {
edges {
node {
id
data {
body {
__typename
}
}
}
}
}
}
Once you have your custom node type name, you can use a GraphQL fragment to pull data specific to each fragment. Again, this would depend on how you have the fragments defined in your data model, but it would look something like this:
{
allPrismicHomePage {
edges {
node {
data {
seo_title
body {
__typename
... on PrismicYourContentBlockOne {
text {
html
}
}
... on PrismicYourContentBlockTwo {
text {
html
}
}
... on PrismicYourContentBlockThree {
text {
html
}
}
}
}
}
}
}
}

How to populate Enum from the values retrieved from Database

Looking at the example here at Message Controller for Pizza Example, if I want to populate Size or Kind based on some user input and make a call to the database, how would I do that?
So far as I know, there is not an easy way to populate the Enum at runtime.
It looks like this hasn't been implemented yet. I took a look inside https://github.com/Microsoft/BotBuilder/blob/master/CSharp/Library/FormFlow/FormBuilder.cs and found this:
internal static void TypePaths(Type type, string path, List<string> paths)
{
if (type.IsClass)
{
if (type == typeof(string))
{
paths.Add(path);
}
else if (type.IsIEnumerable())
{
var elt = type.GetGenericElementType();
if (elt.IsEnum)
{
paths.Add(path);
}
else
{
// TODO: What to do about enumerations of things other than enums?
}
}
else
{
FieldPaths(type, path, paths);
}
}
else if (type.IsEnum)
{
paths.Add(path);
}
else if (type == typeof(bool))
{
paths.Add(path);
}
else if (type.IsIntegral())
{
paths.Add(path);
}
else if (type.IsDouble())
{
paths.Add(path);
}
else if (type.IsNullable() && type.IsValueType)
{
paths.Add(path);
}
else if (type == typeof(DateTime))
{
paths.Add(path);
}
}
Notice the TODO about enumerations other than enums.
Outside of the FormBuilder we can use PromptDialog.Choice which takes an IEnumerable<> of your options.
It is possible to chain dialogs together, so you may have to split your FormDialog into two with the PromptDialog in-between.
Alternatively take a fork of BotBuilder and implement the TODO!

Resources