Rpc error: code = Unknown desc = Input for predicate author of type uid is scalar

By your description you do an inverse relationship. So it gets confused. The right thing was for you to plan a more organized hierarchical order. But I’ll try to redo what I did up there:

PS. The variable block does not appear in the response.

1 Like

Thanks, this works (:

It does however return everything created by the user, not just boards but also threads and comments. I guess this is what you meant by planning a more organized hierarchical order.

Although I’m not sure what I could have done differently… even if the user: uid @reverse . was changed to user: uid . then it wouldn’t work.

Maybe the right thing to do would be to update the user when creating a new board, so that the new board uid can be attached to the user?

Hierarchical organization would solve some logic usage.
So from parent to child. And just use “reverse” when you’re querying from child to parent. Only if really needed.

Before anything, tell me if you gonna user JSON always or y’ll use RDF in some part.

ps: No matter if you use Reverse or not in Schema, what matters is the format of your mutation. It has to preserve the hierarchy. Reverse is good for other uses. Like querying from child to parent.

ps2: What I’m saying here are not “rules”, just opinions. For who read this and think I’m giving some kind of statement. The rule is, you can do the way you want, but you must know Dgraph Lang for real to be free.

In json the organization would look like this:

User => Boards => other board child

{
    "_User": " ", # type as user
    "username": "John88",
    "boards":  {
        "_Board": " ", # type as Board
        "title": "My Title",
        "description": "My Description"
      }
}

The way you do is like this:

{
   "_Board": " ", # type as Board
   "title": "My Title",
   "description": "My Description"
    "User":  {
    "_User": " ", # type as user
    "username": "John88",
        }
}

But continuing the hierarchy, from the user to the childs. Let’s say you’ve already created a user. And now you are creating a Board and you need to “sign” an existing user and you have his UID.

{
   "uid": "0x123", # signs to John88 UID as his parent
# That way you are writing under the User node and at the same time creating a new node.
   "boards": {
         "uid": "_:newBoard" ", # Using a blank node
         "_Board": " ",  # type as Board
         "title": "My Title",
         "description" : "My Description"
   }
}

I do not understand why this happens (But now I imagine what it is). I did not request it on my query, it does not make sense. Unless you have inserted the predicates or used “expand (_all_)”. You should only use and expand predicates that you will actually use.

You can use “type” to filter those nodes Get started with Dgraph
In this case the query must be like

{
  var(func: uid(0x1)) {
    userBoards as board {
      uid
    }
  }
  theUserBoards(func: uid(userBoards) ) @filter(has(_Board)) {
    uid
    title
    description
  }
  theUserThreads(func: uid(userBoards) ) @filter(has(_thread)) {
    uid
    title
    description
  }
}

So, all your nodes must have a unique “type”
like has(_thread) or has(_comment)

Cheers

1 Like

Thanks a lot, it’s really useful info (:

I would personally prefer to just use json for inserting data if that’s possible. I guess the problem is when I create a new user, board, thread, comment, etc. then I don’t specify who the uid belongs to in the json. I only specify it when I for instance want to say the board belongs to a given user.

Like when I create a new user then I just write {"username":"My Username"} and let dgraph automatically assign a uid, but I also think this feels wrong because it doesn’t specify that this user belongs to the user: uid . schema type. It sounds like when I add the user I’m supposed to write {"user":"_","username":"My Username"} or something like that?


One problem I’m not sure how your organization would address is this:

user → can have many boards, can have many threads, can have many comments

board → can have one user (creator of board), can have many threads

thread → belongs to a board, can have one user (creator of thread), can have many comments

comment → belongs to a thread, can have one user (creator of comment)

Where I’d like to quickly look up:

  • all boards (e.g. 10 newest boards)
  • all threads (e.g. 10 newest threads no matter what board)
  • all comments (e.g. 10 newest comments no matter what thread)
  • all threads belonging to a board
  • all comments belonging to a thread
  • all boards belonging to a user
  • all threads belonging to a user
  • all comments belonging to a user

That’s why I did it the other way because maybe Board (belong to User A) > Thread (belongs to User B) > Comment (belongs to User C)… but I’d really love to know how you feel these 4 uid types should be organized

You do not need to report Blank Nodes using JSON (But you can). You can use the UID predicate in JSON only for existing UIDs. Never define the UID yourself, Dgraph has to create it first.

it’s perfectly right

So this hierarchy seems fair to me:
user -> board -> thread -> comment

You can use pagination or even filter by datetime
In this case you will search for the “kind / type” you give to the node and using “has (something)” you will “filter” those nodes.

Same thing as before
In this case you will search for the “kind / type” you give to the node and using “has (something)” you will “filter” those nodes.

In this case you know the UID of the Board. Then you will request in the query only the threads field and whatever you want below it.

And this is repeated in all cases.

The order influences nothing but the mind of the one who is building the DB structure. So I reinforce you create in a user order for objects. And not objects for users, get it? This makes it more human friendly.

So if I understand correctly, if I first create a user and then create a board (where I make a reference to the user uid, e.g. {"title":"My board","description":"My Description","user":{"uid":"0x01"}}), then it is not necessary to update the user in order to make a reference back to the board?

But instead, what I should do when creating a user is to make an additional field, e.g. {"_user":"-", “username”:“My Username”}, in order to be able to make the type filters you showed before?

This is diferent (for u can work, cuz is the solution for your very first question). Cus you’re saing that the User is a Child of the board. Basicly you asking me the same thing you’re already doing before. There’s no relation to what I’m saing (about hierarchy). What I said was to put the Board as a User Child.

If you wanna do the way you’re doing, you need to use ~reverse approach in your queries. But need also to use kinds or some predicate “type” approach. To separate the wheat from the chaff.

Yeah, but you can use anything as a mention to you this link Get started with Dgraph

You have to use some pattern to be able to filter if all your nodes are similar

I recommend you to use a pattern like “_user” not just a underscore. But if you don’t wanna use “Kinds” like that you can create a predicate indexed by Hash (But the kind by predicate is more recommended). And that’s it. You will use:

author @filter(eq(myNodeType, "User")) {
      name@en
      predicate1
      predicate2
    }

In that last case user should be like that:

{"myNodeType":"User", “username”:“My Username”}

And Schema: myNodeType: string @index(hash) .

Just to clarify. All nodes like “board, thread, comment” need to have a “kind/type” to be able to filter. And you need to put a extra predicate to inform the author of that data/node.

Thanks a lot, that makes a lot of sense.

About this part:

So what you’re suggesting is that:

  1. create user: {"user":"User", “username”:“My Username”} (e.g. return uid 0x01)
  2. create board: {"board":"Board", "title":"My board","description":"My Description"} (e.g. return uid 0x02)
  3. update user: {"uid":"0x01", "user":"User", “username”:“My Username”, "board":{"uid":"0x02"}

This second I believe you can do like this:

So you do not have to take the third step.

{
"uid":"0x01",
 "boards": {  # The relation with the user need to be plural, cuz
# you gonna have many boads.
   "board":"Board", # this is your type? don't need this if not
   "myNodeType":"User" Example of a predicate to be filterable;
   "_Board":"Board" Example of a better filterable approach;
   "title":"My board",
   "description":"My Description"
}

e.g. return uid 0x02 and signed to 0x01 via boards predicate.

1 Like

Extra:

let’s say you gonna add a comment to a thread in that Board.

{
"uid":"0x06", # uid from the thread
 "comments": {  # The relation with the user need to be plural, cuz
# you gonna have many boads.
   "_Comment":" " Example of a better filterable approach;
   "body":" This is a Comment",
   "author": { 
# this relation is reversed, it's ok cus a Comment is
# a child of the thread, not the user.
     "uid": "0x14" # Existing user
   }
}
1 Like

Very interesting… just tested it and it works, really appreciate it <3

1 Like

I did a little mistake in the Comment example. Just fixed it.

was this:

Note A common mistake is to attempt to use {“uid”:“0x123”,“link”:“0x456”}. This will result in an error. Dgraph interprets this JSON object as setting the link predicate to the string"0x456", which is usually not intended.