Solved

[FDM] How to create array of instance relationships via REST API?

  • 31 July 2023
  • 5 replies
  • 73 views

Badge +5

Hello, I am trying to create a row instance in my data model that references multiple other types, via the REST API.

I can do that fine with single relatioships, but when I get the Error

Cannot ingest into a connection property: supportingCast in view 'Film:Actor/xxxxxxxxxxx'.

when I try an array of types like this:

{
"externalId": "Oppenheimer",
"space": "imdb",
"lead": {
"externalId": "CillianMurphy",
"space": "imdb"
},
"supportingCast": [
{
"externalId": "EmilyBlunt",
"space": "imdb"
},
{
"externalId": "RobertDowneyJr",
"space": "imdb"
}
]
}

The supportingCast property is the problem is this case.

icon

Best answer by Jason Dressel 31 July 2023, 23:25

View original

5 replies

Userlevel 4
Badge

@Lucas Carvalho de Sousa,

Can you kindly share the model you are working to create instances for please 😀 and the full POST request?

I believe that supportingCast is of type [Actor].  I believe in the above, you are creating ‘"instanceType": "node"’.  With nodes, you can create direct relationships at the same time (lead), but to create the supportingCast, you need to create "instanceType": "edge" in a separate REST call. 
-Jason

Badge +5

@Jason Dressel,

I’m sorry I can’t share my actual model and POST request due to security reasons, this example was used just to show my intentions, which I believe you have understood.

The “supportingCast” equivalent in my data model is of an array type like “[Actor]” as you mentioned.

I am using the endpoint

/models/instances

building an object like this:

{
"instanceType": "node",
"space": my_space,
"externalId": external_id,
"sources": [
{
"source": {
"type": "view",
"space": my_space,
"externalId": entity,
"version": version,
},
"properties": properties,
}
],
}

Where the properties are the values of the original post object.

So, how should I build the post body of the request to create these “edge” relationships?

Userlevel 4
Badge

@Lucas Carvalho de Sousa ,
Ok, I get your point 😀.

Given the following model and using Movie as the example:

type PersonType @view(space: "imdb", version: "1") {
typename: String!
people: [Person] @relation(type:{space:"imdb", externalId: "Person.people"}, direction: INWARDS)
}

interface Person @view(space: "imdb", version: "1") {
personType: PersonType
name: String!
age: Int
}

type Actor implements Person @view(space: "imdb", version: "1") {
personType: PersonType
name: String!
age: Int
wonOscar: Boolean
hasDirected: Boolean
movies: [Movie] @relation(type:{space:"imdb", externalId: "Movie.actors"}, direction: INWARDS)
}

type Director implements Person @view(space: "imdb", version: "1") {
personType: PersonType
name: String!
age: Int
wonOscar: Boolean
directed: [Movie] @relation(type:{space:"imdb", externalId: "Movie.director"}, direction: INWARDS)
}

type Movie @view(space: "imdb", version: "1") {
name: String!
description: String
watchedIt: Boolean
imdbRating: Float
releasedYear: Int
gross: Int
runTime: Int
director: Director
actors: [Actor] @relation(edgeSource: "ActedIn" type: {space: "imdb", externalId: "Movie.actors"}, direction: OUTWARDS)
}

type ActedIn @edge @view(space: "imdb", version: "1"){
roleCode: String
salary: Float
}

I can create a Movie node instance per the following:
{{baseUrl}}/models/instances

{
"items": [
{
"instanceType": "node",
"space": "imdb",
"externalId": "movie-Oppenheimer",
"existingVersion": "1",
"sources": [
{
"source": {
"type": "view",
"space": "imdb",
"externalId": "Movie",
"version": "1"
},
"properties": {
"name": "Oppenheimer",
"watchedIt": false,
"director": {
"space": "imdb",
"externalId": "Christopher Nolan"
}
}
}
]
}
],
"autoCreateDirectRelations": false,
"autoCreateStartNodes": false,
"autoCreateEndNodes": false,
"skipOnVersionConflict": false,
"replace": false
}

I can create Actor edges via the following (you can create many per request (1000 is the limit).  I just have 1 item in this example.  Create other items for actors in the same movie or another item for another movie.actors edge.  Each edge will have a unique externalId.

{
"items": [
{
"instanceType": "edge",
"space": "imdb",
"externalId": "movie-actors-Oppenheimer-Emily Blunt",
"existingVersion": "1",
"type": {
"space": "imdb",
"externalId": "Movie.actors"
},
"startNode": {
"space": "imdb",
"externalId": "movie-Oppenheimer"
},
"endNode": {
"space": "imdb",
"externalId": "Emily Blunt"
}
}
],
"autoCreateDirectRelations": true,
"autoCreateStartNodes": false,
"autoCreateEndNodes": false,
"skipOnVersionConflict": false,
"replace": false
}

Hope this helps,
Jason

Badge +5

Hello @Jason Dressel,

This was exaclty what I needed, thank you very much!

 

Worked perfectly!

 

I’ll just note here for anyone looking for a solution to this, you don’t need to explicitly declare the relationship directives, in this case:

@relation(edgeSource: "ActedIn" type: {space: "imdb", externalId: "Movie.actors"}, direction: OUTWARDS)

All relationships create these automatically (implicilty), you can just refer to your relationship with the externalId following the pattern: “[ViewName].[PropertyName]” and it should work.

 

I’ll mark this question as answered, but just as curiosity, what is the purpose of these properties:

  • autoCreateStartNodes
  • autoCreateEndNodes

I could/how would I use them to make this easier?

Userlevel 4
Badge

@Lucas Carvalho de Sousa 
Glad to help!

autoCreateStart|End will help if you created edges before the nodes exist. This will auto create missing nodes for you.  You’d still need to populate those nodes with properties, but those nodes would pre-exist with the externalIds you specified during edge creation.

-Jason

Reply