Skip to content

Updating graph using struct with uid makes edges disappear #130

@gluonfield

Description

@gluonfield

I am creating a node by serializing struct and feeding to dgraph. Then I would like to update a value node of the graph by building go struct again and providing it with node UID. Even though update is successful, some edges have disappeared.

Dgo go documentation says While setting an object if a struct has a Uid then its properties in the graph are updated else a new node is created.

I am providing code which:

  1. Creates User with FavQuote, FavCar and Contact details. (All good)
  2. Knowing UID of User I update FavQuote. (FavQuote updated, FavCar remains, however edge to Contact details disappeared)

I had no problems with such node updates before, however this time the struct is more deeply nested.

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/dgraph-io/dgo/v200"
	"github.com/dgraph-io/dgo/v200/protos/api"
	"google.golang.org/grpc"
)

// User -
type User struct {
	UID            string             `json:"uid,omitempty"`
	DType          []string           `json:"dgraph.type,omitempty"`
	FavQuote       string             `json:"quote,omitempty"`
	FavCar         string             `json:"car,omitempty"`
	ContactDetails UserContactDetails `json:"user.contact_details,omitempty"`
}

// UserContactDetails -
type UserContactDetails struct {
	UID    string      `json:"uid,omitempty"`
	DType  []string    `json:"dgraph.type,omitempty"`
	Mobile PhoneNumber `json:"contact_details.mobile,omitempty"`
}

// PhoneNumber -
type PhoneNumber struct {
	UID            string   `json:"uid,omitempty"`
	DType          []string `json:"dgraph.type,omitempty"`
	CountryCode    string   `json:"phone.country_code,omitempty"`
	NationalNumber string   `json:"phone.national_number,omitempty"`
}

func main() {
	conn, err := grpc.Dial("localhost:9080", grpc.WithInsecure())
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	dg := dgo.NewDgraphClient(api.NewDgraphClient(conn))

	u := User{
		UID:      "_:newUser",
		DType:    []string{"User"},
		FavQuote: "Moon",
		FavCar:   "Lambo",
		ContactDetails: UserContactDetails{
			DType: []string{"ContactDetails"},
			Mobile: PhoneNumber{
				DType:          []string{"PhoneNumber"},
				CountryCode:    "+33",
				NationalNumber: "98766543",
			},
		},
	}

	op := &api.Operation{}
	op.Schema = `
		<phone.country_code>: string @index(exact) .
		<phone.national_number>: string @index(exact) .
		<quote>: string .
		<car>: string .

		type User {
			quote
			car
			user.contact_details: ContactDetails
		}

		type ContactDetails {
			contact_details.mobile: PhoneNumber
		}

		type PhoneNumber {
			phone.country_code
			phone.national_number
		}
	`

	ctx := context.Background()
	if err := dg.Alter(ctx, op); err != nil {
		log.Fatal(err)
	}

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

	ub, err := json.Marshal(u)
	if err != nil {
		log.Fatal(err)
	}

	mu.SetJson = ub
	response, err := dg.NewTxn().Mutate(ctx, mu)
	if err != nil {
		log.Fatal(err)
	}

	uid := response.Uids["newUser"]
	fmt.Println("UID: " + uid)

	// User correctly created with all details and can be verified in Ratel

	// MODIFYING USER
	u = User{
		UID:      uid,
		FavQuote: "Jupiter",
	}

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

	ub, err = json.Marshal(u)
	if err != nil {
		log.Fatal(err)
	}

	mu.SetJson = ub
	_, err = dg.NewTxn().Mutate(ctx, mu)
	if err != nil {
		log.Fatal(err)
	}

	// User updated `FavQuote`. "FavCar" remains however contact details edge from user have dissapeared !?
}

To check data in Ratel I use

{
  u(func: uid(0x2a85)) {
    uid
    quote
    car
    user.contact_details {
      contact_details.mobile {
        phone.country_code
        phone.national_number
      }
    }
  }
}

Graph before modifying user

      {
        "uid": "0x2a85",
        "quote": "Moon",
        "car": "Lambo",
        "user.contact_details": {
          "contact_details.mobile": {
            "phone.country_code": "+33",
            "phone.national_number": "98766543"
          }
        }
      }

Graph after modifying user

      {
        "uid": "0x2a85",
        "quote": "Jupiter",
        "car": "Lambo"
      }

Which no longer has contact details 🤷‍♂️

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions