Queries and Resolvers

I have tried GQL quickstart:


and
I have followed the tutorial at

closely adapting it to my own db
Here is the schema:
type User 
 {  
    active : Boolean!
    user_name : String! @unique
    password : String! @unique
    ethaddress : String! @unique
    description : String
    email : String @unique 
    mobile : String @unique
    member_since: Int!
}

type Player 
 {  address : String! @unique
    rank : Int!
    challengeraddress : String
}

type Ranking
  { 
    active : Boolean!
    rankingname : String! @unique
    rankingdesc : String
    rankingowneraddr : String! @unique
    }

type UserJoinedRanking
  { 
    active : Boolean!
    rankingid : Int!
    rankingname : String!
    rankingowneraddr : String!
    }

type Todo {
   title: String!
   completed: Boolean
}

type Mutation {
  createAndOrLoginUser(active: Boolean!, user_name: String!, password: String!, ethaddress: String!, description: String, email: String, mobile: String): String! @resolver(name: "create_andor_login_user")
  createNewPlayer(active: Boolean!, address: String!, rank: Int!, challengeraddress: String): String! @resolver(name: "create_new_player")
  createNewRanking(active: Boolean!, rankingname : String!, rankingdesc : String, rankingowneraddr : String!): String! @resolver(name: "create_new_ranking")
  createNewUserJoinedRanking(active: Boolean!, rankingid : String!, rankingname : String!, rankingowneraddr : String!): String! @resolver(name: "create_new_userjoinedranking")
}

type Query {
  allUserNames: [String!]! @resolver(name: "all_user_names")
  allPlayerAddresses: [String!]! @resolver(name: "all_player_addresses")
  allPlayerRanks: [Int!]! @resolver(name: "all_player_ranks")
  allPlayerChallengerAddresses: [String!]! @resolver(name: "all_player_challenger_addresses")
  allPlayers: [Player] @resolver(name: "all_players")
  allRankings: [Ranking] @resolver(name: "all_rankings")
  allUserJoinedRanking: [UserJoinedRanking] @resolver(name: "all_userjoinedranking")
  allTodos: [Todo!]
  todosByCompletedFlag(completed: Boolean!): [Todo!]
}

FQL for allTodos:

{
  name: "allTodos",
  unique: false,
  serialized: true,
  source: "Todo"
}

If I run the query from the GQL quickstart in Playground:

query FindAllTodos {
  allTodos {
    data {
      _id
      title
      completed
    }
  }
}

I get the expected data. For allRankings
however:
FQL:

{
  name: "allRankings",
  unique: false,
  serialized: true,
  source: "Ranking"
}

if I run the query from the tutorial:

query AllRankings {
  allRankings {
    data {
      _id
      rankingname
      rankingowneraddr
    }
  }
}

In Playground this second query gives error:

{
  "data": null,
  "errors": [
    {
      "message": "Cannot query field 'data' on type 'Ranking'. (line 3, column 5):\n    data {\n    ^",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ]
    }
  ]
}

The only apparent difference (apart from the ! after Todo in schema which isnā€™t affecting the successful FindAllTodos query if I remove/leave it) is that allRankings is associated
with a resolver (@resolver(name: ā€œall_rankingsā€)).
The all_rankings resolver is defined in FQL as:

{
  name: "all_rankings",
  role: null,
  body: Query(Lambda([], Select("data", Paginate(Match(Index("allRankings"))))))
}

Why do I get an error with the AllRankings query and not with the FindAllTodos query? thanks ā€¦

Hi @FreeRoss,

would you try to change your function like this:

 Update(Function('all_rankings'),
{
  name: "all_rankings",
  role: null,
  body: Query(Lambda([], Select("data", Map(Paginate(Match(Index("allRankings"))),Lambda('x',Get(Var('x')))))))
}
)

and your query this way:

 query AllRankings {
  allRankings {
    _id
    active
    rankingname
  }
}

Luigi

Thanks Luigi that worked.
This solution was not apparent to me looking through the documentation, even now you have given me the answer. The closest I found mentioned:

Select("active", Get(Index("index_name")))

(ie. some way off the actual solution you gave me)
Am I looking in the wrong place?

I am currently not sure when to focus on GQL documentation to resolve an issue like this or FQL documentation as there appears to be overlap (e.g. they both cover UDFs). I can read both but then Iā€™m not sure which one to attempt to apply. For example, the query you specify in your answer is quite different from the one in the FQL documentation (any language)(ā€˜postsā€™ would be ā€˜allRankingsā€™, of course):

 query AllRankings {
  allRankings {
    _id
    active
    rankingname
  }
}

