github.com/dgraph-io/dgraph@v1.2.8/wiki/content/mutations/index.md (about)

     1  +++
     2  title = "Mutations"
     3  +++
     4  
     5  Adding or removing data in Dgraph is called a mutation.
     6  
     7  A mutation that adds triples is done with the `set` keyword.
     8  ```
     9  {
    10    set {
    11      # triples in here
    12    }
    13  }
    14  ```
    15  
    16  ## Triples
    17  
    18  The input language is triples in the W3C standard [RDF N-Quad format](https://www.w3.org/TR/n-quads/).
    19  
    20  Each triple has the form
    21  ```
    22  <subject> <predicate> <object> .
    23  ```
    24  Meaning that the graph node identified by `subject` is linked to `object` with directed edge `predicate`.  Each triple ends with a period.  The subject of a triple is always a node in the graph, while the object may be a node or a value (a literal).
    25  
    26  For example, the triple
    27  ```
    28  <0x01> <name> "Alice" .
    29  <0x01> <dgraph.type> "Person" .
    30  ```
    31  Represents that graph node with ID `0x01` has a `name` with string value `"Alice"`.  While triple
    32  ```
    33  <0x01> <friend> <0x02> .
    34  ```
    35  Represents that graph node with ID `0x01` is linked with the `friend` edge to node `0x02`.
    36  
    37  Dgraph creates a unique 64 bit identifier for every blank node in the mutation - the node's UID.  A mutation can include a blank node as an identifier for the subject or object, or a known UID from a previous mutation.
    38  
    39  
    40  ## Blank Nodes and UID
    41  
    42  Blank nodes in mutations, written `_:identifier`, identify nodes within a mutation.  Dgraph creates a UID identifying each blank node and returns the created UIDs as the mutation result.  For example, mutation:
    43  
    44  ```
    45  {
    46   set {
    47      _:class <student> _:x .
    48      _:class <student> _:y .
    49      _:class <name> "awesome class" .
    50      _:class <dgraph.type> "Class" .
    51      _:x <name> "Alice" .
    52      _:x <dgraph.type> "Person" .
    53      _:x <dgraph.type> "Student" .
    54      _:x <planet> "Mars" .
    55      _:x <friend> _:y .
    56      _:y <name> "Bob" .
    57      _:y <dgraph.type> "Person" .
    58      _:y <dgraph.type> "Student" .
    59   }
    60  }
    61  ```
    62  results in output (the actual UIDs will be different on any run of this mutation)
    63  ```
    64  {
    65    "data": {
    66      "code": "Success",
    67      "message": "Done",
    68      "uids": {
    69        "class": "0x2712",
    70        "x": "0x2713",
    71        "y": "0x2714"
    72      }
    73    }
    74  }
    75  ```
    76  The graph has thus been updated as if it had stored the triples
    77  ```
    78  <0x6bc818dc89e78754> <student> <0xc3bcc578868b719d> .
    79  <0x6bc818dc89e78754> <student> <0xb294fb8464357b0a> .
    80  <0x6bc818dc89e78754> <name> "awesome class" .
    81  <0x6bc818dc89e78754> <dgraph.type> "Class" .
    82  <0xc3bcc578868b719d> <name> "Alice" .
    83  <0xc3bcc578868b719d> <dgraph.type> "Person" .
    84  <0xc3bcc578868b719d> <dgraph.type> "Student" .
    85  <0xc3bcc578868b719d> <planet> "Mars" .
    86  <0xc3bcc578868b719d> <friend> <0xb294fb8464357b0a> .
    87  <0xb294fb8464357b0a> <name> "Bob" .
    88  <0xb294fb8464357b0a> <dgraph.type> "Person" .
    89  <0xb294fb8464357b0a> <dgraph.type> "Student" .
    90  ```
    91  The blank node labels `_:class`, `_:x` and `_:y` do not identify the nodes after the mutation, and can be safely reused to identify new nodes in later mutations.
    92  
    93  A later mutation can update the data for existing UIDs.  For example, the following to add a new student to the class.
    94  ```
    95  {
    96   set {
    97      <0x6bc818dc89e78754> <student> _:x .
    98      _:x <name> "Chris" .
    99      _:x <dgraph.type> "Person" .
   100      _:x <dgraph.type> "Student" .
   101   }
   102  }
   103  ```
   104  
   105  A query can also directly use UID.
   106  ```
   107  {
   108   class(func: uid(0x6bc818dc89e78754)) {
   109    name
   110    student {
   111     name
   112     planet
   113     friend {
   114      name
   115     }
   116    }
   117   }
   118  }
   119  ```
   120  
   121  ## External IDs
   122  
   123  Dgraph's input language, RDF, also supports triples of the form `<a_fixed_identifier> <predicate> literal/node` and variants on this, where the label `a_fixed_identifier` is intended as a unique identifier for a node.  For example, mixing [schema.org](http://schema.org) identifiers, [the movie database](https://www.themoviedb.org/) identifiers and blank nodes:
   124  
   125  ```
   126  _:userA <http://schema.org/type> <http://schema.org/Person> .
   127  _:userA <dgraph.type> "Person" .
   128  _:userA <http://schema.org/name> "FirstName LastName" .
   129  <https://www.themoviedb.org/person/32-robin-wright> <http://schema.org/type> <http://schema.org/Person> .
   130  <https://www.themoviedb.org/person/32-robin-wright> <http://schema.org/name> "Robin Wright" .
   131  ```
   132  
   133  As Dgraph doesn't natively support such external IDs as node identifiers.  Instead, external IDs can be stored as properties of a node with an `xid` edge.  For example, from the above, the predicate names are valid in Dgraph, but the node identified with `<http://schema.org/Person>` could be identified in Dgraph with a UID, say `0x123`, and an edge
   134  
   135  ```
   136  <0x123> <xid> "http://schema.org/Person" .
   137  <0x123> <dgraph.type> "ExternalType" .
   138  ```
   139  
   140  While Robin Wright might get UID `0x321` and triples
   141  
   142  ```
   143  <0x321> <xid> "https://www.themoviedb.org/person/32-robin-wright" .
   144  <0x321> <http://schema.org/type> <0x123> .
   145  <0x321> <http://schema.org/name> "Robin Wright" .
   146  <0x321> <dgraph.type> "Person" .
   147  ```
   148  
   149  An appropriate schema might be as follows.
   150  ```
   151  xid: string @index(exact) .
   152  <http://schema.org/type>: [uid] @reverse .
   153  ```
   154  
   155  Query Example: All people.
   156  
   157  ```
   158  {
   159    var(func: eq(xid, "http://schema.org/Person")) {
   160      allPeople as <~http://schema.org/type>
   161    }
   162  
   163    q(func: uid(allPeople)) {
   164      <http://schema.org/name>
   165    }
   166  }
   167  ```
   168  
   169  Query Example: Robin Wright by external ID.
   170  
   171  ```
   172  {
   173    robin(func: eq(xid, "https://www.themoviedb.org/person/32-robin-wright")) {
   174      expand(_all_) { expand(_all_) }
   175    }
   176  }
   177  
   178  ```
   179  
   180  {{% notice "note" %}} `xid` edges are not added automatically in mutations.  In general it is a user's responsibility to check for existing `xid`'s and add nodes and `xid` edges if necessary. Dgraph leaves all checking of uniqueness of such `xid`'s to external processes. {{% /notice %}}
   181  
   182  ## External IDs and Upsert Block
   183  
   184  The upsert block makes managing external IDs easy.
   185  
   186  Set the schema.
   187  ```
   188  xid: string @index(exact) .
   189  <http://schema.org/name>: string @index(exact) .
   190  <http://schema.org/type>: [uid] @reverse .
   191  ```
   192  
   193  Set the type first of all.
   194  ```
   195  {
   196    set {
   197      _:blank <xid> "http://schema.org/Person" .
   198      _:blank <dgraph.type> "ExternalType" .
   199    }
   200  }
   201  ```
   202  
   203  Now you can create a new person and attach its type using the upsert block.
   204  ```
   205     upsert {
   206        query {
   207          var(func: eq(xid, "http://schema.org/Person")) {
   208            Type as uid
   209          }
   210          var(func: eq(<http://schema.org/name>, "Robin Wright")) {
   211            Person as uid
   212          }
   213        }
   214        mutation {
   215            set {
   216             uid(Person) <xid> "https://www.themoviedb.org/person/32-robin-wright" .
   217             uid(Person) <http://schema.org/type> uid(Type) .
   218             uid(Person) <http://schema.org/name> "Robin Wright" .
   219             uid(Person) <dgraph.type> "Person" .
   220            }
   221        }
   222      }
   223  ```
   224  
   225  You can also delete a person and detach the relation between Type and Person Node. It's the same as above, but you use the keyword "delete" instead of "set". "`http://schema.org/Person`" will remain but "`Robin Wright`" will be deleted.
   226  
   227  ```
   228     upsert {
   229        query {
   230          var(func: eq(xid, "http://schema.org/Person")) {
   231            Type as uid
   232          }
   233          var(func: eq(<http://schema.org/name>, "Robin Wright")) {
   234            Person as uid
   235          }
   236        }
   237        mutation {
   238            delete {
   239             uid(Person) <xid> "https://www.themoviedb.org/person/32-robin-wright" .
   240             uid(Person) <http://schema.org/type> uid(Type) .
   241             uid(Person) <http://schema.org/name> "Robin Wright" .
   242             uid(Person) <dgraph.type> "Person" .
   243            }
   244        }
   245      }
   246  ```
   247  
   248  Query by user.
   249  ```
   250  {
   251    q(func: eq(<http://schema.org/name>, "Robin Wright")) {
   252      uid
   253      xid
   254      <http://schema.org/name>
   255      <http://schema.org/type> {
   256        uid
   257        xid
   258      }
   259    }
   260  }
   261  ```
   262  
   263  ## Language and RDF Types
   264  
   265  RDF N-Quad allows specifying a language for string values and an RDF type.  Languages are written using `@lang`. For example
   266  ```
   267  <0x01> <name> "Adelaide"@en .
   268  <0x01> <name> "Аделаида"@ru .
   269  <0x01> <name> "Adélaïde"@fr .
   270  <0x01> <dgraph.type> "Person" .
   271  ```
   272  See also [how language strings are handled in queries]({{< relref "query-language/index.md#language-support" >}}).
   273  
   274  RDF types are attached to literals with the standard `^^` separator.  For example
   275  ```
   276  <0x01> <age> "32"^^<xs:int> .
   277  <0x01> <birthdate> "1985-06-08"^^<xs:dateTime> .
   278  ```
   279  
   280  The supported [RDF datatypes](https://www.w3.org/TR/rdf11-concepts/#section-Datatypes) and the corresponding internal type in which the data is stored are as follows.
   281  
   282  | Storage Type                                                    | Dgraph type     |
   283  | -------------                                                   | :------------:   |
   284  | &#60;xs:string&#62;                                             | `string`         |
   285  | &#60;xs:dateTime&#62;                                           | `dateTime`       |
   286  | &#60;xs:date&#62;                                               | `datetime`       |
   287  | &#60;xs:int&#62;                                                | `int`            |
   288  | &#60;xs:integer&#62;                                            | `int`            |
   289  | &#60;xs:boolean&#62;                                            | `bool`           |
   290  | &#60;xs:double&#62;                                             | `float`          |
   291  | &#60;xs:float&#62;                                              | `float`          |
   292  | &#60;geo:geojson&#62;                                           | `geo`            |
   293  | &#60;xs:password&#62;                                           | `password`       |
   294  | &#60;http&#58;//www.w3.org/2001/XMLSchema#string&#62;           | `string`         |
   295  | &#60;http&#58;//www.w3.org/2001/XMLSchema#dateTime&#62;         | `dateTime`       |
   296  | &#60;http&#58;//www.w3.org/2001/XMLSchema#date&#62;             | `dateTime`       |
   297  | &#60;http&#58;//www.w3.org/2001/XMLSchema#int&#62;              | `int`            |
   298  | &#60;http&#58;//www.w3.org/2001/XMLSchema#positiveInteger&#62;  | `int`            |
   299  | &#60;http&#58;//www.w3.org/2001/XMLSchema#integer&#62;          | `int`            |
   300  | &#60;http&#58;//www.w3.org/2001/XMLSchema#boolean&#62;          | `bool`           |
   301  | &#60;http&#58;//www.w3.org/2001/XMLSchema#double&#62;           | `float`          |
   302  | &#60;http&#58;//www.w3.org/2001/XMLSchema#float&#62;            | `float`          |
   303  
   304  
   305  See the section on [RDF schema types]({{< relref "#rdf-types" >}}) to understand how RDF types affect mutations and storage.
   306  
   307  
   308  ## Batch mutations
   309  
   310  Each mutation may contain multiple RDF triples. For large data uploads many such mutations can be batched in parallel.  The command `dgraph live` does just this; by default batching 1000 RDF lines into a query, while running 100 such queries in parallel.
   311  
   312  `dgraph live` takes as input gzipped N-Quad files (that is triple lists without `{ set {`) and batches mutations for all triples in the input.  The tool has documentation of options.
   313  
   314  ```
   315  dgraph live --help
   316  ```
   317  See also [Fast Data Loading](/deploy#fast-data-loading).
   318  
   319  ## Delete
   320  
   321  A delete mutation, signified with the `delete` keyword, removes triples from the store.
   322  
   323  For example, if the store contained
   324  ```
   325  <0xf11168064b01135b> <name> "Lewis Carrol"
   326  <0xf11168064b01135b> <died> "1998"
   327  <0xf11168064b01135b> <dgraph.type> "Person" .
   328  ```
   329  
   330  Then delete mutation
   331  
   332  ```
   333  {
   334    delete {
   335       <0xf11168064b01135b> <died> "1998" .
   336    }
   337  }
   338  ```
   339  
   340  Deletes the erroneous data and removes it from indexes if present.
   341  
   342  For a particular node `N`, all data for predicate `P` (and corresponding indexing) is removed with the pattern `S P *`.
   343  
   344  ```
   345  {
   346    delete {
   347       <0xf11168064b01135b> <author.of> * .
   348    }
   349  }
   350  ```
   351  
   352  The pattern `S * *` deletes all known edges out of a node (the node itself may
   353  remain as the target of edges), any reverse edges corresponding to the removed
   354  edges and any indexing for the removed data. The predicates to delete are
   355  derived from the type information for that node (the value of the `dgraph.type`
   356  edges on that node and their corresponding definitions in the schema). If that
   357  information is missing, this operation will be a no-op.
   358  
   359  ```
   360  {
   361    delete {
   362       <0xf11168064b01135b> * * .
   363    }
   364  }
   365  ```
   366  
   367  
   368  {{% notice "note" %}} The patterns `* P O` and `* * O` are not supported since its expensive to store/find all the incoming edges. {{% /notice %}}
   369  
   370  ### Deletion of non-list predicates
   371  
   372  Deleting the value of a non-list predicate (i.e a 1-to-1 relation) can be done in two ways.
   373  
   374  1. Using the star notation mentioned in the last section.
   375  1. Setting the object to a specific value. If the value passed is not the current value, the mutation will succeed but will have no effect. If the value passed is the current value, the mutation will succeed and will delete the triple.
   376  
   377  For language-tagged values, the following special syntax is supported:
   378  
   379  ```
   380  {
   381  	delete {
   382  		<0x12345> <name@es> * .
   383  	}
   384  }
   385  ```
   386  
   387  In this example, the value of name tagged with language tag `es` will be deleted.
   388  Other tagged values are left untouched.
   389  
   390  ## Mutations using cURL
   391  
   392  Mutations can be done over HTTP by making a `POST` request to an Alpha's `/mutate` endpoint. On the command line this can be done with curl. To commit the mutation, pass the parameter `commitNow=true` in the URL.
   393  
   394  To run a `set` mutation:
   395  
   396  ```sh
   397  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   398  {
   399    set {
   400      _:alice <name> "Alice" .
   401      _:alice <dgraph.type> "Person" .
   402    }
   403  }'
   404  ```
   405  
   406  To run a `delete` mutation:
   407  
   408  ```sh
   409  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   410  {
   411    delete {
   412      # Example: The UID of Alice is 0x56f33
   413      <0x56f33> <name> * .
   414    }
   415  }'
   416  ```
   417  
   418  To run an RDF mutation stored in a file, use curl's `--data-binary` option so that, unlike the `-d` option, the data is not URL encoded.
   419  
   420  ```sh
   421  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true --data-binary @mutation.txt
   422  ```
   423  
   424  ## JSON Mutation Format
   425  
   426  Mutations can also be specified using JSON objects. This can allow mutations to
   427  be expressed in a more natural way. It also eliminates the need for apps to
   428  have custom serialisation code, since most languages already have a JSON
   429  marshalling library.
   430  
   431  When Dgraph receives a mutation as a JSON object, it first converts in into
   432  multiple RDFs that are then processed as normal.
   433  
   434  Each JSON object represents a single node in the graph.
   435  
   436  {{% notice "note" %}}
   437  JSON mutations are available via gRPC clients such as the Go client, JS client, and Java client, and are available to HTTP clients with [dgraph-js-http](https://github.com/dgraph-io/dgraph-js-http) and cURL. See more about cURL [here]({{< relref "#using-json-operations-via-curl" >}})
   438  {{% /notice %}}
   439  
   440  ### Setting literal values
   441  
   442  When setting new values, the `set_json` field in the `Mutation` message should
   443  contain a JSON object.
   444  
   445  Literal values can be set by adding a key/value to the JSON object. The key
   446  represents the predicate, and the value represents the object.
   447  
   448  For example:
   449  ```json
   450  {
   451    "name": "diggy",
   452    "food": "pizza",
   453    "dgraph.type": "Mascot"
   454  }
   455  ```
   456  Will be converted into the RDFs:
   457  ```
   458  _:blank-0 <name> "diggy" .
   459  _:blank-0 <food> "pizza" .
   460  _:blank-0 <dgraph.type> "Mascot" .
   461  ```
   462  
   463  The result of the mutation would also contain a map, which would have the uid assigned corresponding
   464  to the key `blank-0`. You could specify your own key like
   465  
   466  ```json
   467  {
   468    "uid": "_:diggy",
   469    "name": "diggy",
   470    "food": "pizza",
   471    "dgraph.type": "Mascot"
   472  }
   473  ```
   474  
   475  In this case, the assigned uids map would have a key called `diggy` with the value being the uid
   476  assigned to it.
   477  
   478  ### Language support
   479  
   480  An important difference between RDF and JSON mutations is in regards to specifying a string value's
   481  language. In JSON, the language tag is appended to the edge _name_, not the value like in RDF.
   482  
   483  For example, the JSON mutation
   484  ```json
   485  {
   486    "food": "taco",
   487    "rating@en": "tastes good",
   488    "rating@es": "sabe bien",
   489    "rating@fr": "c'est bon",
   490    "rating@it": "è buono",
   491    "dgraph.type": "Food"
   492  }
   493  ```
   494  
   495  is equivalent to the following RDF:
   496  ```
   497  _:blank-0 <food> "taco" .
   498  _:blank-0 <dgraph.type> "Food" .
   499  _:blank-0 <rating> "tastes good"@en .
   500  _:blank-0 <rating> "sabe bien"@es .
   501  _:blank-0 <rating> "c'est bon"@fr .
   502  _:blank-0 <rating> "è buono"@it .
   503  ```
   504  
   505  ### Geolocation support
   506  
   507  Support for geolocation data is available in JSON. Geo-location data is entered
   508  as a JSON object with keys "type" and "coordinates". Keep in mind we only
   509  support indexing on the Point, Polygon, and MultiPolygon types, but we can store
   510  other types of geolocation data. Below is an example:
   511  
   512  ```
   513  {
   514    "food": "taco",
   515    location: {
   516      "type": "Point",
   517      "coordinates": [1.0, 2.0]
   518    }
   519  }
   520  ```
   521  
   522  ### Referencing existing nodes
   523  
   524  If a JSON object contains a field named `"uid"`, then that field is interpreted
   525  as the UID of an existing node in the graph. This mechanism allows you to
   526  reference existing nodes.
   527  
   528  For example:
   529  ```json
   530  {
   531    "uid": "0x467ba0",
   532    "food": "taco",
   533    "rating": "tastes good",
   534    "dgraph.type": "Food"
   535  }
   536  ```
   537  Will be converted into the RDFs:
   538  ```
   539  <0x467ba0> <food> "taco" .
   540  <0x467ba0> <rating> "tastes good" .
   541  <0x467ba0> <dgraph.type> "Food" .
   542  ```
   543  
   544  ### Edges between nodes
   545  
   546  Edges between nodes are represented in a similar way to literal values, except
   547  that the object is a JSON object.
   548  
   549  For example:
   550  ```json
   551  {
   552    "name": "Alice",
   553    "friend": {
   554      "name": "Betty"
   555    }
   556  }
   557  ```
   558  Will be converted into the RDFs:
   559  ```
   560  _:blank-0 <name> "Alice" .
   561  _:blank-0 <friend> _:blank-1 .
   562  _:blank-1 <name> "Betty" .
   563  ```
   564  
   565  The result of the mutation would contain the uids assigned to `blank-0` and `blank-1` nodes. If you
   566  wanted to return these uids under a different key, you could specify the `uid` field as a blank
   567  node.
   568  
   569  ```json
   570  {
   571    "uid": "_:alice",
   572    "name": "Alice",
   573    "friend": {
   574      "uid": "_:bob",
   575      "name": "Betty"
   576    }
   577  }
   578  ```
   579  
   580  Will be converted to:
   581  
   582  ```
   583  _:alice <name> "Alice" .
   584  _:alice <friend> _:bob .
   585  _:bob <name> "Betty" .
   586  ```
   587  
   588  Existing nodes can be referenced in the same way as when adding literal values.
   589  E.g. to link two existing nodes:
   590  ```json
   591  {
   592    "uid": "0x123",
   593    "link": {
   594      "uid": "0x456"
   595    }
   596  }
   597  ```
   598  
   599  Will be converted to:
   600  
   601  ```JSON
   602  <0x123> <link> <0x456> .
   603  ```
   604  
   605  {{% notice "note" %}}
   606  A common mistake is to attempt to use `{"uid":"0x123","link":"0x456"}`.  This
   607  will result in an error. Dgraph interprets this JSON object as setting the
   608  `link` predicate to the string`"0x456"`, which is usually not intended.  {{%
   609  /notice %}}
   610  
   611  ### Deleting literal values
   612  
   613  Deletion mutations can also be sent in JSON format. To send a delete mutation,
   614  use the `delete_json` field instead of the `set_json` field in the `Mutation`
   615  message.
   616  
   617  {{% notice "note" %}} Check the [JSON Syntax using Raw HTTP or Ratel UI]({{< relref "#json-syntax-using-raw-http-or-ratel-ui">}}) section if you're using the dgraph-js-http client or Ratel UI. {{% /notice %}}
   618  
   619  When using delete mutations, an existing node always has to be referenced. So
   620  the `"uid"` field for each JSON object must be present. Predicates that should
   621  be deleted should be set to the JSON value `null`.
   622  
   623  For example, to remove a food rating:
   624  ```json
   625  {
   626    "uid": "0x467ba0",
   627    "rating": null
   628  }
   629  ```
   630  
   631  ### Deleting edges
   632  
   633  Deleting a single edge requires the same JSON object that would create that
   634  edge. E.g. to delete the predicate `link` from `"0x123"` to `"0x456"`:
   635  ```json
   636  {
   637    "uid": "0x123",
   638    "link": {
   639      "uid": "0x456"
   640    }
   641  }
   642  ```
   643  
   644  All edges for a predicate emanating from a single node can be deleted at once
   645  (corresponding to deleting `S P *`):
   646  ```json
   647  {
   648    "uid": "0x123",
   649    "link": null
   650  }
   651  ```
   652  
   653  If no predicates are specified, then all of the node's known outbound edges (to
   654  other nodes and to literal values) are deleted (corresponding to deleting `S *
   655  *`). The predicates to delete are derived using the type system. Refer to the
   656  [RDF format]({{< relref "#delete" >}}) documentation and the section on the
   657  [type system]({{< relref "query-language/index.md#type-system" >}}) for more
   658  information:
   659  
   660  ```json
   661  {
   662    "uid": "0x123"
   663  }
   664  ```
   665  
   666  ### Facets
   667  
   668  Facets can be created by using the `|` character to separate the predicate
   669  and facet key in a JSON object field name. This is the same encoding schema
   670  used to show facets in query results. E.g.
   671  ```json
   672  {
   673    "name": "Carol",
   674    "name|initial": "C",
   675    "dgraph.type": "Person",
   676    "friend": {
   677      "name": "Daryl",
   678      "friend|close": "yes",
   679      "dgraph.type": "Person"
   680    }
   681  }
   682  ```
   683  Produces the following RDFs:
   684  ```
   685  _:blank-0 <name> "Carol" (initial=C) .
   686  _:blank-0 <dgraph.type> "Person" .
   687  _:blank-0 <friend> _:blank-1 (close=yes) .
   688  _:blank-1 <name> "Daryl" .
   689  _:blank-1 <dgraph.type> "Person" .
   690  ```
   691  
   692  Facets do not contain type information but Dgraph will try to guess a type from
   693  the input. If the value of a facet can be parsed to a number, it will be
   694  converted to either a float or an int. If it can be parsed as a boolean, it will
   695  be stored as a boolean. If the value is a string, it will be stored as a
   696  datetime if the string matches one of the time formats that Dgraph recognizes
   697  (YYYY, MM-YYYY, DD-MM-YYYY, RFC339, etc.) and as a double-quoted string
   698  otherwise. If you do not want to risk the chance of your facet data being
   699  misinterpreted as a time value, it is best to store numeric data as either an
   700  int or a float.
   701  
   702  ### Deleting Facets
   703  
   704  The easiest way to delete a Facet is overwriting it. When you create a new mutation for the same entity without a facet, the existing facet will be deleted automatically.
   705  
   706  e.g:
   707  
   708  ```RDF
   709  <0x1> <name> "Carol" .
   710  <0x1> <friend> <0x2> .
   711  ```
   712  
   713  Another way to do this is by using the Upsert Block.
   714  
   715  > In this query below, we are deleting Facet in the Name and Friend predicates. To overwrite we need to collect the values ​​of the edges on which we are performing this operation and use the function "val(var)" to complete the overwriting.
   716  
   717  ```sh
   718  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   719  upsert {
   720    query {
   721      user as var(func: eq(name, "Carol")){
   722        Name as name
   723        Friends as friend
   724      }
   725   }
   726  
   727    mutation {
   728      set {
   729        uid(user) <name> val(Name) .
   730        uid(user) <friend> uid(Friends) .
   731      }
   732    }
   733  }' | jq
   734  ```
   735  
   736  ### Creating a list with JSON and interacting with
   737  
   738  Schema:
   739  
   740  ```JSON
   741  testList: [string] .
   742  ```
   743  
   744  ```JSON
   745  {
   746    "testList": [
   747      "Grape",
   748      "Apple",
   749      "Strawberry",
   750      "Banana",
   751      "watermelon"
   752    ]
   753  }
   754  ```
   755  
   756  Let’s then remove "Apple" from this list (Remember, it’s case sensitive):
   757  
   758  ```JSON
   759  {
   760     "uid": "0xd", #UID of the list.
   761     "testList": "Apple"
   762  }
   763  ```
   764  
   765  {{% notice "note" %}} Check the [JSON Syntax using Raw HTTP or Ratel UI]({{< relref "#json-syntax-using-raw-http-or-ratel-ui">}}) section if you're using the dgraph-js-http client or Ratel UI. {{% /notice %}}
   766  
   767  
   768  Add another fruit:
   769  
   770  ```JSON
   771  {
   772     "uid": "0xd", #UID of the list.
   773     "testList": "Pineapple"
   774  }
   775  ```
   776  
   777  ### Specifying multiple operations
   778  
   779  When specifying add or delete mutations, multiple nodes can be specified
   780  at the same time using JSON arrays.
   781  
   782  For example, the following JSON object can be used to add two new nodes, each
   783  with a `name`:
   784  
   785  ```JSON
   786  [
   787    {
   788      "name": "Edward"
   789    },
   790    {
   791      "name": "Fredric"
   792    }
   793  ]
   794  ```
   795  
   796  ### JSON Syntax using Raw HTTP or Ratel UI
   797  
   798  This syntax can be used in the most current version of Ratel, in the [dgraph-js-http](https://github.com/dgraph-io/dgraph-js-http) client or even via cURL.
   799  
   800  You can also [download the Ratel UI for Linux, macOS, or Windows](https://discuss.dgraph.io/t/ratel-installer-for-linux-macos-and-windows-preview-version-ratel-update-from-v1-0-6/2884/).
   801  
   802  Mutate:
   803  ```JSON
   804  {
   805    "set": [
   806      {
   807        # One JSON obj in here
   808      },
   809      {
   810        # Another JSON obj in here for multiple operations
   811      }
   812    ]
   813  }
   814  ```
   815  
   816  Delete:
   817  
   818  Deletion operations are the same as [Deleting literal values]({{< relref "#deleting-literal-values">}}) and [Deleting edges]({{< relref "#deleting-edges">}}).
   819  
   820  ```JSON
   821  {
   822    "delete": [
   823      {
   824        # One JSON obj in here
   825      },
   826      {
   827        # Another JSON obj in here for multiple operations
   828      }
   829    ]
   830  }
   831  ```
   832  
   833  ### Using JSON operations via cURL
   834  
   835  First you have to configure the HTTP header to specify content-type.
   836  
   837  ```sh
   838  -H 'Content-Type: application/json'
   839  ```
   840  
   841  {{% notice "note" %}}
   842  In order to use `jq` for JSON formatting you need the `jq` package. See the
   843  [`jq` downloads](https://stedolan.github.io/jq/download/) page for installation
   844  details. You can also use Python's built in `json.tool` module with `python -m
   845  json.tool` to do JSON formatting.
   846  {{% /notice %}}
   847  
   848  ```sh
   849  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'
   850      {
   851        "set": [
   852          {
   853            "name": "Alice"
   854          },
   855          {
   856            "name": "Bob"
   857          }
   858        ]
   859      }' | jq
   860  
   861  ```
   862  
   863  To delete:
   864  
   865  ```sh
   866  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'
   867      {
   868        "delete": [
   869          {
   870            "uid": "0xa"
   871          }
   872        ]
   873      }' | jq
   874  ```
   875  
   876  Mutation with a JSON file:
   877  
   878  ```sh
   879  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d @data.json
   880  ```
   881  
   882  where the contents of data.json looks like the following:
   883  
   884  ```json
   885  {
   886    "set": [
   887      {
   888        "name": "Alice"
   889      },
   890      {
   891        "name": "Bob"
   892      }
   893    ]
   894  }
   895  ```
   896  
   897  The JSON file must follow the same format for mutations over HTTP: a single JSON
   898  object with the `"set"` or `"delete"` key and an array of JSON objects for the
   899  mutation. If you already have a file with an array of data, you can use `jq` to
   900  transform your data to the proper format. For example, if your data.json file
   901  looks like this:
   902  
   903  ```json
   904  [
   905    {
   906      "name": "Alice"
   907    },
   908    {
   909      "name": "Bob"
   910    }
   911  ]
   912  ```
   913  
   914  then you can transform your data to the proper format with the following `jq`
   915  command, where the `.` in the `jq` string represents the contents of data.json:
   916  
   917  ```sh
   918  cat data.json | jq '{set: .}'
   919  ```
   920  
   921  ```
   922  {
   923    "set": [
   924      {
   925        "name": "Alice"
   926      },
   927      {
   928        "name": "Bob"
   929      }
   930    ]
   931  }
   932  ```
   933  
   934  ## Upsert Block
   935  
   936  The upsert block allows performing queries and mutations in a single request. The upsert
   937  block contains one query block and one or more than one mutation blocks. Variables defined
   938  in the query block can be used in the mutation blocks using the `uid` and `val` function.
   939  
   940  In general, the structure of the upsert block is as follows:
   941  
   942  ```
   943  upsert {
   944    query <query block>
   945    [fragment <fragment block>]
   946    mutation <mutation block 1>
   947    [mutation <mutation block 2>]
   948    ...
   949  }
   950  ```
   951  
   952  Execution of an upsert block also returns the response of the query executed on the state
   953  of the database *before mutation was executed*. To get the latest result, we should commit
   954  the mutation and execute another query.
   955  
   956  ### `uid` Function
   957  
   958  The `uid` function allows extracting UIDs from variables defined in the query block.
   959  There are two possible outcomes based on the results of executing the query block:
   960  
   961  * If the variable is empty i.e. no node matched the query, the `uid` function returns a new UID in case of a `set` operation and is thus treated similar to a blank node. On the other hand, for `delete/del` operation, it returns no UID, and thus the operation becomes a no-op and is silently ignored. A blank node gets the same UID across all the mutation blocks.
   962  * If the variable stores one or more than one UIDs, the `uid` function returns all the UIDs stored in the variable. In this case, the operation is performed on all the UIDs returned, one at a time.
   963  
   964  ### `val` Function
   965  
   966  The `val` function allows extracting values from value variables. Value variables store
   967  a mapping from UIDs to their corresponding values. Hence, `val(v)` is replaced by the value
   968  stored in the mapping for the UID (Subject) in the N-Quad. If the variable `v` has no value
   969  for a given UID, the mutation is silently ignored. The `val` function can be used with the
   970  result of aggregate variables as well, in which case, all the UIDs in the mutation would
   971  be updated with the aggregate value.
   972  
   973  ### Example of `uid` Function
   974  
   975  Consider an example with the following schema:
   976  
   977  ```sh
   978  curl localhost:8080/alter -X POST -d $'
   979    name: string @index(term) .
   980    email: string @index(exact, trigram) @upsert .
   981    age: int @index(int) .' | jq
   982  ```
   983  
   984  Now, let's say we want to create a new user with `email` and `name` information.
   985  We also want to make sure that one email has exactly one corresponding user in
   986  the database. To achieve this, we need to first query whether a user exists
   987  in the database with the given email. If a user exists, we use its UID
   988  to update the `name` information. If the user doesn't exist, we create
   989  a new user and update the `email` and `name` information.
   990  
   991  We can do this using the upsert block as follows:
   992  
   993  ```sh
   994  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   995  upsert {
   996    query {
   997      q(func: eq(email, "user@company1.io")) {
   998        v as uid
   999        name
  1000      }
  1001    }
  1002  
  1003    mutation {
  1004      set {
  1005        uid(v) <name> "first last" .
  1006        uid(v) <email> "user@company1.io" .
  1007      }
  1008    }
  1009  }' | jq
  1010  ```
  1011  
  1012  Result:
  1013  
  1014  ```json
  1015  {
  1016    "data": {
  1017      "q": [],
  1018      "code": "Success",
  1019      "message": "Done",
  1020      "uids": {
  1021        "uid(v)": "0x1"
  1022      }
  1023    },
  1024    "extensions": {...}
  1025  }
  1026  ```
  1027  
  1028  The query part of the upsert block stores the UID of the user with the provided email
  1029  in the variable `v`. The mutation part then extracts the UID from variable `v`, and
  1030  stores the `name` and `email` information in the database. If the user exists,
  1031  the information is updated. If the user doesn't exist, `uid(v)` is treated
  1032  as a blank node and a new user is created as explained above.
  1033  
  1034  If we run the same mutation again, the data would just be overwritten, and no new uid is
  1035  created. Note that the `uids` map is empty in the result when the mutation is executed
  1036  again and the `data` map (key `q`) contains the uid that was created in the previous upsert.
  1037  
  1038  ```json
  1039  {
  1040    "data": {
  1041      "q": [
  1042        {
  1043          "uid": "0x1",
  1044          "name": "first last"
  1045        }
  1046      ],
  1047      "code": "Success",
  1048      "message": "Done",
  1049      "uids": {}
  1050    },
  1051    "extensions": {...}
  1052  }
  1053  ```
  1054  
  1055  We can achieve the same result using `json` dataset as follows:
  1056  
  1057  ```sh
  1058  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '
  1059  {
  1060    "query": "{ q(func: eq(email, \\"user@company1.io\\")) {v as uid\\n name} }",
  1061    "set": {
  1062      "uid": "uid(v)",
  1063      "name": "first last",
  1064      "email": "user@company1.io"
  1065    }
  1066  }' | jq
  1067  ```
  1068  
  1069  Now, we want to add the `age` information for the same user having the same email
  1070  `user@company1.io`. We can use the upsert block to do the same as follows:
  1071  
  1072  ```sh
  1073  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
  1074  upsert {
  1075    query {
  1076      q(func: eq(email, "user@company1.io")) {
  1077        v as uid
  1078      }
  1079    }
  1080  
  1081    mutation {
  1082      set {
  1083        uid(v) <age> "28" .
  1084      }
  1085    }
  1086  }' | jq
  1087  ```
  1088  
  1089  Result:
  1090  
  1091  ```json
  1092  {
  1093    "data": {
  1094      "q": [
  1095        {
  1096          "uid": "0x1"
  1097        }
  1098      ],
  1099      "code": "Success",
  1100      "message": "Done",
  1101      "uids": {}
  1102    },
  1103    "extensions": {...}
  1104  }
  1105  ```
  1106  
  1107  Here, the query block queries for a user with `email` as `user@company1.io`. It stores
  1108  the `uid` of the user in variable `v`. The mutation block then updates the `age` of the
  1109  user by extracting the uid from the variable `v` using `uid` function.
  1110  
  1111  We can achieve the same result using `json` dataset as follows:
  1112  
  1113  ```sh
  1114  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'
  1115  {
  1116    "query": "{ q(func: eq(email, \\"user@company1.io\\")) {v as uid} }",
  1117    "set":{
  1118      "uid": "uid(v)",
  1119      "age": "28"
  1120    }
  1121  }' | jq
  1122  ```
  1123  
  1124  If we want to execute the mutation only when the user exists, we could use
  1125  [Conditional Upsert]({{< relref "#conditional-upsert" >}}).
  1126  
  1127  ### Example of `val` Function
  1128  
  1129  Let's say we want to migrate the predicate `age` to `other`. We can do this using the
  1130  following mutation:
  1131  
  1132  ```sh
  1133  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
  1134  upsert {
  1135    query {
  1136      v as var(func: has(age)) {
  1137        a as age
  1138      }
  1139    }
  1140  
  1141    mutation {
  1142      # we copy the values from the old predicate
  1143      set {
  1144        uid(v) <other> val(a) .
  1145      }
  1146  
  1147      # and we delete the old predicate
  1148      delete {
  1149        uid(v) <age> * .
  1150      }
  1151    }
  1152  }' | jq
  1153  ```
  1154  
  1155  Result:
  1156  
  1157  ```json
  1158  {
  1159    "data": {
  1160      "code": "Success",
  1161      "message": "Done",
  1162      "uids": {}
  1163    },
  1164    "extensions": {...}
  1165  }
  1166  ```
  1167  
  1168  Here, variable `a` will store a mapping from all the UIDs to their `age`. The mutation
  1169  block then stores the corresponding value of `age` for each UID in the `other` predicate
  1170  and deletes the `age` predicate.
  1171  
  1172  We can achieve the same result using `json` dataset as follows:
  1173  
  1174  ```sh
  1175  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'{
  1176    "query": "{ v as var(func: regexp(email, /.*@company1.io$/)) }",
  1177    "delete": {
  1178      "uid": "uid(v)",
  1179      "age": null
  1180    },
  1181    "set": {
  1182      "uid": "uid(v)",
  1183      "other": "val(a)"
  1184    }
  1185  }' | jq
  1186  ```
  1187  
  1188  ### Bulk Delete Example
  1189  
  1190  Let's say we want to delete all the users of `company1` from the database. This can be
  1191  achieved in just one query using the upsert block as follows:
  1192  
  1193  ```sh
  1194  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
  1195  upsert {
  1196    query {
  1197      v as var(func: regexp(email, /.*@company1.io$/))
  1198    }
  1199  
  1200    mutation {
  1201      delete {
  1202        uid(v) <name> * .
  1203        uid(v) <email> * .
  1204        uid(v) <age> * .
  1205      }
  1206    }
  1207  }' | jq
  1208  ```
  1209  
  1210  We can achieve the same result using `json` dataset as follows:
  1211  
  1212  ```sh
  1213  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '{
  1214    "query": "{ v as var(func: regexp(email, /.*@company1.io$/)) }",
  1215    "delete": {
  1216      "uid": "uid(v)",
  1217      "name": null,
  1218      "email": null,
  1219      "age": null
  1220    }
  1221  }' | jq
  1222  ```
  1223  
  1224  ## Conditional Upsert
  1225  
  1226  The upsert block also allows specifying conditional mutation blocks using an `@if`
  1227  directive. The mutation is executed only when the specified condition is true. If the
  1228  condition is false, the mutation is silently ignored. The general structure of
  1229  Conditional Upsert looks like as follows:
  1230  
  1231  ```
  1232  upsert {
  1233    query <query block>
  1234    [fragment <fragment block>]
  1235    mutation [@if(<condition>)] <mutation block 1>
  1236    [mutation [@if(<condition>)] <mutation block 2>]
  1237    ...
  1238  }
  1239  ```
  1240  
  1241  The `@if` directive accepts a condition on variables defined in the query block and can be
  1242  connected using `AND`, `OR` and `NOT`.
  1243  
  1244  ### Example of Conditional Upsert
  1245  
  1246  Let's say in our previous example, we know the `company1` has less than 100 employees.
  1247  For safety, we want the mutation to execute only when the variable `v` stores less than
  1248  100 but greater than 50 UIDs in it. This can be achieved as follows:
  1249  
  1250  ```sh
  1251  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d  $'
  1252  upsert {
  1253    query {
  1254      v as var(func: regexp(email, /.*@company1.io$/))
  1255    }
  1256  
  1257    mutation @if(lt(len(v), 100) AND gt(len(v), 50)) {
  1258      delete {
  1259        uid(v) <name> * .
  1260        uid(v) <email> * .
  1261        uid(v) <age> * .
  1262      }
  1263    }
  1264  }' | jq
  1265  ```
  1266  
  1267  We can achieve the same result using `json` dataset as follows:
  1268  
  1269  ```sh
  1270  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '{
  1271    "query": "{ v as var(func: regexp(email, /.*@company1.io$/)) }",
  1272    "cond": "@if(lt(len(v), 100) AND gt(len(v), 50))",
  1273    "delete": {
  1274      "uid": "uid(v)",
  1275      "name": null,
  1276      "email": null,
  1277      "age": null
  1278    }
  1279  }' | jq
  1280  ```
  1281  
  1282  ### Example of Multiple Mutation Blocks
  1283  
  1284  Consider an example with the following schema:
  1285  
  1286  ```sh
  1287  curl localhost:8080/alter -X POST -d $'
  1288    name: string @index(term) .
  1289    email: [string] @index(exact) @upsert .' | jq
  1290  ```
  1291  
  1292  Let's say, we have many users stored in our database each having one or more than
  1293  one email Addresses. Now, we get two email Addresses that belong to the same user.
  1294  If the email Addresses belong to the different nodes in the database, we want to delete
  1295  the existing nodes and create a new node with both the emails attached to this new node.
  1296  Otherwise, we create/update the new/existing node with both the emails.
  1297  
  1298  ```sh
  1299  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
  1300  upsert {
  1301    query {
  1302      # filter is needed to ensure that we do not get same UIDs in u1 and u2
  1303      q1(func: eq(email, "user_email1@company1.io")) @filter(not(eq(email, "user_email2@company1.io"))) {
  1304        u1 as uid
  1305      }
  1306  
  1307      q2(func: eq(email, "user_email2@company1.io")) @filter(not(eq(email, "user_email1@company1.io"))) {
  1308        u2 as uid
  1309      }
  1310  
  1311      q3(func: eq(email, "user_email1@company1.io")) @filter(eq(email, "user_email2@company1.io")) {
  1312        u3 as uid
  1313      }
  1314    }
  1315  
  1316    # case when both emails do not exist
  1317    mutation @if(eq(len(u1), 0) AND eq(len(u2), 0) AND eq(len(u3), 0)) {
  1318      set {
  1319        _:user <name> "user" .
  1320        _:user <dgraph.type> "Person" .
  1321        _:user <email> "user_email1@company1.io" .
  1322        _:user <email> "user_email2@company1.io" .
  1323      }
  1324    }
  1325  
  1326    # case when email1 exists but email2 does not
  1327    mutation @if(eq(len(u1), 1) AND eq(len(u2), 0) AND eq(len(u3), 0)) {
  1328      set {
  1329        uid(u1) <email> "user_email2@company1.io" .
  1330      }
  1331    }
  1332  
  1333    # case when email1 does not exist but email2 exists
  1334    mutation @if(eq(len(u1), 0) AND eq(len(u2), 1) AND eq(len(u3), 0)) {
  1335      set {
  1336        uid(u2) <email> "user_email1@company1.io" .
  1337      }
  1338    }
  1339  
  1340    # case when both emails exist and needs merging
  1341    mutation @if(eq(len(u1), 1) AND eq(len(u2), 1) AND eq(len(u3), 0)) {
  1342      set {
  1343        _:user <name> "user" .
  1344        _:user <dgraph.type> "Person" .
  1345        _:user <email> "user_email1@company1.io" .
  1346        _:user <email> "user_email2@company1.io" .
  1347      }
  1348  
  1349      delete {
  1350        uid(u1) <name> * .
  1351        uid(u1) <email> * .
  1352        uid(u2) <name> * .
  1353        uid(u2) <email> * .
  1354      }
  1355    }
  1356  }' | jq
  1357  ```
  1358  
  1359  Result (when database is empty):
  1360  
  1361  ```json
  1362  {
  1363    "data": {
  1364      "q1": [],
  1365      "q2": [],
  1366      "q3": [],
  1367      "code": "Success",
  1368      "message": "Done",
  1369      "uids": {
  1370        "user": "0x1"
  1371      }
  1372    },
  1373    "extensions": {...}
  1374  }
  1375  ```
  1376  
  1377  Result (both emails exist and are attached to different nodes):
  1378  ```json
  1379  {
  1380    "data": {
  1381      "q1": [
  1382        {
  1383          "uid": "0x2"
  1384        }
  1385      ],
  1386      "q2": [
  1387        {
  1388          "uid": "0x3"
  1389        }
  1390      ],
  1391      "q3": [],
  1392      "code": "Success",
  1393      "message": "Done",
  1394      "uids": {
  1395        "user": "0x4"
  1396      }
  1397    },
  1398    "extensions": {...}
  1399  }
  1400  ```
  1401  
  1402  Result (when both emails exist and are already attached to the same node):
  1403  
  1404  ```json
  1405  {
  1406    "data": {
  1407      "q1": [],
  1408      "q2": [],
  1409      "q3": [
  1410        {
  1411          "uid": "0x4"
  1412        }
  1413      ],
  1414      "code": "Success",
  1415      "message": "Done",
  1416      "uids": {}
  1417    },
  1418    "extensions": {...}
  1419  }
  1420  ```
  1421  
  1422  We can achieve the same result using `json` dataset as follows:
  1423  
  1424  ```sh
  1425  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '{
  1426    "query": "{q1(func: eq(email, \"user_email1@company1.io\")) @filter(not(eq(email, \"user_email2@company1.io\"))) {u1 as uid} \n q2(func: eq(email, \"user_email2@company1.io\")) @filter(not(eq(email, \"user_email1@company1.io\"))) {u2 as uid} \n q3(func: eq(email, \"user_email1@company1.io\")) @filter(eq(email, \"user_email2@company1.io\")) {u3 as uid}}",
  1427    "mutations": [
  1428      {
  1429        "cond": "@if(eq(len(u1), 0) AND eq(len(u2), 0) AND eq(len(u3), 0))",
  1430        "set": [
  1431          {
  1432            "uid": "_:user",
  1433            "name": "user",
  1434            "dgraph.type": "Person"
  1435          },
  1436          {
  1437            "uid": "_:user",
  1438            "email": "user_email1@company1.io",
  1439            "dgraph.type": "Person"
  1440          },
  1441          {
  1442            "uid": "_:user",
  1443            "email": "user_email2@company1.io",
  1444            "dgraph.type": "Person"
  1445          }
  1446        ]
  1447      },
  1448      {
  1449        "cond": "@if(eq(len(u1), 1) AND eq(len(u2), 0) AND eq(len(u3), 0))",
  1450        "set": [
  1451          {
  1452            "uid": "uid(u1)",
  1453            "email": "user_email2@company1.io",
  1454            "dgraph.type": "Person"
  1455          }
  1456        ]
  1457      },
  1458      {
  1459        "cond": "@if(eq(len(u1), 1) AND eq(len(u2), 0) AND eq(len(u3), 0))",
  1460        "set": [
  1461          {
  1462            "uid": "uid(u2)",
  1463            "email": "user_email1@company1.io",
  1464            "dgraph.type": "Person"
  1465          }
  1466        ]
  1467      },
  1468      {
  1469        "cond": "@if(eq(len(u1), 1) AND eq(len(u2), 1) AND eq(len(u3), 0))",
  1470        "set": [
  1471          {
  1472            "uid": "_:user",
  1473            "name": "user",
  1474            "dgraph.type": "Person"
  1475          },
  1476          {
  1477            "uid": "_:user",
  1478            "email": "user_email1@company1.io",
  1479            "dgraph.type": "Person"
  1480          },
  1481          {
  1482            "uid": "_:user",
  1483            "email": "user_email2@company1.io",
  1484            "dgraph.type": "Person"
  1485          }
  1486        ],
  1487        "delete": [
  1488          {
  1489            "uid": "uid(u1)",
  1490            "name": null,
  1491            "email": null
  1492          },
  1493          {
  1494            "uid": "uid(u2)",
  1495            "name": null,
  1496            "email": null
  1497          }
  1498        ]
  1499      }
  1500    ]
  1501  }' | jq
  1502  ```