0

I'm new to GraphQL and need to write a Python function that updates 2 ID types (videoId and trackId) as variables, each 10 in number. They are stored in a mapped_ids list, which consists of 10 tupels in the following form: ('video ID', 'track ID').

My goal is to write a function that updates the query's variables for each of the 10 ID pairs that I got in the mapped_ids list. So basically, each video should get a separate request including video ID and track ID.

With my current approach (being at the very end of the code below), the variables are always overwritten, which is why only the last ID pair of the mapped_ids list are considered. With one single pair of IDs, my code works.

My code:

import requests

endpoint = 'endpoint of your choice'

# Query containing video and track ID of German track as variables.
GET_TRACK_URLS = '''
query GetUrls($id: ID!, $trackId: ID!) {
    video(id: $id) {
        id
         voices {
             id
             dubbingSegments {
                 start
                 duration
                 meta(trackId: $trackId) {
                     text
                     trackId
                     asset {
                         representations {
                             href
                         }
                     }
                 }
             }
         }
    }
}
''' 

# POST GraphQL request and parse response.
def run_query(query, variables):
    response = requests.post(
        endpoint,
        json={'query': query, 'variables': variables},
    )
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f'Query failed with a {response.status_code}: {response.json()}')


# Approach 1 to update variables (not successful so far):
for video_id, track_id in mapped_ids:
    video_id = video_id
    track_id = track_id
data2 = run_query(GET_TRACK_URLS, {'id': video_id, 'trackId': track_id})


# Approach 2 to update variables (not successful so far):
my_variables = {}
for video_id, track_id in mapped_ids:
    my_variables['id'] = video_id
    my_variables['trackId'] = track_id
data2 = run_query(GET_TRACK_URLS, my_variables)

Unfortunately I can't wrap my head around writing the desired function, even though I already did a lot of research.

A sample of the JSON response:

