grpc/protobuffer ask for specific fields - protocol-buffers

GraphQL lets you ask for specific fields, the response contains only the fields that you had asked for. For example:
a graphql query like:
{
hero {
name
}
}
will return:
{
"data": {
"hero": {
"name": "R2-D2"
}
}
}
where as a graphQl query like:
{
hero {
name
friends {
name
}
}
}
would return:
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke"
},
{
"name": "Han Solo"
},
{
"name": "Leia"
}
]
}
}
}
Is there a similar mechanism/library/pattern that can be used in gRPC to achieve the same?

FieldMask is similar in protobuf. It is a list of fields to retain, so the first example would be paths: "hero.name" and the second would be paths: ["hero.name", "hero.friends.name"].
It is probably most frequently used to specify which fields should be changed in an update. But it can equally be used to specify the fields that should be returned.
The server can either process the FieldMask directly (e.g., only using the listed fields in a SELECT SQL query), or it can retrieve all the information and filter the result using FieldMaskUtil.merge() to copy just the requested fields into a new proto message to return to the client.

Related

Nested query in Strapi GraphQL

I have a document structured as follows, more or less:
post {
_id
title
isPublished
}
user {
_id
username
name
[posts]
}
I know I can query fields like postConnection and userConnection with the aggregate subfield in order to query a count of all objects. But how do I get the total count of all posts by a given user?
I was able to come up with this:
{
postsConnection(where: {isPublished: true}){
groupBy{
author{
key
connection{
aggregate{
count
}
}
}
}
}
}
But this returns (expectedly) something like this:
{
"data": {
"postsConnection": {
"groupBy": {
"author": [
{
"key": "5c9136976238de2cc029b5d3",
"connection": {
"aggregate": {
"count": 5
}
}
},
{
"key": "5c99d5d5fcf70010b75c07d5",
"connection": {
"aggregate": {
"count": 3
}
}
}
]
}
}
}
}
As you can see, it returns post counts for all authors in an array. What I need is to be able to return the count for only one specific user and not by _id (which is what the key field seems to map to) but by another unique field I have in the users collection, i.e. username.
Is that possible?
Need to pass in a parameter to either the query or the field to return specific data

GraphQL: Explore API without a wildcard (*)?

