github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/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  ```
    30  Represents that graph node with ID `0x01` has a `name` with string value `"Alice"`.  While triple
    31  ```
    32  <0x01> <friend> <0x02> .
    33  ```
    34  Represents that graph node with ID `0x01` is linked with the `friend` edge to node `0x02`.
    35  
    36  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.
    37  
    38  
    39  ## Blank Nodes and UID
    40  
    41  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:
    42  
    43  ```
    44  {
    45   set {
    46      _:class <student> _:x .
    47      _:class <student> _:y .
    48      _:class <name> "awesome class" .
    49      _:x <name> "Alice" .
    50      _:x <planet> "Mars" .
    51      _:x <friend> _:y .
    52      _:y <name> "Bob" .
    53   }
    54  }
    55  ```
    56  results in output (the actual UIDs will be different on any run of this mutation)
    57  ```
    58  {
    59    "data": {
    60      "code": "Success",
    61      "message": "Done",
    62      "uids": {
    63        "class": "0x2712",
    64        "x": "0x2713",
    65        "y": "0x2714"
    66      }
    67    }
    68  }
    69  ```
    70  The graph has thus been updated as if it had stored the triples
    71  ```
    72  <0x6bc818dc89e78754> <student> <0xc3bcc578868b719d> .
    73  <0x6bc818dc89e78754> <student> <0xb294fb8464357b0a> .
    74  <0x6bc818dc89e78754> <name> "awesome class" .
    75  <0xc3bcc578868b719d> <name> "Alice" .
    76  <0xc3bcc578868b719d> <planet> "Mars" .
    77  <0xc3bcc578868b719d> <friend> <0xb294fb8464357b0a> .
    78  <0xb294fb8464357b0a> <name> "Bob" .
    79  ```
    80  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.
    81  
    82  A later mutation can update the data for existing UIDs.  For example, the following to add a new student to the class.
    83  ```
    84  {
    85   set {
    86      <0x6bc818dc89e78754> <student> _:x .
    87      _:x <name> "Chris" .
    88   }
    89  }
    90  ```
    91  
    92  A query can also directly use UID.
    93  ```
    94  {
    95   class(func: uid(0x6bc818dc89e78754)) {
    96    name
    97    student {
    98     name
    99     planet
   100     friend {
   101      name
   102     }
   103    }
   104   }
   105  }
   106  ```
   107  
   108  ## External IDs
   109  
   110  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:
   111  
   112  ```
   113  _:userA <http://schema.org/type> <http://schema.org/Person> .
   114  _:userA <http://schema.org/name> "FirstName LastName" .
   115  <https://www.themoviedb.org/person/32-robin-wright> <http://schema.org/type> <http://schema.org/Person> .
   116  <https://www.themoviedb.org/person/32-robin-wright> <http://schema.org/name> "Robin Wright" .
   117  ```
   118  
   119  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
   120  
   121  ```
   122  <0x123> <xid> "http://schema.org/Person" .
   123  ```
   124  
   125  While Robin Wright might get UID `0x321` and triples
   126  
   127  ```
   128  <0x321> <xid> "https://www.themoviedb.org/person/32-robin-wright" .
   129  <0x321> <http://schema.org/type> <0x123> .
   130  <0x321> <http://schema.org/name> "Robin Wright" .
   131  ```
   132  
   133  An appropriate schema might be as follows.
   134  ```
   135  xid: string @index(exact) .
   136  <http://schema.org/type>: [uid] @reverse .
   137  ```
   138  
   139  Query Example: All people.
   140  
   141  ```
   142  {
   143    var(func: eq(xid, "http://schema.org/Person")) {
   144      allPeople as <~http://schema.org/type>
   145    }
   146  
   147    q(func: uid(allPeople)) {
   148      <http://schema.org/name>
   149    }
   150  }
   151  ```
   152  
   153  Query Example: Robin Wright by external ID.
   154  
   155  ```
   156  {
   157    robin(func: eq(xid, "https://www.themoviedb.org/person/32-robin-wright")) {
   158      expand(_all_) { expand(_all_) }
   159    }
   160  }
   161  
   162  ```
   163  
   164  {{% 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 %}}
   165  
   166  ## External IDs and Upsert Block
   167  
   168  The upsert block makes managing external IDs easy.
   169  
   170  Set the schema.
   171  ```
   172  xid: string @index(exact) .
   173  <http://schema.org/name>: string @index(exact) .
   174  <http://schema.org/type>: [uid] @reverse .
   175  ```
   176  
   177  Set the type first of all.
   178  ```
   179  {
   180    set {
   181      _:blank <xid> "http://schema.org/Person" .
   182    }
   183  }
   184  ```
   185  
   186  Now you can create a new person and attach its type using the upsert block.
   187  ```
   188     upsert {
   189        query {
   190          var(func: eq(xid, "http://schema.org/Person")) {
   191            Type as uid
   192          }
   193          var(func: eq(<http://schema.org/name>, "Robin Wright")) {
   194            Person as uid
   195          }
   196        }
   197        mutation {
   198            set {
   199             uid(Person) <xid> "https://www.themoviedb.org/person/32-robin-wright" .
   200             uid(Person) <http://schema.org/type> uid(Type) .
   201             uid(Person) <http://schema.org/name> "Robin Wright" .
   202            }
   203        }
   204      }
   205  ```
   206  
   207  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.
   208  
   209  ```
   210     upsert {
   211        query {
   212          var(func: eq(xid, "http://schema.org/Person")) {
   213            Type as uid
   214          }
   215          var(func: eq(<http://schema.org/name>, "Robin Wright")) {
   216            Person as uid
   217          }
   218        }
   219        mutation {
   220            delete {
   221             uid(Person) <xid> "https://www.themoviedb.org/person/32-robin-wright" .
   222             uid(Person) <http://schema.org/type> uid(Type) .
   223             uid(Person) <http://schema.org/name> "Robin Wright" .
   224            }
   225        }
   226      }
   227  ```
   228  
   229  Query by user.
   230  ```
   231  {
   232    q(func: eq(<http://schema.org/name>, "Robin Wright")) {
   233      uid
   234      xid
   235      <http://schema.org/name>
   236      <http://schema.org/type> {
   237        uid
   238        xid
   239      }
   240    }
   241  }
   242  ```
   243  
   244  ## Language and RDF Types
   245  
   246  RDF N-Quad allows specifying a language for string values and an RDF type.  Languages are written using `@lang`. For example
   247  ```
   248  <0x01> <name> "Adelaide"@en .
   249  <0x01> <name> "Аделаида"@ru .
   250  <0x01> <name> "Adélaïde"@fr .
   251  ```
   252  See also [how language strings are handled in queries]({{< relref "query-language/index.md#language-support" >}}).
   253  
   254  RDF types are attached to literals with the standard `^^` separator.  For example
   255  ```
   256  <0x01> <age> "32"^^<xs:int> .
   257  <0x01> <birthdate> "1985-06-08"^^<xs:dateTime> .
   258  ```
   259  
   260  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.
   261  
   262  | Storage Type                                            | Dgraph type    |
   263  | -------------                                           | :------------: |
   264  | &#60;xs:string&#62;                                     | `string`         |
   265  | &#60;xs:dateTime&#62;                                   | `dateTime`       |
   266  | &#60;xs:date&#62;                                       | `datetime`       |
   267  | &#60;xs:int&#62;                                        | `int`            |
   268  | &#60;xs:boolean&#62;                                    | `bool`           |
   269  | &#60;xs:double&#62;                                     | `float`          |
   270  | &#60;xs:float&#62;                                      | `float`          |
   271  | &#60;geo:geojson&#62;                                   | `geo`            |
   272  | &#60;xs:password&#62;                                   | `password`       |
   273  | &#60;http&#58;//www.w3.org/2001/XMLSchema#string&#62;   | `string`         |
   274  | &#60;http&#58;//www.w3.org/2001/XMLSchema#dateTime&#62; | `dateTime`       |
   275  | &#60;http&#58;//www.w3.org/2001/XMLSchema#date&#62;     | `dateTime`       |
   276  | &#60;http&#58;//www.w3.org/2001/XMLSchema#int&#62;      | `int`            |
   277  | &#60;http&#58;//www.w3.org/2001/XMLSchema#boolean&#62;  | `bool`           |
   278  | &#60;http&#58;//www.w3.org/2001/XMLSchema#double&#62;   | `float`          |
   279  | &#60;http&#58;//www.w3.org/2001/XMLSchema#float&#62;    | `float`          |
   280  
   281  
   282  See the section on [RDF schema types]({{< relref "#rdf-types" >}}) to understand how RDF types affect mutations and storage.
   283  
   284  
   285  ## Batch mutations
   286  
   287  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.
   288  
   289  `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.
   290  
   291  ```
   292  dgraph live --help
   293  ```
   294  See also [Fast Data Loading](/deploy#fast-data-loading).
   295  
   296  ## Delete
   297  
   298  A delete mutation, signified with the `delete` keyword, removes triples from the store.
   299  
   300  For example, if the store contained
   301  ```
   302  <0xf11168064b01135b> <name> "Lewis Carrol"
   303  <0xf11168064b01135b> <died> "1998"
   304  ```
   305  
   306  Then delete mutation
   307  
   308  ```
   309  {
   310    delete {
   311       <0xf11168064b01135b> <died> "1998" .
   312    }
   313  }
   314  ```
   315  
   316  Deletes the erroneous data and removes it from indexes if present.
   317  
   318  For a particular node `N`, all data for predicate `P` (and corresponding indexing) is removed with the pattern `S P *`.
   319  
   320  ```
   321  {
   322    delete {
   323       <0xf11168064b01135b> <author.of> * .
   324    }
   325  }
   326  ```
   327  
   328  The pattern `S * *` deletes all known edges out of a node (the node itself may
   329  remain as the target of edges), any reverse edges corresponding to the removed
   330  edges and any indexing for the removed data. The predicates to delete are
   331  derived from the type information for that node (the value of the `dgraph.type`
   332  edges on that node and their corresponding definitions in the schema). If that
   333  information is missing, this operation will be a no-op.
   334  
   335  ```
   336  {
   337    delete {
   338       <0xf11168064b01135b> * * .
   339    }
   340  }
   341  ```
   342  
   343  
   344  {{% notice "note" %}} The patterns `* P O` and `* * O` are not supported since its expensive to store/find all the incoming edges. {{% /notice %}}
   345  
   346  ### Deletion of non-list predicates
   347  
   348  Deleting the value of a non-list predicate (i.e a 1-to-1 relation) can be done in two ways.
   349  
   350  1. Using the star notation mentioned in the last section.
   351  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.
   352  
   353  For language-tagged values, the following special syntax is supported:
   354  
   355  ```
   356  {
   357  	delete {
   358  		<0x12345> <name@es> * .
   359  	}
   360  }
   361  ```
   362  
   363  In this example, the value of name tagged with language tag `es` will be deleted.
   364  Other tagged values are left untouched.
   365  
   366  ## Mutations using cURL
   367  
   368  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.
   369  
   370  To run a `set` mutation:
   371  
   372  ```sh
   373  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   374  {
   375    set {
   376      _:alice <name> "Alice" .
   377    }
   378  }'
   379  ```
   380  
   381  To run a `delete` mutation:
   382  
   383  ```sh
   384  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   385  {
   386    delete {
   387      # Example: The UID of Alice is 0x56f33
   388      <0x56f33> <name> * .
   389    }
   390  }'
   391  ```
   392  
   393  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.
   394  
   395  ```sh
   396  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true --data-binary @mutation.txt
   397  ```
   398  
   399  ## JSON Mutation Format
   400  
   401  Mutations can also be specified using JSON objects. This can allow mutations to
   402  be expressed in a more natural way. It also eliminates the need for apps to
   403  have custom serialisation code, since most languages already have a JSON
   404  marshalling library.
   405  
   406  When Dgraph receives a mutation as a JSON object, it first converts in into
   407  multiple RDFs that are then processed as normal.
   408  
   409  Each JSON object represents a single node in the graph.
   410  
   411  {{% notice "note" %}}
   412  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" >}})
   413  {{% /notice %}}
   414  
   415  ### Setting literal values
   416  
   417  When setting new values, the `set_json` field in the `Mutation` message should
   418  contain a JSON object.
   419  
   420  Literal values can be set by adding a key/value to the JSON object. The key
   421  represents the predicate, and the value represents the object.
   422  
   423  For example:
   424  ```json
   425  {
   426    "name": "diggy",
   427    "food": "pizza"
   428  }
   429  ```
   430  Will be converted into the RDFs:
   431  ```
   432  _:blank-0 <name> "diggy" .
   433  _:blank-0 <food> "pizza" .
   434  ```
   435  
   436  The result of the mutation would also contain a map, which would have the uid assigned corresponding
   437  to the key `blank-0`. You could specify your own key like
   438  
   439  ```json
   440  {
   441    "uid": "_:diggy",
   442    "name": "diggy",
   443    "food": "pizza"
   444  }
   445  ```
   446  
   447  In this case, the assigned uids map would have a key called `diggy` with the value being the uid
   448  assigned to it.
   449  
   450  ### Language support
   451  
   452  An important difference between RDF and JSON mutations is in regards to specifying a string value's
   453  language. In JSON, the language tag is appended to the edge _name_, not the value like in RDF.
   454  
   455  For example, the JSON mutation
   456  ```json
   457  {
   458    "food": "taco",
   459    "rating@en": "tastes good",
   460    "rating@es": "sabe bien",
   461    "rating@fr": "c'est bon",
   462    "rating@it": "è buono"
   463  }
   464  ```
   465  
   466  is equivalent to the following RDF:
   467  ```
   468  _:blank-0 <food> "taco" .
   469  _:blank-0 <rating> "tastes good"@en .
   470  _:blank-0 <rating> "sabe bien"@es .
   471  _:blank-0 <rating> "c'est bon"@fr .
   472  _:blank-0 <rating> "è buono"@it .
   473  ```
   474  
   475  ### Geolocation support
   476  
   477  Support for geolocation data is available in JSON. Geo-location data is entered
   478  as a JSON object with keys "type" and "coordinates". Keep in mind we only
   479  support indexing on the Point, Polygon, and MultiPolygon types, but we can store
   480  other types of geolocation data. Below is an example:
   481  
   482  ```
   483  {
   484    "food": "taco",
   485    location: {
   486      "type": "Point",
   487      "coordinates": [1.0, 2.0]
   488    }
   489  }
   490  ```
   491  
   492  ### Referencing existing nodes
   493  
   494  If a JSON object contains a field named `"uid"`, then that field is interpreted
   495  as the UID of an existing node in the graph. This mechanism allows you to
   496  reference existing nodes.
   497  
   498  For example:
   499  ```json
   500  {
   501    "uid": "0x467ba0",
   502    "food": "taco",
   503    "rating": "tastes good",
   504  }
   505  ```
   506  Will be converted into the RDFs:
   507  ```
   508  <0x467ba0> <food> "taco" .
   509  <0x467ba0> <rating> "tastes good" .
   510  ```
   511  
   512  ### Edges between nodes
   513  
   514  Edges between nodes are represented in a similar way to literal values, except
   515  that the object is a JSON object.
   516  
   517  For example:
   518  ```json
   519  {
   520    "name": "Alice",
   521    "friend": {
   522      "name": "Betty"
   523    }
   524  }
   525  ```
   526  Will be converted into the RDFs:
   527  ```
   528  _:blank-0 <name> "Alice" .
   529  _:blank-0 <friend> _:blank-1 .
   530  _:blank-1 <name> "Betty" .
   531  ```
   532  
   533  The result of the mutation would contain the uids assigned to `blank-0` and `blank-1` nodes. If you
   534  wanted to return these uids under a different key, you could specify the `uid` field as a blank
   535  node.
   536  
   537  ```json
   538  {
   539    "uid": "_:alice",
   540    "name": "Alice",
   541    "friend": {
   542      "uid": "_:bob",
   543      "name": "Betty"
   544    }
   545  }
   546  ```
   547  Will be converted to:
   548  ```
   549  _:alice <name> "Alice" .
   550  _:alice <friend> _:bob .
   551  _:bob <name> "Betty" .
   552  ```
   553  
   554  Existing nodes can be referenced in the same way as when adding literal values.
   555  E.g. to link two existing nodes:
   556  ```json
   557  {
   558    "uid": "0x123",
   559    "link": {
   560      "uid": "0x456"
   561    }
   562  }
   563  ```
   564  
   565  Will be converted to:
   566  
   567  ```JSON
   568  <0x123> <link> <0x456> .
   569  ```
   570  
   571  {{% notice "note" %}}
   572  A common mistake is to attempt to use `{"uid":"0x123","link":"0x456"}`.  This
   573  will result in an error. Dgraph interprets this JSON object as setting the
   574  `link` predicate to the string`"0x456"`, which is usually not intended.  {{%
   575  /notice %}}
   576  
   577  ### Deleting literal values
   578  
   579  Deletion mutations can also be sent in JSON format. To send a delete mutation,
   580  use the `delete_json` field instead of the `set_json` field in the `Mutation`
   581  message.
   582  
   583  {{% 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 %}}
   584  
   585  When using delete mutations, an existing node always has to be referenced. So
   586  the `"uid"` field for each JSON object must be present. Predicates that should
   587  be deleted should be set to the JSON value `null`.
   588  
   589  For example, to remove a food rating:
   590  ```json
   591  {
   592    "uid": "0x467ba0",
   593    "rating": null
   594  }
   595  ```
   596  
   597  ### Deleting edges
   598  
   599  Deleting a single edge requires the same JSON object that would create that
   600  edge. E.g. to delete the predicate `link` from `"0x123"` to `"0x456"`:
   601  ```json
   602  {
   603    "uid": "0x123",
   604    "link": {
   605      "uid": "0x456"
   606    }
   607  }
   608  ```
   609  
   610  All edges for a predicate emanating from a single node can be deleted at once
   611  (corresponding to deleting `S P *`):
   612  ```json
   613  {
   614    "uid": "0x123",
   615    "link": null
   616  }
   617  ```
   618  
   619  If no predicates are specified, then all of the node's known outbound edges (to
   620  other nodes and to literal values) are deleted (corresponding to deleting `S *
   621  *`). The predicates to delete are derived using the type system. Refer to the
   622  [RDF format]({{< relref "#delete" >}}) documentation and the section on the
   623  [type system]({{< relref "query-language/index.md#type-system" >}}) for more
   624  information:
   625  
   626  ```json
   627  {
   628    "uid": "0x123"
   629  }
   630  ```
   631  
   632  ### Facets
   633  
   634  Facets can be created by using the `|` character to separate the predicate
   635  and facet key in a JSON object field name. This is the same encoding schema
   636  used to show facets in query results. E.g.
   637  ```json
   638  {
   639    "name": "Carol",
   640    "name|initial": "C",
   641    "friend": {
   642      "name": "Daryl",
   643      "friend|close": "yes"
   644    }
   645  }
   646  ```
   647  Produces the following RDFs:
   648  ```
   649  _:blank-0 <name> "Carol" (initial=C) .
   650  _:blank-0 <friend> _:blank-1 (close=yes) .
   651  _:blank-1 <name> "Daryl" .
   652  ```
   653  
   654  ### Creating a list with JSON and interacting with
   655  
   656  Schema:
   657  
   658  ```JSON
   659  testList: [string] .
   660  ```
   661  
   662  ```JSON
   663  {
   664    "testList": [
   665      "Grape",
   666      "Apple",
   667      "Strawberry",
   668      "Banana",
   669      "watermelon"
   670    ]
   671  }
   672  ```
   673  
   674  Let’s then remove "Apple" from this list (Remember, it’s case sensitive):
   675  
   676  ```JSON
   677  {
   678     "uid": "0xd", #UID of the list.
   679     "testList": "Apple"
   680  }
   681  ```
   682  
   683  {{% 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 %}}
   684  
   685  
   686  Add another fruit:
   687  
   688  ```JSON
   689  {
   690     "uid": "0xd", #UID of the list.
   691     "testList": "Pineapple"
   692  }
   693  ```
   694  
   695  ### Specifying multiple operations
   696  
   697  When specifying add or delete mutations, multiple nodes can be specified
   698  at the same time using JSON arrays.
   699  
   700  For example, the following JSON object can be used to add two new nodes, each
   701  with a `name`:
   702  
   703  ```JSON
   704  [
   705    {
   706      "name": "Edward"
   707    },
   708    {
   709      "name": "Fredric"
   710    }
   711  ]
   712  ```
   713  
   714  ### JSON Syntax using Raw HTTP or Ratel UI
   715  
   716  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.
   717  
   718  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/).
   719  
   720  Mutate:
   721  ```JSON
   722  {
   723    "set": [
   724      {
   725        # One JSON obj in here
   726      },
   727      {
   728        # Another JSON obj in here for multiple operations
   729      }
   730    ]
   731  }
   732  ```
   733  
   734  Delete:
   735  
   736  Deletion operations are the same as [Deleting literal values]({{< relref "#deleting-literal-values">}}) and [Deleting edges]({{< relref "#deleting-edges">}}).
   737  
   738  ```JSON
   739  {
   740    "delete": [
   741      {
   742        # One JSON obj in here
   743      },
   744      {
   745        # Another JSON obj in here for multiple operations
   746      }
   747    ]
   748  }
   749  ```
   750  
   751  ### Using JSON operations via cURL
   752  
   753  First you have to configure the HTTP header to specify content-type.
   754  
   755  ```sh
   756  -H 'Content-Type: application/json'
   757  ```
   758  
   759  {{% notice "note" %}}
   760  In order to use `jq` for JSON formatting you need the `jq` package. See the
   761  [`jq` downloads](https://stedolan.github.io/jq/download/) page for installation
   762  details. You can also use Python's built in `json.tool` module with `python -m
   763  json.tool` to do JSON formatting.
   764  {{% /notice %}}
   765  
   766  ```sh
   767  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'
   768      {
   769        "set": [
   770          {
   771            "name": "Alice"
   772          },
   773          {
   774            "name": "Bob"
   775          }
   776        ]
   777      }' | jq
   778  
   779  ```
   780  
   781  To delete:
   782  
   783  ```sh
   784  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'
   785      {
   786        "delete": [
   787          {
   788            "uid": "0xa"
   789          }
   790        ]
   791      }' | jq
   792  ```
   793  
   794  Mutation with a JSON file:
   795  
   796  ```sh
   797  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d @data.json
   798  ```
   799  
   800  where the contents of data.json looks like the following:
   801  
   802  ```json
   803  {
   804    "set": [
   805      {
   806        "name": "Alice"
   807      },
   808      {
   809        "name": "Bob"
   810      }
   811    ]
   812  }
   813  ```
   814  
   815  The JSON file must follow the same format for mutations over HTTP: a single JSON
   816  object with the `"set"` or `"delete"` key and an array of JSON objects for the
   817  mutation. If you already have a file with an array of data, you can use `jq` to
   818  transform your data to the proper format. For example, if your data.json file
   819  looks like this:
   820  
   821  ```json
   822  [
   823    {
   824      "name": "Alice"
   825    },
   826    {
   827      "name": "Bob"
   828    }
   829  ]
   830  ```
   831  
   832  then you can transform your data to the proper format with the following `jq`
   833  command, where the `.` in the `jq` string represents the contents of data.json:
   834  
   835  ```sh
   836  cat data.json | jq '{set: .}'
   837  ```
   838  
   839  ```
   840  {
   841    "set": [
   842      {
   843        "name": "Alice"
   844      },
   845      {
   846        "name": "Bob"
   847      }
   848    ]
   849  }
   850  ```
   851  
   852  ## Upsert Block
   853  
   854  The upsert block allows performing queries and mutations in a single request. The upsert
   855  block contains one query block and one mutation block. Variables defined in the query
   856  block can be used in the mutation block using the `uid` function.
   857  Support for `val` function is coming soon.
   858  
   859  In general, the structure of the upsert block is as follows:
   860  
   861  ```
   862  upsert {
   863    query <query block>
   864    [fragment <fragment block>]
   865    mutation <mutation block>
   866  }
   867  ```
   868  
   869  The Mutation block currently only allows the `uid` function, which allows extracting UIDs
   870  from variables defined in the query block. There are two possible outcomes based on the
   871  results of executing the query block:
   872  
   873  * 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.
   874  * 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.
   875  
   876  ### Example
   877  
   878  Consider an example with the following schema:
   879  
   880  ```sh
   881  curl localhost:8080/alter -X POST -d $'
   882    name: string @index(term) .
   883    email: string @index(exact, trigram) @upsert .
   884    age: int @index(int) .
   885  ' | jq
   886  ```
   887  
   888  Now, let's say we want to create a new user with `email` and `name` information.
   889  We also want to make sure that one email has exactly one corresponding user in
   890  the database. To achieve this, we need to first query whether a user exists
   891  in the database with the given email. If a user exists, we use its UID
   892  to update the `name` information. If the user doesn't exist, we create
   893  a new user and update the `email` and `name` information.
   894  
   895  We can do this using the upsert block as follows:
   896  
   897  ```sh
   898  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   899  upsert {
   900    query {
   901      v as var(func: eq(email, "user@company1.io"))
   902    }
   903  
   904    mutation {
   905      set {
   906        uid(v) <name> "first last" .
   907        uid(v) <email> "user@company1.io" .
   908      }
   909    }
   910  }
   911  ' | jq
   912  ```
   913  
   914  Result:
   915  
   916  ```json
   917  {
   918    "data": {
   919      "code": "Success",
   920      "message": "Done",
   921      "uids": {
   922        "uid(v)": "0x2"
   923      }
   924    },
   925    "extensions": {...}
   926  }
   927  ```
   928  
   929  The query part of the upsert block stores the UID of the user with the provided email
   930  in the variable `v`. The mutation part then extracts the UID from variable `v`, and
   931  stores the `name` and `email` information in the database. If the user exists,
   932  the information is updated. If the user doesn't exist, `uid(v)` is treated
   933  as a blank node and a new user is created as explained above.
   934  
   935  If we run the same mutation again, the data would just be overwritten, and no new uid is
   936  created. Note that the `uids` map is empty in the response when the mutation is executed again:
   937  
   938  ```json
   939  {
   940    "data": {
   941      "code": "Success",
   942      "message": "Done",
   943      "uids": {}
   944    },
   945    "extensions": {...}
   946  }
   947  ```
   948  
   949  We can achieve the same result using `json` dataset as follows:
   950  
   951  ```sh
   952  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '
   953  {
   954    "query": "{ v as var(func: eq(email, \"user@company1.io\")) }",
   955    "set": {
   956      "uid": "uid(v)",
   957      "name": "first last",
   958      "email": "user@company1.io"
   959    }
   960  }
   961  ' | jq
   962  ```
   963  
   964  Now, we want to add the `age` information for the same user having the same email
   965  `user@company1.io`. We can use the upsert block to do the same as follows:
   966  
   967  ```sh
   968  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
   969  upsert {
   970    query {
   971      v as var(func: eq(email, "user@company1.io"))
   972    }
   973  
   974    mutation {
   975      set {
   976        uid(v) <age> "28" .
   977      }
   978    }
   979  }
   980  ' | jq
   981  ```
   982  
   983  Result:
   984  
   985  ```json
   986  {
   987    "data": {
   988      "code": "Success",
   989      "message": "Done",
   990      "uids": {}
   991    },
   992    "extensions": {...}
   993  }
   994  ```
   995  
   996  Here, the query block queries for a user with `email` as `user@company1.io`. It stores
   997  the `uid` of the user in variable `v`. The mutation block then updates the `age` of the
   998  user by extracting the uid from the variable `v` using `uid` function.
   999  
  1000  We can achieve the same result using `json` dataset as follows:
  1001  
  1002  ```sh
  1003  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '
  1004  {
  1005    "query": "{ v as var(func: eq(email, \"user@company1.io\")) }",
  1006    "set":{
  1007      "uid": "uid(v)",
  1008      "age": "28"
  1009    }
  1010  }
  1011  ' | jq
  1012  ```
  1013  
  1014  If we want to execute the mutation only when the user exists, we could use
  1015  [Conditional Upsert]({{< relref "#conditional-upsert" >}}).
  1016  
  1017  ### Bulk Delete Example
  1018  
  1019  Let's say we want to delete all the users of `company1` from the database. This can be
  1020  achieved in just one query using the upsert block:
  1021  
  1022  ```sh
  1023  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
  1024  upsert {
  1025    query {
  1026      v as var(func: regexp(email, /.*@company1.io$/))
  1027    }
  1028  
  1029    mutation {
  1030      delete {
  1031        uid(v) <name> * .
  1032        uid(v) <email> * .
  1033        uid(v) <age> * .
  1034      }
  1035    }
  1036  }
  1037  ' | jq
  1038  ```
  1039  
  1040  Result:
  1041  
  1042  ```json
  1043  {
  1044    "data": {
  1045      "code": "Success",
  1046      "message": "Done",
  1047      "uids": {}
  1048    },
  1049    "extensions": {...}
  1050  }
  1051  ```
  1052  
  1053  We can achieve the same result using `json` dataset as follows:
  1054  
  1055  ```sh
  1056  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d $'{
  1057    "query": "{ v as var(func: regexp(email, /.*@company1.io$/)) }",
  1058    "delete": {
  1059      "uid": "uid(v)",
  1060      "name": null,
  1061      "email": null,
  1062      "age": null
  1063    }
  1064  }
  1065  ' | jq
  1066  ```
  1067  
  1068  ## Conditional Upsert
  1069  
  1070  The upsert block also allows specifying a conditional mutation block using an `@if`
  1071  directive. The mutation is executed only when the specified condition is true. If the
  1072  condition is false, the mutation is silently ignored. The general structure of
  1073  Conditional Upsert looks like as follows:
  1074  
  1075  ```
  1076  upsert {
  1077    query <query block>
  1078    [fragment <fragment block>]
  1079    mutation @if(<condition>) <mutation block>
  1080  }
  1081  ```
  1082  
  1083  The `@if` directive accepts a condition on variables defined in the query block and can be
  1084  connected using `AND`, `OR` and `NOT`.
  1085  
  1086  ### Example
  1087  
  1088  Let's say in our previous example, we know the `company1` has less than 100 employees.
  1089  For safety, we want the mutation to execute only when the variable `v` stores less than
  1090  100 but greater than 50 UIDs in it. This can be achieved as follows:
  1091  
  1092  ```sh
  1093  curl -H "Content-Type: application/rdf" -X POST localhost:8080/mutate?commitNow=true -d $'
  1094  upsert {
  1095    query {
  1096      v as var(func: regexp(email, /.*@company1.io$/))
  1097    }
  1098  
  1099    mutation @if(lt(len(v), 100) AND gt(len(v), 50)) {
  1100      delete {
  1101        uid(v) <name> * .
  1102        uid(v) <email> * .
  1103        uid(v) <age> * .
  1104      }
  1105    }
  1106  }
  1107  ' | jq
  1108  ```
  1109  
  1110  We can achieve the same result using `json` dataset as follows:
  1111  
  1112  ```sh
  1113  curl -H "Content-Type: application/json" -X POST localhost:8080/mutate?commitNow=true -d '{
  1114    "query": "{ v as var(func: regexp(email, /.*@company1.io$/)) }",
  1115    "cond": "@if(lt(len(v), 100) AND gt(len(v), 50))",
  1116    "delete": {
  1117      "uid": "uid(v)",
  1118      "name": null,
  1119      "email": null,
  1120      "age": null
  1121    }
  1122  }' | jq
  1123  ```