# Upsert using Go client creates duplicate nodes

**URL:** <https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452>\
**Category:** Dgraph\
**Tags:** mutation\
**Created:** [April 26, 2020, 6:36pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452 "2020-04-26T18:36:52Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![milosgajdos](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/milosgajdos/32/2726_2.png) [@milosgajdos](https://discuss.dgraph.io/u/milosgajdos)\
**Post date:** [April 26, 2020, 6:36pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/1 "2020-04-26T18:36:52Z")

</div>

I’m trying to do an `upsert` using Go client based on the official [README](https://github.com/dgraph-io/dgo#running-an-upsert-query--mutation) and [godoc](https://godoc.org/github.com/dgraph-io/dgo#example-Txn-Mutate-Upsert), but it seems to be creating duplicate entries in the database o\_O

This is a short snippet of my code:

```auto
	query := `
          query Node($xid: string){
		     node(func: eq(xid, $xid)) {
			      xid
		     }
          }
	`

	node := &Node{
		UID: obj.UID().String(),
		Name: obj.Name(),
		Kind: obj.Kind(),
		Ns: obj.Namespace(),
		DType: []string{"Object"},
	}

	pb, err := json.Marshal(node)
	if err != nil {
		return nil, err
	}

	mu := &api.Mutation{
		SetJson: pb,
	}

	req := &api.Request{
		Query: query,
		Vars: map[string]string{"$xid": obj.UID().String()},
		Mutations: []*api.Mutation{mu},
		CommitNow: true,
	}

	ctx := context.Background()
	txn := d.client.NewTxn()
	defer txn.Discard(ctx)

	if _, err := txn.Do(ctx, req); err != nil {
		return nil, err
	}

```

The idea is to create the `Object` only if it does not exist, but the above keeps creating duplicate entries. Am I missing something here? This is the JSON result

```auto
{
  "data": {
    "node": [
      {
        "xid": "objectUID",
        "name": "fooKind-objectX",
        "kind": "fooKind",
        "ns": "fooNS"
      },
      {
        "xid": "objectUID",
        "name": "fooKind-objectX",
        "kind": "fooKind",
        "ns": "fooNS"
      }
    ]
  },

```

Thanks

---

<div class="post-metadata">

**Author:** ![Paras](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/paras/32/2768_2.png) [@Paras](https://discuss.dgraph.io/u/Paras)\
**Post date:** [April 26, 2020, 8:11pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/2 "2020-04-26T20:11:12Z")

</div>

Can you provide the complete snippet?

From a first look, it looks your query block is not assigning any query variables. And the mutation is happening unconditionally since it is not using any variables.

You should assign a var in the query block and use that in mutation as shown in the examples

---

<div class="post-metadata">

**Author:** ![milosgajdos](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/milosgajdos/32/2726_2.png) [@milosgajdos](https://discuss.dgraph.io/u/milosgajdos)\
**Post date:** [April 26, 2020, 8:21pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/3 "2020-04-26T20:21:17Z")

</div>

> [@Paras](#):
>
> Can you provide the complete snippet?

Sure, but I doubt it will make things any clearer

```auto
func (d *dgraph) Add(obj Object) (store.Node, error) {
	query := `
          query Node($xid: string){
		      node(func: eq(xid, $xid)) {
			      xid
		      }
          }
	`

	node := &Node{
		UID: obj.UID().String(),
		Name: obj.Name(),
		Kind: obj.Kind(),
		Namespace: obj.Namespace(),
		DType: []string{"Object"},
	}

	pb, err := json.Marshal(node)
	if err != nil {
		return nil, err
	}

	mu := &api.Mutation{
		SetJson: pb,
	}

	req := &api.Request{
		Query: query,
		Vars: map[string]string{"$xid": obj.UID().String()},
		Mutations: []*api.Mutation{mu},
		CommitNow: true,
	}

	ctx := context.Background()
	txn := d.client.NewTxn()
	defer txn.Discard(ctx)

	if _, err := txn.Do(ctx, req); err != nil {
		return nil, err
	}

	snode := entity.NewNode(node.UID)

	return snode, nil
}

```

For the completeness, this is the schema:

```auto
var Schema = `
	type Object {
		xid
		name
		kind
		namespace
	}

	xid: string @index(exact) .
	name: string @index(exact) .
	kind: string @index(exact) .
	namespace: string @index(exact) .
`

```

> [@Paras](#):
>
> From a first look, it looks your query block is not assigning any query variables

This was my suspicion, but I expect passing `Vars: map[string]string{"$xid": obj.UID().String()},` to the `api.Request` automatically assigns the `$xid` to the query before execution the `Mutation`? Am I missing anything here?

I shall also add I’m using the following version of dgraph:

```auto
dgraph/standalone v2.0.0-beta 38fd01d675aa 2 months ago 153MB

```

And the following version of Go client:

```auto
github.com/dgraph-io/dgo/v200 v200.0.0-20200402171935-2ec5bf1438b0

```

---

<div class="post-metadata">

**Author:** ![Paras](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/paras/32/2768_2.png) [@Paras](https://discuss.dgraph.io/u/Paras)\
**Post date:** [April 26, 2020, 8:31pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/4 "2020-04-26T20:31:38Z")

</div>

I am unaware of how Vars is used. I will need to learn about it.

However, in the meantime, can you assign a variable in the query block itself exactly as shown in the examples? That should just work.

---

<div class="post-metadata">

**Author:** ![milosgajdos](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/milosgajdos/32/2726_2.png) [@milosgajdos](https://discuss.dgraph.io/u/milosgajdos)\
**Post date:** [April 26, 2020, 8:37pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/5 "2020-04-26T20:37:22Z")

</div>

> [@Paras](#):
>
> can you assign a variable in the query block itself exactly as shown in the examples?

Are you suggesting I should avoid marshalling into JSON completely and take the `Nquads` approach ?

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [April 26, 2020, 8:43pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/6 "2020-04-26T20:43:21Z")

</div>

I think you are using [Upsert Block](https://dgraph.io/docs/mutations/#upsert-block). Unfortunately there nos support for [GraphQL Variables](https://dgraph.io/docs/query-language/#graphql-variables) in Upsert Block.

Follow this ticket  
[https://github.com/dgraph-io/dgraph/issues/4615](https://github.com/dgraph-io/dgraph/issues/4615)

---

<div class="post-metadata">

**Author:** ![Paras](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/paras/32/2768_2.png) [@Paras](https://discuss.dgraph.io/u/Paras)\
**Post date:** [April 26, 2020, 8:46pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/8 "2020-04-26T20:46:20Z")

</div>

> [@milosgajdos](#):
>
> Are you suggesting I should avoid marshalling into JSON completely and take the `Nquads` approach ?

No.  
In the godocs [dgo package - github.com/dgraph-io/dgo - Go Packages](https://godoc.org/github.com/dgraph-io/dgo#example-Txn-Mutate-Upsert) , there is also an example for JSON Upsert. Please follow that.

---

<div class="post-metadata">

**Author:** ![milosgajdos](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/milosgajdos/32/2726_2.png) [@milosgajdos](https://discuss.dgraph.io/u/milosgajdos)\
**Post date:** [April 26, 2020, 9:10pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/9 "2020-04-26T21:10:01Z")

</div>

> [@Paras](#):
>
> In the godocs [dgo package - github.com/dgraph-io/dgo - Go Packages](https://godoc.org/github.com/dgraph-io/dgo#example-Txn-Mutate-Upsert) , there is also an example for JSON Upsert

Ah, I totally missed that! Ok, I will check this out later on and send an update, but I suspect @MichelDiz is right. I am using the GraphQL vars \>\_\<

I also suspect, judging by the quick look at the code, without the GraphQL vars I’ll have to do some mad string concatenation to write the query ugh 😅 so the code itself will become a bit of an unwieldy mess, but I guess if there is no other way.

---

<div class="post-metadata">

**Author:** ![milosgajdos](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/milosgajdos/32/2726_2.png) [@milosgajdos](https://discuss.dgraph.io/u/milosgajdos)\
**Post date:** [April 26, 2020, 9:33pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/10 "2020-04-26T21:33:17Z")

</div>

Ok, I just quickly wrote some code to test the @Paras’ suggestion to follow the godoc upsert JSON example did the trick.

I also feel @MichelDiz was right to highlight the GraphQL vars do not work with `upsert`s at the moment – I really hope they will do, soon.

I’d like to accept both answers as solutions because I believe both are correct. I shall leave you two to decide who gets the green tick 😉

Either way, thanks to both of you for pointing me in the right direction!

---

<div class="post-metadata">

**Author:** ![MichelDiz](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/micheldiz/32/11873_2.png) [@MichelDiz](https://discuss.dgraph.io/u/MichelDiz)\
**Post date:** [April 26, 2020, 11:52pm UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/11 "2020-04-26T23:52:38Z")

</div>

Done, as both answers are different valid solutions. Your answer holds the solution.

---

<div class="post-metadata">

**Author:** ![milosgajdos](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/milosgajdos/32/2726_2.png) [@milosgajdos](https://discuss.dgraph.io/u/milosgajdos)\
**Post date:** [April 28, 2020, 9:16am UTC](https://discuss.dgraph.io/t/upsert-using-go-client-creates-duplicate-nodes/6452/13 "2020-04-28T09:16:37Z")

</div>

For anyone following this thread, the answer turns to be this:

```auto
query := `
	{
		node(func: eq(xid, "` + obj.UID().String() + `")) {
			u as uid
		}
	}
	`

	node := &Node{
		UID: "uid(u)",
		XID: obj.UID().String(),
		Name: obj.Name(),
		Kind: obj.Kind(),
		Namespace: obj.Namespace(),
		CreatedAt: time.Now(),
		DType: []string{"Object"},
	}

```

NOTE: the query variable is `uid` and not `xid`, which is then used for serialization (Dgraph creates a unique uid in the DB when the new object is created)
