# DQL conditional upsert with nested query value variables

**URL:** https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809
**Category:** Dgraph
**Tags:** mutation, kind:question
**Created:** [July 2, 2021, 4:43pm UTC](https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809 "2021-07-02T16:43:17Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Thammada](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/thammada/32/8360_2.png) [@Thammada](https://discuss.dgraph.io/u/Thammada)
#### Post date: [July 2, 2021, 4:43pm UTC](https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809/1 "2021-07-02T16:43:17Z")

</div>

## What I want to do

I want to use DQL mutation to update my data. The choice to use DQL is because I want to bypass @auth rules  
I have the following simplified GraphQL Schema

```auto
type Payment { # @auth rules omitted for simplification
  id: ID!
  isSuccessful: Boolean
  method: String
  reference: PaymentExternal
}

union PaymentExternal = ExternalXCharge | ExternalYRecord

type ExternalXCharge {
  id: String! @id
  # other fields specific to XCharge
}

type ExternalYRecord {
  id: String! @id
  # other fields specific to YRecord
}

```

with the following sample data

```auto
{
  "id": "0x8",
  "isSuccessFul": null,
  "method": "creditcard",
  "reference": {
    "id": "x_charge_id_12345"
  }
}

```

When querying using DQL, I get the following output

```auto
{
  "uid": "0x8",
  "Payment.method": "creditcard",
  "Payment.reference": {
    "uid": "0x7",
    "ExternalXCharge.id": "chrg_test_5odblz0450uyyjfo34z"
  }
}

```

I would like to update isSuccessful for the Payment record `0x8` while also checking whether reference.id value is equal to “x\_charge\_id\_12345”

## What I did

Since I have a conditional update, I tried to use Conditional Upsert, using the following RDF syntax

```auto
upsert {
  query {
    p as payment(func: uid(0x8)) {
      uid
      Payment.method
      Payment.reference {
        chargeId as ExternalXCharge.id
      }
    }
  }
  mutation @if(eq(val(chargeId), "x_charge_id_12345")) {
    set {
      uid(p) <Payment.isSuccessful> "true" .
    }
  }
}

```

ISSUE  
When I run the above request, no update occurred. The data has not been updated, when I tried to query using GraphQL and DQL syntax.  
It seems chargeId is not set properly, when I tried removing `@if` and set the values to new test predicates as follows

```auto
upsert {
  query {
    p as payment(func: uid(0x8)) {
      uid
      m as Payment.method
      Payment.reference {
        chargeId as ExternalXCharge.id
      }
    }
  }
  mutation {
    set {
      uid(p) <Payment.isSuccessful> "true" .
      uid(p) <testMethod> val(m) .
      uid(p) <testChargeId> val(chargeId) .
    }
  }
}

```

Only the value of `testMethod` is set.

However, both `val(m)` and `val(chargeId)` don’t seem to work with the `@if` condition

How do I update using the predicate `ExternalXCharge.id` on `Payment.reference` as a condition?

NOTE:  
When the update is successful I got the following as part of the raw response  
Is extensions.txn.preds supposed to be like that?

```auto
"preds":["1-\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000Payment.isSuccessful"]

```

PS: I’m using Postman to send requests

## Dgraph metadata

> **dgraph version**
>
> Dgraph version : v21.03.0  
> Dgraph codename : rocket  
> Dgraph SHA-256 : b4e4c77011e2938e9da197395dbce91d0c6ebb83d383b190f5b70201836a773f  
> Commit SHA-1 : a77bbe8ae  
> Commit timestamp : 2021-04-07 21:36:38 +0530  
> Branch : HEAD  
> Go version : go1.16.2  
> jemalloc enabled : true
> 
> For Dgraph official documentation, visit [Overview - Dgraph](https://dgraph.io/docs).  
> For discussions about Dgraph , visit [http://discuss.hypermode.com](http://discuss.hypermode.com).  
> For fully-managed Dgraph Cloud , visit [Overview - Dgraph](https://dgraph.io/cloud).
> 
> Licensed variously under the Apache Public License 2.0 and Dgraph Community License.  
> Copyright 2015-2021 Dgraph Labs, Inc.

---

<div class="post-metadata">

### Author: ![dmai](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/dmai/32/1254_2.png) [@dmai](https://discuss.dgraph.io/u/dmai)
#### Post date: [July 3, 2021, 5:48am UTC](https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809/2 "2021-07-03T05:48:58Z")

</div>

Dgraph’s `@if` upserts currently do not directly support string equals in the directive itself. You’ll want to do those matches in the query and then match against the `len()` of your query variable.

Something like this will work, essentially moving your conditional check into the query section:

```plaintext
upsert {
  query {
    p as payment(func: uid(0x2)) {
      uid
      Payment.method
      Payment.isSuccessful
      Payment.reference {
        chargeId as ExternalXCharge.id
      }
    }
    match as var(func: eq(val(chargeId), "x_charge_id_12345"))
  }
  mutation @if(eq(len(match), 1)) {
    set {
      uid(p) <Payment.isSuccessful> "true" .
    }
  }
}

```

* * *

> [@Thammada](#):
>
> When the update is successful I got the following as part of the raw response  
> Is extensions.txn.preds supposed to be like that?
> 
> ```auto
> "preds":["1-\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000Payment.isSuccessful"]
> 
> ```

Yup, that’s expected. The encoding here accounts for the multi-tenancy namespace available in the enterprise version and Dgraph Cloud.

---

<div class="post-metadata">

### Author: ![Thammada](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/thammada/32/8360_2.png) [@Thammada](https://discuss.dgraph.io/u/Thammada)
#### Post date: [July 3, 2021, 4:16pm UTC](https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809/3 "2021-07-03T16:16:33Z")

</div>

Wow, that works great. Thank you!

Could you explain this part? I wonder why only `<testMethod>` is set and `<testChargeId>` is not

> [@Thammada](#):
>
> ```auto
> upsert {
> query {
> p as payment(func: uid(0x8)) {
> uid
> m as Payment.method
> Payment.reference {
> chargeId as ExternalXCharge.id
> }
> }
> }
> mutation {
> set {
> uid(p) <Payment.isSuccessful> "true" .
> uid(p) <testMethod> val(m) .
> uid(p) <testChargeId> val(chargeId) .
> }
> }
> }
> 
> ```
> 
> Only the value of `testMethod` is set.

---

<div class="post-metadata">

### Author: ![amaster507](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/amaster507/32/4123_2.png) [@amaster507](https://discuss.dgraph.io/u/amaster507)
#### Post date: [July 3, 2021, 4:42pm UTC](https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809/4 "2021-07-03T16:42:51Z")

</div>

This will do it:

```auto
upsert {
  query {
    p as payment(func: uid(0x8)) {
      uid
      m as Payment.method
      r as Payment.reference {
        chargeId as ExternalXCharge.id
      }
    }
  }
  mutation {
    set {
      uid(p) <Payment.isSuccessful> "true" .
      uid(p) <testMethod> val(m) .
      uid(r) <testChargeId> val(chargeId) .
    }
  }
}

```

The `val` is a special function in that it is not just returning a list of values but rather a list mapped to uids. So when the uid of the value is not found in the `p variable then the value gets ignored.

---

<div class="post-metadata">

### Author: ![BenW](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/benw/32/7532_2.png) [@BenW](https://discuss.dgraph.io/u/BenW)
#### Post date: [August 30, 2022, 10:58pm UTC](https://discuss.dgraph.io/t/dql-conditional-upsert-with-nested-query-value-variables/14809/5 "2022-08-30T22:58:38Z")

</div>

Solved another one of my problems, yet again lol. Thanks
