RethinkDB Example App (via GraphQL)

I just wanted to share a new spike that I made this weekend. It’s running @arunoda 's wonderful GraphQL package and a standard version of RethinkDB running the rethinkdbdash driver.

Also after taking a day to learn with @arunoda 's Learn GraphQL course and some tinkering on my own making a blog API I was really surprised at how easy it is! It’s by far easier than writing your own REST API.

https://github.com/AdamBrodzinski/Meteor-RethinkDB-GraphQL


### Search for all posts and only send the id, title, content keys:

#


### Create a new post (instead of a Meteor method) ![|690x208](upload://7Q1nKahdQUBwpvZJ0uD5zCIr2Ck.png)
If you're curious about how the meat of it works, GraphQL creates types that create 'model' (although it's not really quite a model) that can be referenced when you say, this post has a `Comment` or fetch me all `Comment`s. It refers to a row in the database.

This is much like simple-schema and publish-composite:

Comment = new GraphQLObjectType({
  name: 'Comment',
  fields: () => ({
    id: {type: GraphQLString},
    text: {type: GraphQLString},
    // if author was embedded in the comment document you would just do this:
    // author: {type: ... },
    // but we'll demonstrate fetching from another table (or even db)
    author: {
      type: Author,
      // when something asks for the `comment.author` key, fetch this and use returned val as that key
      resolve(comment) {
        return r.table('comments').get(comment.author).run();
      }
    }
  })
})     
8 Likes

This is great.

BTW: kadira:graphql runs inside a fiber. So, you can use authorization stuff as well.

1 Like

Oh Snap! I was wondering exactly what the fibers were doing while looking at the source. I just assumed it was to make it be able to start up :laughing:

Is there a reason your demo uses a Promisify? I assumed that was just a hack to get it working. Could you just depend on fibers if you’re using Mongo?

For those not sure what i’m talking about you could do this and fibers still work :smile: :


    recentPost: {
      type: BlogPost,
      resolve() {
        docId = Things.insert({title: 'adam', content: 'a mongo blog'})
        doc = Things.findOne(docId)
        return doc;
      }
    },    

Yeah! We could do it.
When we are working on the demo, fiber support was not there.

This is possible.
BTW: I’m open to PR, if you just wanna remove all the promisify stuff :slight_smile:

1 Like

Nice, I most likely will tomorrow unless something unexpected pops up.

Also speaking of example apps and PRs, do you think separating the mutations and queries out makes things easier to read or more complex? I can’t decide myself… to me it seems simpler but I guess the file jumping can be an issue too.

1 Like

And checkout our graphql-utils too. With that, you can get which fields user as asked and do better field filtering.

1 Like

Is there a better way to do this? I was tinkering and came up with this to pass to mongo:

      resolve(root, args, info) {
        // create an object of fields for mongo to limit keys
        const keys = Object.keys(getFieldsFromInfo(info));
        const filterMap = keys.reduce((obj, key) => {
          obj[key] = true;
          return obj;
        }, {})

       return Collections.posts.findOne({}, {fields: filterMap});
      }  

What we did is a universal tool. Actually, it was not built with Mongo.
I agree we can do better.

May be this can be used in a much higher level API.

1 Like

Oh yea I think it’s just fine the way it is… better to have it universal than specific to Mongo. I just made a quick helper function to wrap it:

function createFilterFields(info) {
  return Object.keys(getFieldsFromInfo(info))
  .reduce((obj, key) => {
    obj[key] = true;
    return obj;
  }, {});
}

Then it becomes:

resolve(root, args, info) {
  const fields = createFilterFields(info);
  return Collections.posts.findOne({}, {fields});
}

Thanks again :thumbsup:

So uhhh, what part of Meteor are you actually using? :smile:

3 Likes

So basically everything except subscribe/publications which is great because i’ve always disliked that part about Meteor… the 20% use cases stole away any productivity the 80% originally bought me :smiley:

In a Blaze app you can take the response (JSON) and insert it into a local MiniMongo collection and the rest of the app is ignorant of how data is fetched. If you needed realtime though, you would need to re-fetch every N seconds and re-insert for the UI to auto update. (GraphQL doesn’t support realtime yet but soon)

3 Likes

you would need to re-fetch every N seconds and re-insert for the UI to auto update

What happens if the data needed by a component doesn’t change between two fetches ? Is everything still re-sent and re-rendered ? That would be rather inefficient :s
Genuine question, I don’t know how GraphQL handles that kind of things.

1 Like

Re-rendering won’t be an issue in React. It won’t re-render DOM.
This will be an issue if you are processing more than 10000 docs in the client.
If so, there are ways to deal with that too.

2 Likes

What happens if the data needed by a component doesn’t change between two fetches ? Is everything still re-sent and re-rendered ?

It depends on how MiniMongo handles new data… not sure if it will force a re-render. However, if it does force a re-render and it’s polling every say 30 seconds then it’s not that big of a deal as most UI will render in less than 16ms (to hit 60fps). If your UI is React then it won’t matter since the virtual dom would diff it.

GraphQL is more less like a Meteor method. However, Relay would have enough smarts to not re-render… but it’s fairly complicated. Luckily @arunoda wrote Lokka which is much simpler and uses Meteor internals.

2 Likes

quick question: how to do paging with GraphQL as my Meteor App uses paging?

One correction. Lokka does not use Meteor stuff. It’s on pure JS.
It’s for someone who doesn’t want to use Relay, but to use GraphQL.

1 Like

It’s the same way as you do with Meteor, pass some variables to the query to mentioning start and limit positions.

1 Like

Oh wow, I didn’t look close enough at that yet! :smile: I’m going to use this with my React Native app that’s already using flux and slowly sneak GraphQL into it :wink:

1 Like

See this: https://voice.kadira.io/using-graphql-inside-a-react-native-app-763ab54df28a

1 Like

A dumb question: does graphql diff the update on the server side and send the updated to client like mergebox does or it does something else?