The val function doesn't work when i use upsert


Report a Dgraph Bug

What version of Dgraph are you using?

from the latest commit feat(enterprise): audit logs for alpha and zero (#7295) · dgraph-io/dgraph@be9ce74 · GitHub

I found the val function doesn't work when i use upsert. and i run dgraph in a empty directory Dgraph Version
$ dgraph version
 
[Decoder]: Using assembly version of decoder
Page Size: 4096

Dgraph version   : v20.11.0-gbe9ce74e8
Dgraph codename  : unnamed-mod
Dgraph SHA-256   : 3bead42c6a5a1eaffd3fa33c5aca3f09574fad600b82cc1531f4f047db2b1ded
Commit SHA-1     : be9ce74e8
Commit timestamp : 2021-01-26 19:27:50 +0530
Branch           : master
Go version       : go1.15.6
jemalloc enabled : true

For Dgraph official documentation, visit https://dgraph.io/docs/.
For discussions about Dgraph     , visit http://discuss.dgraph.io.

Licensed variously under the Apache Public License 2.0 and Dgraph Community License.
Copyright 2015-2020 Dgraph Labs, Inc.

Have you tried reproducing the issue with the latest release?

Yes

What is the hardware spec (RAM, OS)?

$ lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma] (rev 02)
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.1 IDE interface: Intel Corporation 82371SB PIIX3 IDE [Natoma/Triton II]
00:01.2 USB controller: Intel Corporation 82371SB PIIX3 USB [Natoma/Triton II] (rev 01)
00:01.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 03)
00:02.0 VGA compatible controller: Cirrus Logic GD 5446
00:03.0 Unclassified device [00ff]: Red Hat, Inc. Virtio memory balloon
00:04.0 Communication controller: Red Hat, Inc. Virtio console
00:0a.0 SCSI storage controller: Red Hat, Inc. Virtio block device
00:12.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 03)
00:18.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #1 (rev 03)
00:18.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 03)
00:18.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #3 (rev 03)
00:18.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #1 (rev 03)
00:19.0 USB controller: NEC Corporation uPD720200 USB 3.0 Host Controller (rev 03)

$ uname -a
Linux parrot 5.9.0-2parrot1-amd64 #1 SMP Debian 5.9.6-2parrot1 (2020-11-17) x86_64 GNU/Linux

Steps to reproduce the issue (command/config used to run Dgraph).

the test script:

client = pydgraph.DgraphClient(client_stub)

txn = client.txn()
p = {
    'name': 'Alice',
}
print(txn.mutate(set_obj=p, commit_now=True))
query_ = '''{
a(func: has(name)){
    name
    uid
    }
}'''
print("***********************************************")
txn = client.txn()
pprint(json.loads(txn.query(query_).json))

query = '''{
test as uid(func: uid(0x666))
opt(func: has(name)){
    n as name
}
}'''
nquad = '''
uid(test) <name> val(n) .
'''
print("***********************************************")

txn = client.txn()
mutation = txn.create_mutation(set_nquads=nquad)
req = txn.create_request(query=query, mutations=[mutation], commit_now=1)
print(txn.do_request(req))

print("***********************************************")
txn = client.txn()
pprint(json.loads(txn.query(query_).json))

the result:

txn {
  start_ts: 8
  commit_ts: 9
  preds: "1-name"
}
latency {
  parsing_ns: 26591
  processing_ns: 2655303
  assign_timestamp_ns: 614663
  total_ns: 3482318
}
metrics {
  num_uids {
    key: "_total"
    value: 2
  }
  num_uids {
    key: "mutation_cost"
    value: 2
  }
}
uids {
  key: "dg.448592534.1"
  value: "0x3"
}

***********************************************
{'a': [{'name': 'Alice', 'uid': '0x3'}]}
***********************************************
json: "{\"uid\":[],\"opt\":[{\"name\":\"Alice\"}]}"
txn {
  start_ts: 11
  commit_ts: 12
}
latency {
  parsing_ns: 70497
  processing_ns: 1171391
  encoding_ns: 21325
  assign_timestamp_ns: 1510030
  total_ns: 3006946
}
metrics {
  num_uids {
    value: 1
  }
  num_uids {
    key: "_total"
    value: 2
  }
  num_uids {
    key: "mutation_cost"
  }
  num_uids {
    key: "name"
    value: 1
  }
}

***********************************************
{'a': [{'name': 'Alice', 'uid': '0x3'}]}

Expected behaviour and actual result.

i expect the node 0x666 should has name property and the value is Alice, but finally it still haven’t .

Experience Report for Feature Request

Note: Feature requests are judged based on user experience and modeled on Go Experience Reports. These reports should focus on the problems: they should not focus on and need not propose solutions.

What you wanted to do

What you actually did

Why that wasn’t great, with examples

Any external references to support your case

Same here. This actually doesn’t work.

The predicate is skipped if the uid connected to the variable and the target uid are different.

Unless of course this is an intended limitation of upsert? The upsert block documentation doesn’t explicitly say this is a limitation.

so…we can only use query+mutate, but not upsert ? :sob:

Welcome @Ro0tk1t,
From the above upsert block, it looks like you are trying to copy the name value from an existing node (with uid = 0x3) into a new node. Further, you want to assign the uid value to 0x666. Is this correct?

Dgraph uids for new nodes are typically assigned by zero, and not from a client.

In case you are trying to copy a node , you can achieve this by first querying the name value, along with any other attributes, of a particular node (with uid 0x3), and then send in a mutation to create a new node along with its name and other attributes set appropriately.

yeap, but when i copy a value from a exist node to another node that has been assigned by zero and with not queried by uid, the val(n) still has no effitient. the above script just for test for you see. :sob:

Yes it doesn’t work even when copying to an existing node.

This can’t be working as intended…

Hi @Ro0tk1t,

Let’s assume that there is one node with name “Alice”. Assuming that you want to use an upsert block to copy name value, you can try this:

upsert{
  query{
      alice(func: eq(name,"Alice")){
        n as name
      }
      qName(){
        nm as max(val(n))
      }

  }
  mutation{
    set{
      _:new <name> val(nm) .
    }
  }
}

This will create a new node with the name set to “Alice”.

The reason we have to use a max aggregation here is because, there is no guarantee that the opt or the alice query returns a single result. What if the data is such that val(n) can have multiple values? The aggregation helps in this case.

2 Likes

cool, thx. and i wanner know what the proof of comparsion of the max function for a string list, is the length or the ascii code or otherwise ?

AFAIK, the max function on string will sort using lexical ordering.

1 Like

awesome

Thank you so much for this answer. Can we get this added to the docs? I just ran into this issue where I couldn’t use the val on a new node but I could on an existing node. Very confusing.

@MichelDiz FYI - In my case I was using the uid() in the query block so I assumed the result was a single item and not an array. I didn’t know I would have to use the max to return a single item. There were also no errors or warnings in the result. It just silently ignored that line. It would be nice to have the error/warnings updated and also have this added to the docs. Thank you!

1 Like