Insert

Insert new data with e.insert.

  1. e.insert(e.Movie, {
  2. title: e.str("Spider-Man: No Way Home"),
  3. release_year: e.int64(2021)
  4. });

For convenience, the second argument of e.insert function can also accept plain JS data.

  1. e.insert(e.Movie, {
  2. title: "Spider-Man: No Way Home",
  3. actors: e.select(e.Person, person => ({
  4. filter: e.op(person.name, "=", "Robert Downey Jr."),
  5. '@character_name': e.str("Iron Man")
  6. }))
  7. });

As in EdgeQL, link properties are inserted inside the shape of a subquery.

  1. const query = e.insert(e.Movie, {
  2. title: "Iron Man",
  3. actors: e.select(e.Person, person => ({
  4. filter: e.op(person.name, '=', "Robert Downey Jr."),
  5. "@character_name": e.str("Tony Stark")
  6. // link props must correspond to expressions
  7. "@character_name": "Tony Stark" // invalid
  8. ))
  9. });

For technical reasons, link properties must correspond to query builder expressions, not plain JS data.

Similarly you can directly include link properties inside nested e.insert queries:

  1. const query = e.insert(e.Movie, {
  2. title: "Iron Man",
  3. release_year: 2008,
  4. actors: e.insert(e.Person, {
  5. name: "Robert Downey Jr.",
  6. "@character_name": e.str("Tony Start")
  7. }),
  8. });

Handling conflicts

In EdgeQL, “upsert” functionality is achieved by handling conflicts on insert statements with the unless conflict clause. In the query builder, this is possible with the .unlessConflict method (available only on insert expressions).

In the simplest case, adding .unlessConflict (no arguments) will prevent EdgeDB from throwing an error if the insertion would violate an exclusivity contstraint. Instead, the query returns an empty set (null).

  1. e.insert(e.Movie, {
  2. title: "Spider-Man: No Way Home",
  3. release_year: 2021
  4. }).unlessConflict();
  5. // => null

Provide an on clause to “catch” conflicts only on a specific property/link.

  1. e.insert(e.Movie, {
  2. title: "Spider-Man: No Way Home",
  3. release_year: 2021
  4. }).unlessConflict(movie => ({
  5. on: movie.title, // can be any expression
  6. }));

You can also provide an else expression which will be executed and returned in case of a conflict. You must specify an on clause in order to use else.

The following query simply returns the pre-existing (conflicting) object.

  1. e.insert(e.Movie, {
  2. title: "Spider-Man: Homecoming",
  3. release_year: 2021
  4. }).unlessConflict(movie => ({
  5. on: movie.title,
  6. else: movie
  7. }));

Or you can perform an upsert operation with an e.update in the else.

  1. e.insert(e.Movie, {
  2. title: "Spider-Man: Homecoming",
  3. release_year: 2021
  4. }).unlessConflict(movie => ({
  5. on: movie.title,
  6. else: e.update(movie, () => ({
  7. set: {
  8. release_year: 2021
  9. }
  10. })),
  11. }));

Bulk inserts

It’s common to use for loops to perform bulk inserts. The raw data is passed in as a json parameter, converted to a set of json objects with json_array_unpack, then passed into a for loop for insertion.

  1. const query = e.params({items: e.json}, (params) => {
  2. return e.for(e.json_array_unpack(params.items), (item) => {
  3. return e.insert(e.Movie, {
  4. title: e.cast(e.str, item.title),
  5. release_year: e.cast(e.int64, item.release_year),
  6. });
  7. });
  8. });
  9. const result = await query.run(client, {
  10. items: [
  11. {title: 'Deadpool', release_year: 2016},
  12. {title: 'Deadpool 2', release_year: 2018},
  13. {title: 'Deadpool 3', release_year: null},
  14. ]
  15. });