2017-02-28 44 views
2

我試圖put嵌套entity/dict成使用Python數據存儲,ValueError異常:未知的protobuf ATTR類型<類的字典'>當試圖把一個嵌套字典/實體

metadata_row = dict() 
metadata_row['batch_id'] = str(uuid1()) 
metadata_row['table_ok'] = True 
metadata_row['table_name'] = 'metadata' 
metadata_row['num_rows'] = 1 
metadata_row['violations'] = [] 
metadata_row['errors'] = [] 

metadata_row['time'] = {} 
metadata_row['time']['total_time'] = 82.42656564712524 
metadata_row['time']['mod1'] = 5.940682411193848 
metadata_row['time']['mod2'] = 19.16786551475525 
metadata_row['time']['mod3'] = 31.617812633514404 
metadata_row['time']['mod4'] = 0.00038933753967285156 
metadata_row['time']['mod5'] = 53.35780310630798 

with self.client.transaction(): 

    entities = [Entity(self.client.key('metadata')) for i in range(len([metadata_row]))] 

    for entity, update_dict in zip(entities, [metadata_row]): 
     entity.update(update_dict) 

    self.client.put_multi(entities) 

我通過使用datastore emulator測試它,但我得到以下錯誤,

ValueError: Unknown protobuf attr type <class 'dict'> 

我想知道如何解決這個問題。我也想知道datastore原生支持嵌套字典,因爲在這種情況下,不需要爲內部字典創建entity,即time

UPDATE。我在metadata_row中爲time加了一個內部實體來解決這個問題。

client = datastore.Client() 
metadata_row['time'] = datastore.Entity(key=client.key('time')) 

metadata_row['time']['total_time'] = 82.42656564712524 
metadata_row['time']['mod1'] = 5.940682411193848 
metadata_row['time']['mod2'] = 19.16786551475525 
metadata_row['time']['mod3'] = 31.617812633514404 
metadata_row['time']['mod4'] = 0.00038933753967285156 
metadata_row['time']['mod5'] = 53.35780310630798 

# code for put_multi() 
+1

不是100%確定,但我懷疑字典中的值應該在可接受的類型中(來自https://cloud.google.com/datastore/docs/concepts/entities#properties_and_value_types),其中不包括http://stardict.sourceforge.net/Dictionaries.php下載。也許json.dumps字典的值,並將其存儲爲一個字符串? –

+0

@DanCornilescu我也嘗試過'json.dumps',它也可以工作,也許稍微比爲內部字典添加一個內部實體更好。 – daiyue

+0

使用json.dumps時遇到同樣的問題。我認爲我們必須將嵌套值轉換爲「嵌入式實體」 –

回答

0
def convert(obj, client, key): 
""" 
:param obj: dict 
:param client: datastore client 
:param key: Generated as client.key("your_table", "your_key") 
:return: datastore.Entity 
""" 
if isinstance(obj, list): 
    return [convert(item, client, None) for item in obj] 
elif isinstance(obj, dict): 
    entity = datastore.Entity(key) 
    for key in obj: 
     entity[key] = convert(obj[key], client, None) 
    return entity 
else: 
    return obj 

請不要提出任何改進或替代品谷歌雲存儲目前不建議的方式到JSON轉換成實體。