{'data': {'video': {'id': 'c0deeabc-6b12-11eb-b741-7b3016ed7f39', 'voices': "
 "[{'id': '745b74d0-7b48-11eb-9e5f-7fc87d0ed7ca', 'dubbingSegments': "
 "[{'start': 140, 'duration': 3539, 'meta': [{'text': 'Heute geht es bei uns "
 "um Reptilien.', 'trackId': '9mn86640-87c0-11eb-a09e-ad706c66b842', 'asset': "
 "{'representations': [{'href': "
 "'https://arbitraryurl.com/5dbb3m88-87c0-11eb-a09e-ad741a76b842/original?av=1'}]}}]}, "
 "{'start': 3700, 'duration': 6469, 'meta': [{'text': 'Im Gegensatz zu "
 'Säugetieren, Amphibien, Vögeln und Fischen, die wir bereits behandelt '
 "haben,', 'trackId': '7bn86640-80c0-11eb-a09e-ad706a76b851', 'asset': "
 "{'representations': [{'href': "
 "'https://arbitraryurl.com/5daa1l79-87c0-11eb-a09e-ad706m16b842/original?av=1'}]}}]}, "
 "{'start': 10170, 'duration': 3099, 'meta': [{'text': 'haben Reptilien "
 "außergewöhnliche Schuppen.', 'trackId': "
 "'5da82140-87c0-11bm-a09e-ad706a76b842', 'asset': {'representations': "
 "[{'href': "
 "'https://arbitraryurl.com/5daa5341-87c0-11eb-a09e-ad706a76b842/original?av=1'}]}}]},

Edit:

After considering Bijay Regmi's solution, my code and my query now looks like this if I print it:

for elem in mapped_ids:
    query_string = GET_TRACK_URLS.replace('(id: $id)','(id: "' + elem[0] + '")')
    query_string = query_string.replace('(trackId: $trackId)', '(trackId: "' + elem[1] + '")')
    print(query_string)

data = run_query(GET_TRACK_URLS, {})
print('\nDATA:\n', data)  # Debug.


query GetUrls($id: ID!, $trackId: ID!) {
    video(id: b8bce3e0-6b84-18jb-b741-7b3016ed7f01) {
        id
         voices {
             id
             dubbingSegments {
                 start
                 duration
                 meta(trackId: 5bv76640-09c0-11eb-a09e-ad706a76b873) {
                     text
                     trackId
                     asset {
                         representations {
                             href
                         }
                     }
                 }
             }
         }
    }
}

Now I'm getting the error message:

Exception: Query failed with a 400: 
{'errors': [{'message': 'Variable "$id" of required type "ID!" was not provided.', 
'locations': [{'line': 2, 'column': 15}], 'extensions': {'code': 'INTERNAL_SERVER_ERROR'}}, 
{'message': 'Variable "$trackId" of required type "ID!" was not provided.', 'locations': [{'line': 2, 'column': 25}], 'extensions': {'code': 'INTERNAL_SERVER_ERROR'}}]}
MareikeP
  • 186
  • 9

1 Answers1

1

Edit: new approach: Since there seems to exist a mismatch of variable, I have completely recreated the code on top of what you had written, so please populate the mapped_ids variable as per your data.

import requests

def run_query(query, variables):
   endpoint = "https://api.myserver.de"

   response = requests.post(
       endpoint,
       json={'query': query, 'variables': variables},
   )
   if response.status_code == 200:
       return response.json()
   else:
       raise Exception(f'Query failed with a {response.status_code}: {response.json()}')

GET_TRACK_URLS = '''
query GetUrls($id: ID!, $trackId: ID!) {
   video(id: $id) {
       id
        voices {
            id
            dubbingSegments {
                start
                duration
                meta(trackId: $trackId) {
                    text
                    trackId
                    asset {
                        representations {
                            href
                        }
                    }
                }
            }
        }
   }
}
''' 
mapped_ids = [["video_id_1","track_id_1"], ["video_id_2", "track_id_2"]]

for video_id, track_id in mapped_ids:
   my_variables = {}
   my_variables['id'] = video_id
   my_variables['trackId'] = track_id
   resp_data = run_query(GET_TRACK_URLS, my_variables)
   print(resp_data)

''' 
mapped_ids = [["video_id_1","track_id_1"], ["video_id_2", "track_id_2"]]

for video_id, track_id in mapped_ids:
   my_variables = {}
   my_variables['video_ID'] = video_id
   my_variables['track_ID'] = track_id
   resp_data = run_query(GET_TRACK_URLS, my_variables)
   print(resp_data)

First Attempt:

I tried something like string.replace() as it seems to be the easiest to insert the IDs into required fields. Below is a sample code I tried and it works for my sample I created.

GET_TRACK_URLS = '''
query GetUrls($id: ID!, $trackId: ID!) {
    video(id: $id) {
        id
         voices {
             id
             dubbingSegments {
                 start
                 duration
                 meta(trackId: $trackId) {
                     text
                     trackId
                     asset {
                         representations {
                             href
                         }
                     }
                 }
             }
         }
    }
}
''' 

id_list = [("t1","v1"),("t2","v2"),("t3","v3")] #trackID and videoIDs i created as sample.

for elem in id_list:
    QUERY_STRING = GET_TRACK_URLS.replace("$id: ID!","$id: " + elem[1] + "!")
    QUERY_STRING = QUERY_STRING.replace("$trackId: ID!", "$trackId: "+ elem[0] +"!")
    print(QUERY_STRING)

prints :

query GetUrls($id: v1!, $trackId: t1!) {
    video(id: $id) {
        id
         voices {
             id
             dubbingSegments {
                 start
                 duration
                 meta(trackId: $trackId) {
                     text
                     trackId
                     asset {
                         representations {
                             href
                         }
                     }
                 }
             }
         }
    }
}


query GetUrls($id: v2!, $trackId: t2!) {
    video(id: $id) {
        id
         voices {
             id
             dubbingSegments {
                 start
                 duration
                 meta(trackId: $trackId) {
                     text
                     trackId
                     asset {
                         representations {
                             href
                         }
                     }
                 }
             }
         }
    }
}


query GetUrls($id: v3!, $trackId: t3!) {
    video(id: $id) {
        id
         voices {
             id
             dubbingSegments {
                 start
                 duration
                 meta(trackId: $trackId) {
                     text
                     trackId
                     asset {
                         representations {
                             href
                         }
                     }
                 }
             }
         }
    }
}

p.s. I was not sure if ! after each ID was intended so I kept it.

Bijay Regmi
  • 1,187
  • 2
  • 11
  • 25
  • Thank you for your answer, I'll try it out and let you know if it works. The thing is, I've read that the replacement of strings is like "abusing graphQL" (https://stackoverflow.com/questions/62384215/best-way-to-construct-a-graphql-query-string-in-python) which is why I haven't tried it out so far. But I will now. – MareikeP Mar 26 '21 at 09:23
  • 1
    If you want to do a more graphQL way, you can do something like `query GetUrls($id: [VIDEO_ID!]!, $trackId: [TRACK_ID!]!) {` and you create a new dict with list of variables you pass like `variables = {'id' : videoID, 'trackID' : trackID}` but then you have to create a graphql schema where you define VIDEO_ID and TRACK_ID. Once you do that, you can create request to your endpoint where you can just define `variables` as `r = requests.post(url, json={'query': your_query , 'variables': variables})` and the endpoint will decide automatically what belongs where! – Bijay Regmi Mar 26 '21 at 09:42
  • I have tried your first solution approach, adjusted it a little (videoId and trackId needed to be exchanged) and now I'm getting the error message: `'message': 'Variable "$id" of required type "ID!" was not provided.'` (full error message as well as my updated code can be seen at the very end of my post). I don't know what's wrong now. – MareikeP Mar 26 '21 at 10:13
  • I see that you have modified the query to look like `query GetUrls($id: ID!, $trackId: ID!) { video(id: b8bce3e0-6b84-18jb-b741-7b3016ed7f01) {` in your example, i think the correct way would be `query GetUrls($id: b8bce3e0-6b84-18jb-b741-7b3016ed7f01, $trackId: ID!) { video(id: $id) {` – Bijay Regmi Mar 26 '21 at 10:22
  • We need to specify `$id` in `GetUrls` and pass it on to nested categories with `id: $id` – Bijay Regmi Mar 26 '21 at 10:23
  • I also tried explicitly your way without adjusting, I'm still getting the same 400 error message saying that the variables are not provided. – MareikeP Mar 26 '21 at 10:31
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/230406/discussion-between-bijay-regmi-and-mareikep). – Bijay Regmi Mar 26 '21 at 11:01