Using linked fields (aka bubbled fields) in API requests

A linked field, also known as a bubbled field, is a field that is accessed via indirection through an entity or multi-entity link. The pattern to be used when specifying such a field is as follows:

field.EntityType.field

The first field is an entity or multi-entity field on the entity type you are currently querying. The EntityType is a valid entity type for the initially specified field and the last field specified is a valid field on the linked record.

For example, if you had a Version linked to a Shot and you wanted to know which Sequence that Shot was linked to, you could do two API queries, or you could use linked field syntax:

version = sg.find('Version', [['id', 'is', 1234]], ['entity.Shot.sg_sequence'])
print version['entity.Shot.sg_sequence']

This linked field syntax can be used in field lists, like above, and can also be used in filters.

If you want to find all the Versions that “belong” to a particular Sequence you could do:

some_sequence = {'type':'Sequence', 'id':1234}
version = sg.find('Version', [['entity.Shot.sg_sequence', 'is', some_sequence]])
print version['entity.Shot.sg_sequence']

You should know, however, that you can’t use linked filter syntax in a field list if one of the links in your path is a multi-entity link. By definition, a multi-entity link you hop through would have to follow multiple paths and there’s currently no way to reflect that in a result set.

For example, in the following, it would be impossible to flow through all tasks to return multiple statuses:

shots = sg.find('Shot', [['id', 'is', 1234]], ['tasks.Task.sg_status_list'])

You can also hop through two fields or more, like:

field.EntityType.field.EntityType.field

Sometimes this can come in very handy to optimize queries or algorithms.

Let’s say you wanted to find all Task records linked to Shot records as long as you were assigned to at least one of the tasks on the Shot. You could start by finding all the tasks you’re assigned to and returning their linked Shot and then looping on those Shot records to find all tasks… Or even munging together a big filter list with all the Shot records to find all the tasks at once.

me = {'type':'HumanUser', 'id':1234}
my_tasks = sg.find('Task', [['task_assignees', 'is', me]], ['entity'])
shot_tasks = sg.find('Task', [['entity', 'in', [t['entity'] for t in my_tasks]]])

However, you could do this in a single which will save you some networking time to the Shotgun server.

me = {'type':'HumanUser', 'id':1234}
shot_tasks = sg.find('Task', [['entity.Shot.tasks.Task.task_assignees', 'is', me]])

Have fun using this syntax to help with your script development!

4 Likes