question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Google Drive Python API: Adding Multiple Properties

See original GitHub issue

Hello,

I would like to add multiple entries into the properties metadata field for a file so that the file is indexable using files().list(). Here is my code:

# define read and write permissions

SCOPES = ['https://www.googleapis.com/auth/drive.file']

# check if the user's access and refresh tokens already exist

import pickle
import os

if os.path.exists('token.pickle'):
    with open('token.pickle','rb') as f:
        creds = pickle.load(f)
else:
    creds = None

"""
If the user's access and refresh tokens don't exist, or they are no longer valid, then create them and save them. This will not work if the credentials.json file is not in the user's working directory.
"""

from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    
    with open('token.pickle', 'wb') as f:
        pickle.dump(creds,f)

"""
check that the authentication flow worked. This should be the same as the string in the "client_id" field in the credentials.json file. Additionally, if the access and refresh tokens did not already exist, then a token.pickle file should now be in the user's working directory.
"""

print('client_id is: {}'.format(creds.client_id))

# create a drive object to directly interface with the user's Google Drive.

from googleapiclient.discovery import build

drive = build('drive', 'v3',credentials=creds)

# create a folder in the root directory of the user's Google Drive.

folder_metadata = {
    
    'name': 'TestFolder',
    'mimeType': 'application/vnd.google-apps.folder'
    
}

folder = drive.files().create(body = folder_metadata, fields = 'id,name').execute()

# upload a file with indexable properties to the created folder

# first create the file
with open('HelloWorld.txt','w') as f:
    f.write('Hello World!')

# then define metadata
property1 = {'key' : 'day_of_week', 'value' : 'Monday'}
property2 = {'key' : 'patient_num', 'value' : '001'}

file_metadata = {
    'name': 'HelloWorld.txt',
    'parents': [folder['id']],
    'properties':[property1,property2]
}

# finally upload
from googleapiclient.http import MediaFileUpload

media = MediaFileUpload('HelloWorld.txt',chunksize = -1,resumable = False)
file = drive.files().create(body = file_metadata, media_body = media, fields = 'name,properties').execute()

# try to search for the file

query = "properties has {key = 'patient_num' and value = '001'}"

files_list = drive.files().list(q = query, fields = 'files(name,properties)').execute()

When I execute this code, files_list contains {'files': []}. The reason for this is because the file variable contains:

{'name': 'HelloWorld.txt',
 'properties': {'value': 'Monday', 'key': 'day_of_week'}}

Clearly, the 'patient_num' property was not added to the properties field, even though it was explicitly defined in the file_metadata dictionary. I am aware of this question on Stack Overflow, but I feel that the proposed solution is inefficient. How do I add multiple properties to a file so that it is indexable using either the day_of_week property or the patient_num property or both properties at the same time? Also, once I can do this, how should I modify query so that I am able to index using multiple properties simultaneously?

Thanks a lot, Mahmoud Abdelkhalek

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mhdadkcommented, Jun 25, 2020

Here is the correct query format for multiple properties in case anyone needs it.

# try to search for the file

query = "properties has {key = 'day_of_week' and value = 'Monday'} and properties has {key = 'patient_num' and value = '001'}"

files_list = drive.files().list(q = query, fields = 'files(name,properties)').execute()

The full working code is:

# define read and write permissions

SCOPES = ['https://www.googleapis.com/auth/drive.file']

# check if the user's access and refresh tokens already exist

import pickle
import os

if os.path.exists('token.pickle'):
    with open('token.pickle','rb') as f:
        creds = pickle.load(f)
else:
    creds = None

"""
If the user's access and refresh tokens don't exist, or they are no longer valid, then create them and save them. This will not work if the credentials.json file is not in the user's working directory.
"""

from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    
    with open('token.pickle', 'wb') as f:
        pickle.dump(creds,f)

"""
check that the authentication flow worked. This should be the same as the string in the "client_id" field in the credentials.json file. Additionally, if the access and refresh tokens did not already exist, then a token.pickle file should now be in the user's working directory.
"""

print('client_id is: {}'.format(creds.client_id))

# create a drive object to directly interface with the user's Google Drive.

from googleapiclient.discovery import build

drive = build('drive', 'v3',credentials=creds)

# create a folder in the root directory of the user's Google Drive.

folder_metadata = {
    
    'name': 'TestFolder',
    'mimeType': 'application/vnd.google-apps.folder'
    
}

folder = drive.files().create(body = folder_metadata, fields = 'id,name').execute()

# upload a file with indexable properties to the created folder

# first create the file
with open('HelloWorld.txt','w') as f:
    f.write('Hello World!')

# then define metadata

properties = {
    'day_of_week' : 'Monday',
    'patient_num' : '001'
}

file_metadata = {
    'name' : 'HelloWorld.txt',
    'parents' : [folder['id']],
    'properties' : properties
}

# finally upload
from googleapiclient.http import MediaFileUpload

media = MediaFileUpload('HelloWorld.txt',chunksize = -1,resumable = False)
file = drive.files().create(body = file_metadata, media_body = media, fields = 'name,properties').execute()

# try to search for the file

query = "properties has {key = 'day_of_week' and value = 'Monday'} and properties has {key = 'patient_num' and value = '001'}"

files_list = drive.files().list(q = query, fields = 'files(name,properties)').execute()

Note that the general format to query multiple properties at the same time is:

"properties has {key = 'key1' and value = 'value1'} and properties has {key = 'key2' and value = 'value2'} and properties has {key = 'key3' and value = 'value3'} and ..."

Hope this helps.

0reactions
busunkim96commented, Jun 25, 2020

@mhdadk Thanks for the update!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Google Drive Python API: Adding Multiple Properties
Here is the correct query format for multiple properties in case anyone needs it. # try to search for the file query =...
Read more >
Properties: insert | Google Drive
Insert a new custom file property. * * @param service Drive API service instance. * @param fileId ID of the file to insert...
Read more >
Indexes | Cloud Datastore Documentation
Composite indexes are composed of multiple properties and require that each individual property must not be excluded from your indexes. Composite indexes are ......
Read more >
Google Drive API in Python | Getting Started - YouTube
Google Drive API allows you to create apps that leverage Google Drive cloud storage. You can develop applications that integrate with Google ...
Read more >
How to Use the Google Drive API with JavaScript - Medium
How to Use the Google Drive API with JavaScript · Authentication · Enable APIs · Share Files · Install Modules · Getting Google...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found