compared to:

serverClient.query(
  q.Get(q.Ref(q.Collection('posts'), '192903209792046592'))
)
.then((ret) => console.log(ret))

and yet I feel I should focus on FQL since that is the format requested in the Forum.

Perhaps this serverClient would run on the client in a terminal window, but, even so, there is no similarity in syntax. So my biggest problem currently is effectively applying the comprehensive documentation.

From the perspective of developing my application all I need to do is correctly define the functionality I need in FaunaDB and then apply elm-graphql to link my front and back ends. Iā€™m trying to avoid asking in the forum how each query/function etc. should be specified in FQL and use the documentation to figure it out myself.

Do you have any feedback on the difficulties I am having doing this and any suggestions as to how I should be approaching this problem?

Perhaps there is something Iā€™m clearly misunderstanding that can be addressed in a reference article or section of the documentation?
Thanks ā€¦

Hi @FreeRoss,
Sorry for the misunderstanding, Iā€™m trying to shad some light on the topic.
FQL is quite different from any other DB language, and you might need some time before mastering it.
Letā€™s start with the first query:

 Select("active", Get(Index("index_name")))

Index(ā€œindex_nameā€) is a reference to an index with name ā€œindex_nameā€
With a reference, you can look at any metadata definition (indexes, functions, collections) or at data in any document using the function Get()

> Get(Index("allTodos"))
{ ref: Index("allTodos"),
  ts: 1598953094866000,
  active: true,
  serialized: true,
  name: 'allTodos',
  source: Collection("Todo"),
  data:
   { gql:
      { ts: Time("2020-09-01T09:38:14.517525Z"),
        meta:
         { name: 'allTodos',
           directives: [ { name: 'index', args: { name: 'allTodos' } } ],
           type: { List: { NotNull: { Named: 'Todo' } } } } } },
  unique: false,
  partitions: 8 }

or for docs:

> Get(Ref(Collection("Ranking"), "275454960714383878"))
{ ref: Ref(Collection("Ranking"), "275454960714383878"),
  ts: 1598953171430000,
  data:
   { active: true,
     rankingname: 'Test 9',
     rankingdesc: 't9',
     rankingowneraddr: '0x267dsfdfdgsdfsdfgecb3c3ec88332a537dddggdvsd' } }

The Select() extract a field from a specific document:

> Select(['active'],Get(Index("allTodos")))
true

Said that, trying to answer your second question, should you put your focus on FQL or GraphQL forfixing the issue?
In your case on both, since you are using a resolver (which is an UDF function written in FQL).

About the queries you are comparing, there is a huge difference because the first is pure GraphQL syntax, the second instead is FQL via JS driver.

At the end, depending on the projects you are developing, you have to gain a good understanding on GraphQL, to retrieve/ingest your data, as well with FQL for writing ad-hoc functions for your specific needs.

By the way, every time you create a type, Fauna creates for you the underlying collection and mutations for adding, updating and deleting this specific type, and a query for retrieving data from such collection.

Hope this answer all your questions/doubts. In any case, Iā€™m available for further help.

Luigi

2 Likes

Thanks again @Luigi_Servini for the further explanation. Tbh I still would not have figured out:

body: Query(Lambda([], Select("data", Map(Paginate(Match(Index("allRankings"))),Lambda('x',Get(Var('x')))))))

from the extra info. However, perhaps I would not be expected to at this stage (maybe it was a fix for a problem I had introduced (?)) and for such circumstances I would simply have to ask for help (mine is only a small app with a handful of functions/queries). Your comments continue to be helpful and appreciated ā€¦

Hey FreeRoss,

in terms of what you are struggling with and things that could help you. I think I answered this in another post but Iā€™ll answer it for other people that stumble upon this and have similar questions. The reason why you had to select data is that FaunaDB transforms the return value of your regular GraphQL queries (non resolver) to pages. image
since it will automatically generate code that supports pagination.

Which it doesnā€™t do for your resolver since itā€™s not going to generate code for that, your FQL query did return pages (you used Pagination) which typically have a ā€˜dataā€™ field.

In terms of resources. For how UDFs and GraphQL queries interact and how you could go about writing these step by step I recently wrote an elaborate stackoverflow answer:

To learn FQL:

and the great series by @pier:

The idea is that these resources find a place in the docs in the long run.

2 Likes

@databrecht. Thanks for the follow up info ā€¦ useful background reading ā€¦