Upsert not working golang


(Barum) #1

I am trying to use upsert but having issues. this is an example of my go code:


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

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

// If omitempty is not set, then edges with empty values (0 for int/float, "" for string, false
// for bool) would be created for values not specified explicitly.

type App struct {
	Uid     string `json:"uid,omitempty"`
	AppID   string `json:"apps.apps.app_id, omitempty"`
	AppDesc string `json:"apps.apps.app_desc, omitempty"`
}

func main() {
	conn, err := grpc.Dial("127.0.0.1:9080", grpc.WithInsecure())
	if err != nil {
		log.Fatal("While trying to dial gRPC")
	}
	defer conn.Close()

	dc := api.NewDgraphClient(conn)
	dg := dgo.NewDgraphClient(dc)

	//dob := time.Date(1980, 01, 01, 23, 0, 0, 0, time.UTC)
	// While setting an object if a struct has a Uid then its properties in the graph are updated
	// else a new node is created.
	// In the example below new nodes for Alice, Bob and Charlie and school are created (since they
	// dont have a Uid).
	p := App{
		AppID:   "APPID01",
		AppDesc: "this is app01",
	}

	op := &api.Operation{}
	op.Schema = `
		apps.apps.app_id: string @index(exact) @upsert .
		apps.apps.app_desc: string .

	`

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

	mu := &api.Mutation{
		CommitNow: true,
	}
	pb, err := json.Marshal(p)
	if err != nil {
		log.Fatal(err)
	}

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

	// Assigned uids for nodes which were created would be returned in the assigned.Uids map.
	//variables := map[string]string{"$id": assigned.Uids["blank-0"]}
	q := `
		{
			lookup(func: eq(apps.apps.app_id, "APPID01")){
				uid
				apps.apps.app_id
				apps.apps.app_desc
			}
		}
	
	`

	resp, err := dg.NewTxn().Query(ctx, q)
	if err != nil {
		log.Fatal(err)
	}

	type Root struct {
		Me []App `json:"me"`
	}

	var r Root
	err = json.Unmarshal(resp.Json, &r)
	if err != nil {
		log.Fatal(err)
	}
	// fmt.Printf("Me: %+v\n", r.Me)
	// R.Me would be same as the person that we set above.

	fmt.Println(string(resp.Json))
}

what am I missing?


(Michel Conrado) #2

Check this test file https://github.com/dgraph-io/dgraph/blob/master/contrib/integration/acctupsert/main.go

You need to query and then mutate, using the upsert procedure.


(Barum) #3

Thank you for the example.
Question: I thought the @upsert was supposed to take care of duplicate inserts?
Whats the point of having the @upsert if I have to do a READ before WRITE?


(Michel Conrado) #4

Yeah, actually the upsert directive takes care of duplicate during transactions. It’s not a kind of “lock” ou automation. But we are working in a better upsert feature here https://github.com/dgraph-io/dgraph/issues/3059

Check https://github.com/dgraph-io/dgraph/pull/3412

So, Dgraph has “Upsert directive” and “Upsert procedure”. They’re different but for the same purpose, you need to use both together. Upsert procedure is basically a transaction with a query and then a mutation.

I think #3059 will cover this need better soon.