How to write resolvers for related attributes in API Management GraphQL NoSQL CosmosDB Resolver?

W. Alex Livesley 0 Reputation points
2024-07-07T01:25:02.6033333+00:00

I have a Cosmos NoSQL model with document types user, clip, and audioFile. I have created GraphQL resolvers to access CosmosDB. One GraphQL query (query/clip by ID) works fine until I ask for the child audioFiles (I have a clip/audioFiles resolver).

My first question, how do I write the resolver to support encapsulated attributes (clip->audioFiles) where more than one NoSQL query is required to retrieve information (one for clip and one for audioFiles)? I had assumed that the Clip-audioFiles resolver would be invoked in the query returning the clip (Query-clip) if the audioFiles property is included in the query. Resolvers are provided. What am I missing?

A second question is how to return something which is virtual (ClipsConnection) comprising a bunch of other information but which has no direct NoSQL equivalent.

Details

This is my GraphQL schema

type AudioFile {
  created: IsoDate!
  id: ID!
  lastModified: IsoDate!
  url: Url!
}

"A clip is a sequence create by parsing one or more audio files"
type Clip {
  "The collection of audio files forming the input to create the clip"
  audioFiles: [AudioFile!]!
  created: IsoDate!
  description: String
  id: ID!
  lastModified: IsoDate!
  title: String
}

type ClipsConnection {
  clips: [Clip!]!
  numberOfClips: Int!
  pageInfo: PageInfo!
}

scalar Cursor

scalar IsoDate

type Mutation {
  createClip(body: String): Clip
  deleteClip(id: ID!): Clip
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  numberOfPages: Int!
  previousPageCursor: Cursor
  nextPageCursor: Cursor
}

type Query {
  clip(id: ID!): Clip
  clips(
    cursor: String
    limit: Int
    sortField: String
    sortOrder: String
  ): ClipsConnection!
  user: User!
}

scalar Url

schema {
  query: Query
  mutation: Mutation
}

type User {
  created: IsoDate!
  familyName: String
  fullName: String
  givenName: String
  id: ID!
  imageUrl: Url
  lastModified: IsoDate!
}

The Cosmos NoSQL model comprises the following document types:

  • user
  • clip
  • audioFile

I have created the following resolvers to access CosmosDB.

  • Query-clip
  • Query-clips
  • Query-user
  • ClipsConnection-clips
  • ClipsConnection-numberOfClips
  • Clip-audioFiles,

This query works fine

query {
	clip(id: "pxwRRLtSRhOHpbDtiwM73w") {
		created
		id
	}
}

This query, however, does not

query {
	clip(id: "pxwRRLtSRhOHpbDtiwM73w") {
		audioFiles {
			id
		}
		created
		id
	}
}
{
  "errors": [
    {
      "message": "Error trying to resolve field 'audioFiles'.",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ],
      "path": [
        "clip",
        "audioFiles"
      ],
      "extensions": {
        "code": "JSON_READER",
        "codes": [
          "JSON_READER"
        ]
      }
    }
  ],
  "data": {
    "clip": null
  }
}

Resolvers are as follows (both work when run from the test in the resolvers tab)
Query-clip

<cosmosdb-data-source>
	<connection-info>
		<connection-string>{{Cyllin-CosmosDB-Connection-String}}</connection-string>
		<database-name>{{Cyllin-CosmosDB-Database}}</database-name>
		<container-name>{{Cyllin-CosmosDB-Container}}</container-name>
	</connection-info>
	<read-request>
		<id>
            @(context.GraphQL.Arguments["id"].ToString())
        </id>
		<partition-key data-type="string">3dcc911iTP2QV8TyqEWbfQ</partition-key>
	</read-request>
</cosmosdb-data-source>

Clip-audioFiles

<cosmosdb-data-source>
	<connection-info>
		<connection-string>{{Cyllin-CosmosDB-Connection-String}}</connection-string>
		<database-name>{{Cyllin-CosmosDB-Database}}</database-name>
		<container-name>{{Cyllin-CosmosDB-Container}}</container-name>
	</connection-info>
	<query-request>
		<sql-statement>SELECT * FROM c WHERE c.type="audioFile" AND c.clipId=@parentId</sql-statement>
		<parameters>
			<parameter name="@parentId">@(context.GraphQL.Parent["id"])</parameter>
		</parameters>
		<partition-key data-type="string">3dcc911iTP2QV8TyqEWbfQ</partition-key>
	</query-request>
</cosmosdb-data-source>

Similarly, I can't get the clips query to work at all. For example

query {
	clips {
		clips {
			id
		}
		numberOfClips
	}
}

One issue here is that the clips query returns an connector object which doesn't exist - it's virtual. I suppose I could query the NoSQL databases to return the page of clips then modify the response so that they are returned as the child-clips field.

Azure API Management
Azure API Management
An Azure service that provides a hybrid, multi-cloud management platform for APIs.
1,910 questions
Azure
Azure
A cloud computing platform and infrastructure for building, deploying and managing applications and services through a worldwide network of Microsoft-managed datacenters.
1,070 questions
Azure Cosmos DB
Azure Cosmos DB
An Azure NoSQL database service for app development.
1,520 questions
{count} votes