Conditionally insert an optional link property inside a for loop

69 Views Asked by At

I am using the edgedb typescript client.

Here is my simplified schema:

  type Ratings {
    property imdb -> float32;
  }

  type Movie {
    required property year -> int16;
    single link ratings -> Ratings {
      constraint exclusive;
    }
  }

As you can see, Movie.ratings is not required thus can be null.

I am trying to implement a function to insert movies using the e.for loop.

  insertMovies([
    // First movie without ratings
    {
      year: 1900,
      ratings: null,
    },
    // Second movie with ratings
    {
      year: 1900,
      ratings: {
        imdb: 9
      },
    },
  ]);

Here is my current implementation which is throwing an error

QueryError: INSERT statements cannot be used inside conditional expressions

export async function insertMovies(movies: MovieNoId[]) {
  const query = e.params({ items: e.json }, params => {
    return e.for(e.json_array_unpack(params.items), item => {
      return e
        .insert(e.Movie, {
          year: e.cast(e.int16, item.year),
          genresIds: e.cast(e.array(e.int32), item.genresIds),
          ratings: e.op(
            e.insert(e.Ratings, {
              imdb: e.cast(e.float32, item.ratings.imdb),
              metacritic: e.cast(e.float32, item.ratings.metacritic),
              rottenTomatoes: e.cast(e.float32, item.ratings.rottenTomatoes),
            }),
            "if",
            e.op("exists", item.ratings),
            "else",
            e.cast(e.Ratings.__element__, e.set()) // set null
          ),
        })
        .unlessConflict();
    });
  });

  return query.run(edgedbClient, { items: movies });
}

Here is the simple logic I would like to implement:

...
ratings: item.ratings 
  ? e.insert(e.Ratings, {
      imdb: e.cast(e.float32, item.ratings.imdb),
    }) 
  : null,
...

but this obviously doesn't work like this.

How can I insert ratings in this for loop only when it is defined?

0

There are 0 best solutions below