Relation between user and post with UID using dgraph client

I have been creating post data which is assigned to user, for the given reason, I have following struct:-

type Post struct {
	UID              string
...
	Body             string
	Title            string
...
	OwnerUserID      string
...
}

type Users struct {
	UID            string
	Name           string
...
	Email          string
...
}

And I am using dgraph client - https://github.com/dgraph-io/dgo with the below code to create post :-

cdate := time.Now()
		crx := ctx.Request().Context()

		p := Post{
			CreationDate: &cdate,
...
			Body:         ask.Content,
			Title:        ask.Title,
			OwnerUserID:  "0x1",
...
		}

		mu := &api.Mutation{
			CommitNow: true,
		}

As you can see in OwnerUserID, I am providing directly uid of user. This goes all good, but problem comes, when I print post data with user information.

{
  me(func: anyofterms(Tags, "life")) {
    uid
    Title
    Tags
    OwnerUserID {
      uid
      Name
    }
  }
}

It gives me data like below :-

"data": {
    "me": [
      {
        "uid": "0x2",
        "Title": "What should I do to improve my memory?",
        "Tags": [
          " story life problem memory health"
        ],
        "OwnerUserID": "0x1"
      }
    ]
  },

It does not know about the user associated with the ID. How can I tell my code at above that this post belongs to user whose uid is 0x1.

Thanks

When I use User struct reference in Post struct for OwnerUserID, It creates another user.

type Post struct {
	uid              string
...
	Body             string
	Title            string
...
	OwnerUserID      Users
...
}

As you can see, I have given reference to Users struct in OwnerUserID and while inserting like below:-

p := Post{
...
			Body:         ask.Content,
			Title:        ask.Title,
			OwnerUserID: Users{
				uid: "0x1",
			},
...
		}

Instead of assigning user id of uid “0x1” - It creates another user of uid “0x3”


"data": {
    "me": [
      {
        "uid": "0x2",
        "Title": "What should I do to improve my memory?",
        "Tags": " story life problem memory health",
        "OwnerUserID": [
          {
            "uid": "0x3",
            "Name": ""
          }
        ]
      }
    ]
  },

You should not do that for that case.

Users - is not part of Dgraph’s Schema. For you is just a representation of the type of node for users (I believe so, I don’t know Go). You could only do this in “OwnerUserID” as in your first example.

OwnerUserID is the relationship predicate (it’s your “belongs”) that you have between two or more nodes. So is just what you should use to relate the user and the Post or comments and etc.

If you do anything out of the ordinary, sure Dgraph will create empty Nodes. It is not even creating “Users” because this certainly does not exist in Schema within the Dgraph. Only in your application.

The idea is if you are creating a new post and informing a new “Users” the Client will create a new node for each. The right thing is for you to relate to an existing User node. As in the first example. In the second example you are “forcing” (I believe) the creation of a new post and a new user.

Repeating: Users to be unique, can only have relations via predicates. Every time you use a structure to create multiple Nodes. Will create a new user and post nodes.

For me seems not to be a relation through predicate.

You should treat each node separately. I’ve never used the Go client, but I assume it’s the same as the others.

I agree, it is creating new node, but how can one really establish a relation using dgraph client.

With query browser, I could just create

_:userUID <post> _:postUID

But how this can be done using dgraph client - https://github.com/dgraph-io/dgo

I think you first example can do that for existing nodes (Post).

OwnerUserID: "0x1",

If you just want to relate a post already created with a user already created as you did now in the last comment. I don’t know how to do it, would that? Surely you should have something in the client documentation https://godoc.org/github.com/dgraph-io/dgo

The third you can use so

p := Post{
			CreationDate: &cdate,
			PostType:     "question",
			Score:        0,
			ViewCount:    0,
			Body:         ask.Content,
			Title:        ask.Title,
			Users{
					Name:           "Jordan Williams"
			        LastName:       "Williams"
			        FirstName:      "Jordan "
			        Email:          "Jordan@gmail.com"
			        NickName:       "Jordan79"
			        Birth:          "7/5/1979"

			},
			Tags: hashTag,
		}

If you feel comfortable with RDF I think you should use Dgraph directly

See this test example using RDF.

Presuming go client is similar to java client, i think if you are trying to serialize go objects, then the uid values in the the go objects should begin with the, “_:” …

See https://docs.dgraph.io/mutations/#json-mutation-format

In this way, dgraph knows tu associate your post with the user.

Hope that helps.

S

But in his case it seems to me that he wants to link a new Post to an existing user. (this would be the logic of a running application). So in this case it needs to use UIDs(cuz, user already exists). If it uses Blank_Nodes (_: node) it will create a new node in the same way.

That will also create new user and it will not associate post with the existing user.

Here new user will be created with “Jordan Williams” and other data specified below.

The second you can use so

p := Post{
CreationDate: &cdate,
Body: ask.Content,
Title: ask.Title,
Users{
Name: “Jordan Williams”
NickName: “Jordan79”
Birth: “7/5/1979”

  	},
  }

I gave you three options. Like I do not know exactly what you want. So I wrote of three possibilities. Of course this third will create a new Post and a new user. However, you will be creating a full user this time and not an empty Node.

If you explain in more detail what you want, in the sense “Business Logic” would help. For me, your first choice up there perfectly matches what I think you want to do.

	p := Post{
		CreationDate: &cdate,
		PostType:     "question",
		Score:        0,
		ViewCount:    0,
		Body:         ask.Content,
		Title:        ask.Title,
		OwnerUserID:  "0x1",
		Tags:         hashTag,
	}

There is already few users who exists in database. So, Now Post is being created and these posts needs to be associated with existing user.

that is clearly mentioned in first post and title of this post.

Associating post with existing user.

The above you believe the code (dgraph?) does not know who owns the post. But you may not have noticed, but in “OwnerUserID”: “0x1” says just that.

And The “uid”: “0x2” is the UID of the post itself.

if you would have read the whole post carefully, you can see that I did mention :-

As you can see in OwnerUserID, I am providing directly uid of user. This goes all good, but problem comes, when I print post data with user information.

{
  me(func: anyofterms(Tags, "life")) {
    uid
    Title
    Tags
    OwnerUserID {
      uid
      Name
    }
  }
}

It gives me data like below :-

"data": {
    "me": [
      {
        "uid": "0x2",
        "Title": "What should I do to improve my memory?",
        "Tags": [
          " story life problem memory health"
        ],
        "OwnerUserID": "0x1"
      }
    ]
  },

Where, I am trying to fetch the user name, but this is not providing user information, it is only providing below information as it is.

It’s perfectly correct, but it should be something on your Node “0x1”.

Check for this node indeed exist. If it has the data you are looking for. I find it impossible for you to do the right thing and Dgraph just return the UID and nothing more…

{
  me(func: uid(0x1)) {
   uid
   expand(_all_)
  }
}

Here is the data, it returns :-

data": {
    "me": [
      {
        "uid": "0x1",
        "CreationDate": "2018-05-12T15:59:28.213406+05:45",
        "Name": "Alice",
        "Email": "alice@mailinator.com",
        "NickName": "alice"
      }
    ]
  },

Can you share your schema?

I just noticed my OwnerUserID is of type “string” and changing it to “UID” is giving me an error -

“Could not alter schema: Schema change not allowed from scalar to uid or vice versa while there is data for pred: OwnerUserID”

So that was the problem. You need to drop you dgraph and start your schema correctly with UID. And if you prefer use @Reverse is good for future uses.

1 Like