#python #pandas #salesforce #soql #simple-salesforce
#python #pandas #salesforce #soql #ordereddictionary
Вопрос:
Я пытаюсь запросить информацию из salesforce, используя simple_salesforce
пакет на python.
Проблема в том, что это вложение полей, которые являются частью отношения родитель-потомок, в упорядоченный dict внутри упорядоченного dict
Я хочу .. из объекта Opportunity найти идентификатор и идентификатор учетной записи, связанный с этой записью.
Запрос SOQL может выглядеть следующим образом..
query = "select id, account.id from opportunity where closedate = last_n_days:5"
в SOQL (salesforce object query language) точка обозначает отношения родитель-потомок в базе данных. Итак, я пытаюсь получить идентификатор из объекта opportunity, а затем связанный идентификатор из объекта account в этой записи.
по какой-то причине идентификатор отображается нормально, но account.id вложен в упорядоченный dict внутри упорядоченного dict:
q = sf.query_all(query)
это возвращает упорядоченный словарь..
OrderedDict([('totalSize', 455),
('done', True),
('records',
[OrderedDict([('attributes',
OrderedDict([('type', 'Opportunity'),
('url',
Я бы вытащил records
часть ordereddict
, чтобы создать df
df = pd.DataFrame(q['records'])
Это дает мне 3 столбца, вызывается упорядоченный dict 'attributes'
Id
и вызывается другой упорядоченный dict 'Account'
. Я ищу способ извлечь ('BillingCountry', 'United States')
фрагмент из вложенного упорядоченного dict 'Account'
[OrderedDict([('attributes',
OrderedDict([('type', 'Opportunity'),
('url',
'/services/data/v34.0/sobjects/Opportunity/0061B003451RhZgiHHF')])),
('Id', '0061B003451RhZgiHHF'),
('Account',
OrderedDict([('attributes',
OrderedDict([('type', 'Account'),
('url',
'/services/data/v34.0/sobjects/Account/001304300MviPPF3Z')])),
('BillingCountry', 'United States')]))])
Редактировать: уточнение того, что я ищу.
Я хочу закончить фреймом данных со столбцом для каждого из запрашиваемых полей.
Когда я помещаю 'records'
фрагмент в df = pd.DataFrame(sf.query_all(query)['records'])
фрейм данных, используя его, я:
attributes Id Account
OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v34.0/sobjects/Opportunity/0061B003451RhZgiHHF')]) 0061B003451RhZgiHHF OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', '/services/data/v34.0/sobjects/Account/0013000000MvkRQQAZ')])), ('BillingCountry', 'United States')])
OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v34.0/sobjects/Opportunity/0061B00001Pa52QQAR')]) 0061B00001Pa52QQAR OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', '/services/data/v34.0/sobjects/Account/0011300001vQPxqAAG')])), ('BillingCountry', 'United States')])
OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v34.0/sobjects/Opportunity/0061B00001TRu5mQAD')]) 0061B00001TRu5mQAD OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', '/services/data/v34.0/sobjects/Account/0011300001rfRTrAAE')])), ('BillingCountry', 'United States')])
после удаления 'attributes'
столбца я хочу, чтобы результат был
Id BillingCountry
0061B003451RhZgiHHF 'United States'
0061B00001Pa52QQAR 'United States'
0061B00001TRu5mQAD 'United States'
Комментарии:
1. @StephenRauch Я обновил свой вопрос, чтобы внести некоторую ясность
2. Почему вы помещаете это в Dataframe? Что это вам дает? Из какой формы взяты записи
sf.query_all(query)
?3. это фактически sql-запрос из базы данных. Но по какой-то причине
query
функция в пакете возвращает упорядоченный dict. Я могу превратить записи из упорядоченного dict в фрейм данных, но в этом случае один из списков, которые становятся сериями при его преобразовании, на самом деле является другим упорядоченным dict.4. Да, но. Почему вы заходите в dataframe? Это кажется дополнительным шагом, который не дает никакого значения, только путаница.
5. в какой форме вы бы его сохранили?
Ответ №1:
Pandas — потрясающий инструмент для обработки табличных данных. Но, хотя он может содержать объекты Python, это не его преимущество. Я предлагаю вам извлечь ваши данные из запроса, прежде чем вставлять их в pandas.Dataframe
:
Извлечение записей:
Извлечь нужные поля в виде списка словарей так же просто, как:
records = [dict(id=rec['Id'], country=rec['Account']['BillingCountry'])
for rec in data['records']]
Вставка записей в фрейм данных:
Со списком dicts фрейм данных так же прост, как:
df = pd.DataFrame(records)
Тестовый код:
import pandas as pd
from collections import OrderedDict
data = OrderedDict([
('totalSize', 455),
('done', True),
('records', [
OrderedDict([
('attributes', OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v34.0/sobjects/Opportunity/0061B003451RhZgiHHF')])),
('Id', '0061B003451RhZgiHHF'),
('Account', OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', '/services/data/v34.0/sobjects/Account/0013000000MvkRQQAZ')])),
('BillingCountry', 'United States')])),
]),
OrderedDict([
('attributes', OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v34.0/sobjects/Opportunity/0061B00001Pa52QQAR')])),
('Id', '0061B00001Pa52QQAR'),
('Account', OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', '/services/data/v34.0/sobjects/Account/0011300001vQPxqAAG')])),
('BillingCountry', 'United States')])),
]),
OrderedDict([
('attributes', OrderedDict([('type', 'Opportunity'), ('url', '/services/data/v34.0/sobjects/Opportunity/0061B00001TRu5mQAD')])),
('Id', '0061B00001TRu5mQAD'),
('Account', OrderedDict([('attributes', OrderedDict([('type', 'Account'), ('url', '/services/data/v34.0/sobjects/Account/0011300001rfRTrAAE')])),
('BillingCountry', 'United States')])),
]),
])
])
records = [dict(id=rec['Id'], country=rec['Account']['BillingCountry'])
for rec in data['records']]
for r in records:
print(r)
print(pd.DataFrame(records))
Результаты тестирования:
{'country': 'United States', 'id': '0061B003451RhZgiHHF'}
{'country': 'United States', 'id': '0061B00001Pa52QQAR'}
{'country': 'United States', 'id': '0061B00001TRu5mQAD'}
country id
0 United States 0061B003451RhZgiHHF
1 United States 0061B00001Pa52QQAR
2 United States 0061B00001TRu5mQAD
Комментарии:
1. идеальный ответ. Хорошо объяснено, я многому научился, и это решило мою проблему. Большое спасибо @Stephen Rauch
Ответ №2:
Pandas может читать упорядоченные dicts.
import pandas as pd
from simple_salesforce import Salesforce
sf = Salesforce(username='your_username',
password='your_password',
security_token='your_token')
query = "select id, account.id from opportunity where closedate = last_n_days:5"
df = pd.DataFrame(sf.query_all(query)['records']).drop(columns='attributes')
Комментарии:
1. это возможно, но это не решает проблему, когда
account.id
также появляется как упорядоченный dict, а не как поле.account
таблица представляет собой вложенную таблицу, связанную с таблицей возможностей. Словарь в ответе Стивена — это то, как решить эту проблему. Но спасибо!