I am new to GraphQL and I wonder how I can explore an API without a possible wildcard (*) (https://github.com/graphql/graphql-spec/issues/127).
I am currently setting up a headless Craft CMS with GraphQL and I don't really know how my data is nested.
Event with the REST API I have no chance of just getting all the data, because I have to setup all the endpoints and therefore I have to know all field names as well.
So how could I easily explore my CraftCMS data structure?
Thanks for any hints on this.
Cheers
merc
------ Edit -------
If I use #simonpedro s suggestion:
{
__schema {
types {
name
kind
fields {
name
}
}
}
}
I can see a lot of types (?)/fields (?)...
For example I see:
{
"name": "FlexibleContentTeaser",
"kind": "OBJECT",
"fields": [
{
"name": "id"
},
{
"name": "enabled"
},
{
"name": "teaserTitle"
},
{
"name": "text"
},
{
"name": "teaserLink"
},
{
"name": "teaserLinkConnection"
}
]
But now I would like to know how a teaserLink ist structured.
I somehow found out that the teaserLink (it is a field with the type Entries, where I can link to another page) has the properties url & title.
But how would I set up query to explore the properties available within teaserLink?
I tried all sorts of queries, but I am always confrontend with messages like this:
I would be really glad if somebody could give me another pointer how I can find out which properties I can actually query...
Thank you
As far as I'm concerned currently there is no graphql implementation with that capability. However, if what you want to do is to explore the "data structure", i.e, the schema, you should use schema instrospection, which was thought for that (explore the graphql schema). For example, a simple graphql instrospection query would be like this:
{
__schema {
types {
name
kind
fields {
name
}
}
}
}
References:
- https://graphql.org/learn/introspection/
UPDATE for edit:
What you want to do I think is the following:
Make a query like this
{
__schema {
types {
name
kind
fields {
name
type {
fields {
name
}
}
}
}
}
}
And then find the wished type field to grab more information (the fields) from it. Something like this (I don't know if this works, just an idea):
const typeFlexibleContentTeaser = data.__schema.types.find(t => t === "FlexibleContentTeaser")
const teaserLinkField = typeFlexibleContentTeaser.fields.find(f => f.name === "teaserLink")
const teaserLinkField = teaserLinkField.type.fields;
i.e, you have to transverse recursively through the type field.

is there a way to group queries in graphQL?

I'm trying to group graphQL queries to have a more organized response.
I want to make a query for allEmployees and get back something in the following format
GraphQL Query
{
Employees:allEmployees{
id
firstName
lastName
}
}
Response
{
"data": {
"Employees": [
"new":[
{
"id": "1",
"firstName": "James",
"lastName": "Test"
},
{
"id": "3",
"firstName": "Charles",
"lastName": "Tes"
}
],
"updated":[
{
"id": "4",
"lastName": "Test"
},
],
"deleted":[
{
"id": "1",
},
],
}
}
}
I've looked into a few options to get named sub-request( like new, updated and deleted) via aliases on fragments but that doesn't seem to be a thing. I've looked at unions, but that doesn't seem to be what I'm looking for.
Ideally I would love to query graphql like...
{
Employees:{
new: allEmployees(status:"new"){
id
firstName
lastName
}
updated: allEmployees(status:"updated"){
id
firstName
lastName
}
deleted: allEmployees(status:"deleted"){
id
}
}
but I don't think it is possible to pass a nested query like this.
Is there anyway to do something like this? I'm using graphql with ruby via the graphql-ruby gem.
please let me know if anyone needs more information?
Thanks
Edit
To clarify. We have multiple entities that will follow the new, updated, deleted pattern. Looking to try and get a response where the results are nested inside a parent name/alias (Employees, Users)
{
"data": {
"Employees": [
"new":[...],
"updated":[...],
"deleted":[...],
],
"Users": [
"new":[...],
"updated":[...],
"deleted":[...],
],
...
}
That is why we would want to nest
GraphQL definitely supports nested queries and multiple top-level queries, and graphql-ruby supports these just fine.
If your GraphQL schema looks like:
type Employee {
id: ID!
firstName: String
lastName: String
}
enum Status { NEW, UPDATED, DELETED }
type Query {
allEmployees(status: Status): [Employee!]!
}
then you could write a query
fragment EmployeeData on Employee { id firstName lastName }
query Everyone {
new: allEmployees(status: NEW) { ... EmployeeData }
updated: allEmployees(status: UPDATED) { ... EmployeeData }
deleted: allEmployees(status: DELETED) { ... EmployeeData }
}
That wouldn't have quite the specific form you're looking for – there aren't good ways to add or remove arbitrary levels in your query, like adding an "Employees" label or removing layers from React-style connection records – but it can retrieve the data you're looking for.

GraphQL Move a child property into parent

I'm looking into GraphQL and got to a question I'm not even sure how to look for in the docs. Probably this isn't even supposed to work, but I'll ask anyway.
I have this query:
query {
organization(login: "facebook") {
repositories(first: 5) {
items: edges {
repo: node {
name
owner {
login
}
}
}
}
}
}
Now, in the response I would like a way to place the login next to name, instead of nested in owner login.
So in the response instead of:
{
...
"name": "react-native",
"owner": {
"login": "facebook"
}
}
I would like to have:
{
...
"name": "react-native",
"ownerName": "facebook"
}
Thank you.
From the specification this is not possible. The response has to be shaped in the way the object types are shaped. There is a project called GraphQL Lodash that gives you a new directive to modify the results. It can be helpful here but it is rather experimental and IMO very undogmatic.

How to return object type with union query results in GraphQL?

I'm building a GraphQL API. When returning a union / interface type field, is it possible to have the server tell me the object type? i.e. something like this
{
search(text: "an") {
... on Human {
__type
name
height
}
... on Droid {
__type
name
primaryFunction
}
... on Starship {
name
length
}
}
}
// or even better
{
search(text: "an") {
__type // <--- even though it's a Union query, everything has a type right? :/
... on Human {
name
height
}
... on Droid {
name
primaryFunction
}
... on Starship {
name
length
}
}
}
which would return
{
"data": {
"search": [
{
"__type": "Human",
"name": "Han Solo",
"height": 1.8
},
{
"__type": "Human",
"name": "Leia Organa",
"height": 1.5
},
{
"name": "TIE Advanced x1",
"length": 9.2
}
]
}
}
Obviously, I could manually add this functionality by adding "type" fields to objects as needed, but I imagine something like this is already built into GraphQL? Seeing as all of the objects already have names. Basically I'm trying to access introspection information as part of a normal query.
This is possible using the special meta field __typename, which is available on all Graphql objects and returns the object's Graphql type name. See http://graphql.org/learn/queries/#meta-fields for more info.
PS: it looks like __typename is the only meta field that can be called outside of an introspection query.
Used like:
{
search(text: "an") {
__typename
... on Human {
name
}
... on Droid {
name
}
... on Starship {
name
}
}
}

Resources