Clients: Making mutations and queries easier to construct

As @Rahul-Sagore plans to use the Go client for Gru, I think it would be worth the effort to make it easier to use.

Right now, the Go client just sends a string similar to the HTTP client.

Mutations

  • The ideal thing to do would be that the Client can send a slice of NQuads for both Set and Delete operations. The validation for NQuads can be done at client side. Though this would require some duplication of code on the server and the client regarding moving the lang to the predicate and the logic that validates RDF. https://github.com/dgraph-io/dgraph/blob/master/rdf/parse.go#L190.

  • Another thing that we could do is that we can provide helper functions to easily add RDF’s but what is sent to the server are still strings for Set and Delete. This would avoid code duplication and reuse between HTTP Client and the language clients.

Queries

  • Here too the options are whether to provide helper functions to make it easier to construct the string or have all the logic for creating a GraphQuery(which is a bit too much) and send that to the server.

I think for now if we can just make it easier to construct the query and mutation(set and delete) string that would be good, though the server still needs to do the string parsing which is a bit inefficient. Advice @minions?

1 Like

The main thing we can save here is to avoid creating RDF NQuad strings. Instead, we put them in PB format, setting values for the right fields to create rdf.NQuad struct.

This already saves a bunch of RDF parse runtime logic. We don’t have to go overboard in doing all the validation checks at the client side. We can just do some basic ones, like a subject, a predicate and an object is set. The server can still run all the other checks and reject a mutation. And then we can reuse all the logic to convert rdf.NQuad to x.DirectedEdge.

You’re right that GraphQuery parsing is a bit more complex. So, for that, maybe we can just help create the string query. Though, if while implementing this, you find some ways to aid the gql parser, that’d be great. But, only as long as most of our validation logic and conversion to SubGraph can work.

1 Like

@pawan I’d recommend if you can document the client method APIs and functionalities you are looking to provide for the Go Client. This document can be used as a reference by the other clients.

Having consistent client interfaces across languages (except may be REST calls) is useful.

2 Likes

I think once we have a decent API in Go, we can update the wiki page:
https://wiki.dgraph.io/Clients

2 Likes

I have a few questions/doubts regarding queries:

  1. There is a requirement of modifying the question, for this feature, we have to show all the available question to the admin, like a pagination thing ( or Searching).
  2. Is there a query to fetch all question/tags, something like “Select * from”. (Can not see this happening since this is not a table based database, but still wondering)
  3. I have seen example of dgraph query from <alice-in-wonderland> example. Here we know the entity name so we can query it, but after storing question into database we don’t know the entity name. So how can we get the data? Queries works when we know name.
  4. While creating quiz, questions will be randomly assigned or admin can select from UI?
  5. When we work on some dummy data, where it gets stored? Is there a query to clear all data?

I’ll let @core-devs help you with questions related to Dgraph (lot on my plate). @minions?

1 Like

Hey Rahul. I will try to answer your doubts here.

The root query in Dgraph has to have a xid/uid. I suppose if each question has an edge to the quiz it belongs. You could query like so

query {
  quiz(_xid_:  1) {
    question(offset: 10; first: 5) {
      question.tag
      markdown
      score
      option
    }
  }
}

Also note that for pagination, we support First, Offset and AfterN https://wiki.dgraph.io/Queries_and_Mutations.

Like I said above you need to provide the uid/xid for the root node. And then you can ask for all children(question/tags) for that.

So @jchiu is working on string matching/filtering. After that you’d be able to do queries like.

query {
  quiz(_xid_:  1) {
    question(markdown: "algo") {
      question.tag
      markdown
      score
      option
    }
  }
}

which would give you all questions where markdown has algo in them. Is that what you meant? What’s the use case you have in mind?

For the MVP, lets just keep it so that all the questions associated with a particular quiz are shown randomly to the candidate. Ability to select questions to show would be a good to have though not necessary.

So dgraph binary takes three options, i.e. the directories for storing mutations, uids and postings. If you don’t give those options then those directories(m, u and p) are created in the path that you are running Dgraph server from. One way is to clear the data is to run the delete(https://wiki.dgraph.io/Queries_and_Mutations#Delete) mutation. Other option is to delete those directories(this would clear all the data) and start the server again.

No. You don’t need that functionality here. I think this is the same confusion as @kostub had yesterday. @Rahul-Sagore: If you have the quiz id, then you can retrieve all the questions from them, and all the tags attached to the questions, like so:

{
  qt(_xid_: quizid) {
    quiz.question {
      question.tag
    }
  }
}

In fact, keep the quiz id in xids, so they’re easier to remember. Note that the alice-in-wonderland example, those are xids, not names. You’d like xids because they’re easier to remember, they’re english ids attached to complicated uint64 ids. So, in few cases, like the quiz ids, you can use xids instead of referring them directly via uids. But, for everything else, use uids directly.

Actually, this would be a lot easier to do if we create a topic in wiki.dgraph.io, which jots down the schema and all the queries you need. Then we can all update the schema and the queries before you begin implementation. In fact, do that as the next step, @Rahul-Sagore.

Note: If you need string matching for Gru, you’re doing something wrong.

2 Likes

@Pawan, I know that, if question has an edge to the quiz, we can get the question using quiz’s xid, same goes for tags.
The query that you have written for fetching question is fine, but you have explicitly mentioned external id (_xid_: 1). So if we have quiz with xid 1, how will we assign questions to this xid? I am thinking about the problem from UI perspective also, there will be UI for creating quiz, where admin can add quiz name, duration and associate questions, right? (let me know if this is the case, else how will the quiz(xid: 1) will be generated with questions associated to it?), Like there will be 100 of question but we will assign only 10-20 to the quiz. This is the use case I am thinking.

@mrjn - If I have quiz_id I can fetch every desired data, that is great. I’ll create the topic about schema and the things that we need to implement.

I am not looking for string searching. Probably I am thinking about the Gru in way that is too generalised/customisable. My approach of admin flow is like create/modify questions, tags, quiz independently, then associate/remove relationship through UI: like associate tags to question, associate questions to the quiz (same for the removing). In pawan’s query, what I got that quiz already has questions associated.

You can generate an edge, like so: <quizid> <quiz.question> <question-id> ., if you already know question id.

Actually, if you do create that wiki page, it would become a lot easier to explain all this. Because currently we have this information spread across multiple topics, and some of the questions here are already discussed in the initial write up I had done about the schema and the queries it allows you to run.

That sounds like what I had in mind as well.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.