Ioredis: I wanna talk about an idea for command generator + GraphQL. (Join-Monster like)

Created on 11 Sep 2017  路  7Comments  路  Source: luin/ioredis

First I declare this link as a reference "Logic" https://github.com/stems/join-monster

This is a specific idea for anyone trying to use Redis with GraphQL. (you really can use it, the problem is the complexity with time and I'm trying to solve with this idea below)

Gradually I will analyze how IORedis "Core" works and then see if I spend some time modifying the Join-monster so that this idea may work. Or do something else with Redis Graph - Let's get down to business.

The idea is to use the Join-Monster concept. Join-Monster is a query planning and data fetching for SQL. With it you can generate query based on your GraphQL schema. Its reads the request and transforms the GraphQL request into a SQL. Then you can send SQL by Knex, Sequelize or any other.

The big thing is that it only sends what was requested in a single batch. Avoiding over-fetching.

Hence, what I imagined was that: take this concept from Join-monster. And try to implement it in two ways. Or by using it to generate a requested through IORedis to Redis Graph or use it to generate general Redis commands for the IORedis.

What do you think? I think such a feature would be interesting to generate clean code on resolvers. And it makes it more dynamic.

Example:

// Join monster Reads Schema

input User {
  id: Int!
   Name: String!
 Password: String!
  Phone: String!
  email: String
}

//The user request this Query

mutation {
  createUser(input: {
              id:  999,
    Name: "Michel",
    Password: "12345678",
     Phone: "9999999999",
    email: "[email protected]",
  })
}

//Join-Monster does this graph

let MyJoinMonsterData = 'GRAPH.CREATENODE',  'User', 'id', '999', 'Name', 'Michel', 'Password', '12345678', 'Phone', '9999999999', 'email', '[email protected]'
or
let MyJoinMonsterData = 'hmset' , 'User:id999', 'Name', 'Michel', 'Password', '12345678', 'Phone', '9999999999', 'email', '[email protected]' 

//pack and send In Resolver:
redis.call(MyJoinMonsterData);

discussion wontfix

All 7 comments

Sounds interesting! I haven't used join-monster before, but I'd like to merge a pull request for the feature.

I know that Join-monster maps all Schema and hence it uses a dialect according to the type of SQL dialect. It has MariaDB, MySQL, Oracle, PG, Sqlite3.

I'll need to set up a testing environment to test this hypothesis. Add another dialect to Join-Monster by mapping GraphQL to the Redis commands.

I know that redis.call () is perfect for this situation. But, one detail, is it possible to use "Multi" within "Redis.call"? If not, would it be possible to implement a "Redis.Raw ()"?

Cheers

Before starting something, I did some mental rehearsals in this sketch, taking/using my little knowledge on the Join-Monster tool.

The query simplified

{
  user(id: 999) {
    id
    email
    fullName
    favNums 
    posts {
      title
      body
      comments {
        body
      }
    }
  }
}

I think it would be a bit more complex to develop this feature. It's not impossible, but it's rather complicated (Comparing how Join-Monster produces its results.). Just analyzing this simple Query with many-to-many using simple Redis commands. It got a bit complicated, I believe. Perhaps in Graph mode (using the module) it is easier and more dynamic.

So. Asking for User + Fav numbers + Posts from that user and comments inside the posts from others users

{
  user(id: 999) {   # this whole Query is resolved with  .MULTI command
    id         = HGET user:id-999 id
    email      = HGET user:id-999 email
    fullName   = HGET user:id-999 fullName
    favNums    = GET  user:id-999:favNums Nums
        # This part above could  be generated with the command bellow 
        # if requested all fields but still needs .MULTI for posts and 
        # favNums because they are in different fields/Keys.
           // HGETALL user:id-999
                       return = {
                                "id": "id-999",
                                "email": "[email protected]",
                                "fullName": "Michel Torrado",
                              }
    posts {    = HGET user:id-999:posts 
      #Need to solve a many_to_many problem here
      #I think it would have to create a loop with SCAN inside the 
      #Join-monster and then it will try to make a new call for each 
      #post on a new MULTI command. This is just an abstract sketch.
      title
      body
      comments { = HGET user:id-999:posts:${post_id:X}:comments
        body
      }
    }
  }
}

Thanks for the details. It's indeed a little complex to map a graph request to a Redis structure. The most important part is, there's not a standard on how to store relations in Redis. For instance, m-m can be implemented in Redis using set/string or zset, so it's impossible to decide which command should be used to resolve the graph query.

Using the graph module may be a way to solve the problem. However, I noticed there's a module/standard about implementing the relations with Redis: https://github.com/soveran/ohm. I'm not sure but it may be easier if we build the query resolver on the top of it.

A question is why MULTI is needed here. Transaction in Redis is a simple layer to make sure that the commands are executed sequentially. However, if any commands fail, other commands will be executed normally.

The need with .multi is that Join-Monster could in one "Redis batch" request all Query needs/requests. You see? instead of send lots of little request to Redis. Maybe it's my placebo thinking that way.

And it can have a "dialect" for each Redis relations solution or even modules. If someone uses RedisGraph it would be enough to require the dialect for this module. Or even a dialect for each style, for example a dialect for those using Ohm.

A pipeline would be enough in this case:

const redis = new Redis()
const ret = await redis.pipeline().get('foo').hget('hash', 'key').exec()

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 7 days if no further activity occurs, but feel free to re-open a closed issue if needed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

saschaishikawa picture saschaishikawa  路  4Comments

AdriVanHoudt picture AdriVanHoudt  路  4Comments

kimmobrunfeldt picture kimmobrunfeldt  路  5Comments

No1Jie picture No1Jie  路  5Comments

jamesdixon picture jamesdixon  路  4Comments