# Upsert with val() not working

**URL:** <https://discuss.dgraph.io/t/upsert-with-val-not-working/18926>\
**Category:** Dgraph\
**Created:** [September 21, 2023, 1:05am UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926 "2023-09-21T01:05:51Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![markushedlund](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/markushedlund/32/10286_2.png) [@markushedlund](https://discuss.dgraph.io/u/markushedlund)\
**Post date:** [September 21, 2023, 1:05am UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926/1 "2023-09-21T01:05:51Z")

</div>

## What I want to do

Run an upsert mutation similar to this:

```auto
query lookup($0: string!) { CLASS_1 as var(func: type(Class)) @filter(eq(slug, $0)) { CLASS_1_LABEL as label }

```

```auto
  'set': {
    'uid': 'uid(NODE_1)', 
    'modified': '2023-09-21T00:34:41.648434+00:00', 
    'value': 'val(CLASS_1_LABEL)', 
    'class': {'uid': 'uid(CLASS_1)'}
  }

```

The part `'value': 'val(CLASS_1_LABEL)'` “silently fails”; it doesn’t update the predicate “value”.

## What I did

I’ve run the query part of the mutation separately to verify the query and the variables, both seem fine.

If I change it to something like `'value': 'static value'` it’s reflected in the graph.

## Dgraph metadata

> **dgraph version**
>
> v21.12.0

## References

The DQL / Mutation / val function section in the docs has a JSON example, but it’s using a var that’s not defined (incorrect) [**https://dgraph.io/docs/dql/mutations/val-upsert/**](https://dgraph.io/docs/dql/mutations/val-upsert/)

---

<div class="post-metadata">

**Author:** ![Raphael](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/raphael/32/10075_2.png) [@Raphael](https://discuss.dgraph.io/u/Raphael)\
**Post date:** [September 22, 2023, 5:53am UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926/2 "2023-09-22T05:53:50Z")

</div>

Could you clarify what NODE\_1 is in your query?  
val(CLASS\_1\_LABEL) is retrieving the value of ‘label’ predicate for the given uid which is uid(NODE\_1) in your case.  
But CLASS\_1\_LABEL is a map of uid-\>label for all uids matching (func: type(Class)) @filter(eq(slug, $0)).

If uid(NODE\_1) is not in this list of uids of CLASS\_1\_LABEL map then val(…) is not defined and so the predicate is ignored.

---

<div class="post-metadata">

**Author:** ![markushedlund](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/markushedlund/32/10286_2.png) [@markushedlund](https://discuss.dgraph.io/u/markushedlund)\
**Post date:** [September 22, 2023, 4:45pm UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926/3 "2023-09-22T16:45:08Z")

</div>

Thanks for getting back to me @Raphael.  
Sure. The mutation is part of an upsert:

```auto
{
  'query': 'query lookup($0: string!, $1: string!) {
    CLASS_1 as var(func: type(Class)) @filter(eq(slug, $0)) { CLASS_1_LABEL as label }
    NODE_1 as var(func: type(Node)) @filter(uid_in(parents, $1) AND uid_in(class, uid(CLASS_1))) 
  }',
  'mutations': [
    {
      'cond': '@if(eq(len(CLASS_1), 1) AND eq(len(NODE_1), 1))',
      'set': {
        'uid': 'uid(NODE_1)', 
        'modified': '2023-09-21T00:34:41.648434+00:00', 
        'value': 'val(CLASS_1_LABEL)', 
        'class': {'uid': 'uid(CLASS_1)'}
    },
    {
      'cond': '@if(eq(len(CLASS_1), 1) AND eq(len(NODE_1), 0))',
      'set': {
        # data to create node
      }
    },
  }

```

For reference the schema is something like

```auto
type Class {
  label
  slug
}
type Node {
  class -> Class
  parents -> [Node]
  value
  modified
}

```

My intent with `val(CLASS_1_LABEL)` is to copy the value from `CLASS_1.label` into `NODE_1.value`. Is this possible?

---

<div class="post-metadata">

**Author:** ![Raphael](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/raphael/32/10075_2.png) [@Raphael](https://discuss.dgraph.io/u/Raphael)\
**Post date:** [September 25, 2023, 4:57pm UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926/4 "2023-09-25T16:57:49Z")

</div>

This approach will not work because val(CLASS\_1\_LABEL) is evaluated from a map and using the uid(NODE\_1): there is no value associated with the uid for CLASS\_1\_LABEL.

If I understand correctly you are looking for children of a give nodes that have a relation to a class and want to set the value predicate of those node to the label of the class.

I would do something like this in the query

```auto
var(func:uid($0)) @cascade {
   # parent node
   ~parents {
     # child node
      class @filter(eq(slud,$1)) {
         CLASS_LABEL as label
       }
   # aggregate the class label at the node level
   NODE_LABEL as max(val(CLASS_LABEL))
   }
}

# now use uid(NODE_LABEL) and val(NODE_LABEL) for the mutation.

```

Thinking in terms of graph is not an easy task and there are usually different ways to see the same problem. @cascade is an interesting feature to do “graph pattern matching”. Then var is a good way to extract some node in the path. The aggregation (max in this case) is a way to aggregate (propagate) some values to the upper level in the path.

In this approach @cascade is used to query only the node that can reach the class.  
The max(val()) is used to ‘propagate’ the value at the level of the node ( a node has only one class so the max is the val but we need an aggregation function).  
Now your NODE\_LABEL is a correct map between the node uid and the value of the label you need.  
I’m also using ~parents: you may have to index your predicate to use the reverse edge!

Can’t test the query without your data, but I hope it gives you enough insight to make it work. Let me know.

---

<div class="post-metadata">

**Author:** ![markushedlund](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/markushedlund/32/10286_2.png) [@markushedlund](https://discuss.dgraph.io/u/markushedlund)\
**Post date:** [September 26, 2023, 1:11am UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926/5 "2023-09-26T01:11:04Z")

</div>

Thanks for taking the time explaining it. Without seeing the data you led me to a solution, thanks a lot!

These are the changes I had to make:

1. `{ CLASS_1_LABEL as label }` is removed from `CLASS_1` query.
2. This is added to `NODE_1` query:

```auto
{
  class {
    CLASS_1_LABEL as label
  }
  NODE_LABEL as max(val(CLASS_1_LABEL))
}

```

1. In set, `CLASS_1_LABEL` is changed to `NODE_LABEL`.

---

<div class="post-metadata">

**Author:** ![markushedlund](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/markushedlund/32/10286_2.png) [@markushedlund](https://discuss.dgraph.io/u/markushedlund)\
**Post date:** [September 26, 2023, 2:58am UTC](https://discuss.dgraph.io/t/upsert-with-val-not-working/18926/6 "2023-09-26T02:58:48Z")

</div>

A follow-up question. Is there a solution or work-around for the case where NODE doesn’t exist, i.e. uid(NODE) is blank? Since it’s an upsert I’m trying to accomplish.

Assuming it doesn’t work because the variable is a map for existing uid\>value.
