Нужно было выгрузить с одного орга на другой большое количество связанных записей COUNTRY -> CITY -> AIRPORT
COUNTRY выгрузились очень легко и просто потому что это parent
CITY - пришлось помучаться и подумать(10тысяч записей руками не обновишь), потому как нужно было обновлять COUNTRY__c в соотвтствие с данными орга
Если кому нужно, то вот решение;
import pandas as pd
sep = ","
path_file_1 = "/users/maxim_elets/desktop/csv/cities.csv"
data1 = pd.read_csv(path_file_1, sep=sep, error_bad_lines=False)
path_file_2 = "/users/maxim_elets/desktop/countries_export.csv"
data2 = pd.read_csv(path_file_2, sep=sep, error_bad_lines=False)
data2_dict = dict(zip(data2.EXTERNALID__C, data2.ID))
data1["COUNTRY__C"].replace(data2_dict,inplace=True)
data1.to_csv("/users/maxim_elets/desktop/csv/replaced_cities.csv", mode = 'w', index=False)
Ну и дальше загружаем все это через даталоадер.
Если есть варианты проще, прошу отписаться :)
Нужно было выгрузить с одного орга на другой большое количество связанных записей COUNTRY -> CITY -> AIRPORT COUNTRY выгрузились очень легко и просто потому что это parent CITY - пришлось помучаться и подумать(10тысяч записей руками не обновишь), потому как нужно было обновлять COUNTRY__c в соотвтствие с данными орга Если кому нужно, то вот решение; [list] Выгружаем COUNTRY и мапим ID из CSV в ExternalId__c поле Делаем ЭКСПОРТ и экспортируем Id, ExternalId__c ставим python и либу pandas [/list] [code] import pandas as pd sep = "," path_file_1 = "/users/maxim_elets/desktop/csv/cities.csv" data1 = pd.read_csv(path_file_1, sep=sep, error_bad_lines=False) path_file_2 = "/users/maxim_elets/desktop/countries_export.csv" data2 = pd.read_csv(path_file_2, sep=sep, error_bad_lines=False) data2_dict = dict(zip(data2.EXTERNALID__C, data2.ID)) data1["COUNTRY__C"].replace(data2_dict,inplace=True) data1.to_csv("/users/maxim_elets/desktop/csv/replaced_cities.csv", mode = 'w', index=False) [/code] Ну и дальше загружаем все это через даталоадер. Если есть варианты проще, прошу отписаться :)
Можно сделать тоже самое, но через Excel без питона.
Можно сделать тоже самое, но через Excel без питона.
Расскажи плиз, как.
[quote="Gres"]Можно сделать тоже самое, но через Excel без питона.[/quote] Расскажи плиз, как.
чисто теоретически, на практике не перименял, может гдето не так понимаю ?
1 сделать по external ID text полю на COUNTRY and CITY (только в новом орге)
2 забить оба поля данными прямо в CSV или Excel , используя старый SFDC ID t.e. рекорд COUNTRY будет иметь External text ID со значением SFDC ID в старом орге. По сути переименовать ID в ExternalId__c прямо в CSV.
3 загрузить парента вместе с новым External ID полем, загрузить чайлда используя связь по external ID (чайлда соответственно тянуть со старого орга вместе с parent ID) see link below
4 повторить для грандчайлда по той же схеме
5 удалить external ID поля с нового орга
https://help.salesforce.com/articleView?id=000320964&type=1&mode=1
чисто теоретически, на практике не перименял, может гдето не так понимаю ? 1 сделать по external ID text полю на COUNTRY and CITY (только в новом орге) 2 забить оба поля данными прямо в CSV или Excel , используя старый SFDC ID t.e. рекорд COUNTRY будет иметь External text ID со значением SFDC ID в старом орге. По сути переименовать ID в ExternalId__c прямо в CSV. 3 загрузить парента вместе с новым External ID полем, загрузить чайлда используя связь по external ID (чайлда соответственно тянуть со старого орга вместе с parent ID) see link below 4 повторить для грандчайлда по той же схеме 5 удалить external ID поля с нового орга https://help.salesforce.com/articleView?id=000320964&type=1&mode=1
1 сделать по external ID text полю на COUNTRY and CITY (только в новом орге)
2 забить оба поля данными прямо в CSV или Excel , используя старый SFDC ID t.e. рекорд COUNTRY будет иметь External text ID со значением SFDC ID в старом орге. По сути переименовать ID в ExternalId__c прямо в CSV.
3 загрузить парента вместе с новым External ID полем, загрузить чайлда используя связь по external ID (чайлда соответственно тянуть со старого орга вместе с parent ID) see link below
4 повторить для грандчайлда по той же схеме
5 удалить external ID поля с нового орга
https://help.salesforce.com/articleView?id=000320964&type=1&mode=1
External Id в любом случае нужен, чтобы мапить значения правильно.
Смысл скрипта в том, что все что нужно - это указать путь к csv и указать откуда какие поля/значения мапить.
Просто я допустим хз как в Excel можно заменить значения в колонке используя мапу - старый айди: новый айди.
[quote="Андрей"]чисто теоретически, на практике не перименял, может гдето не так понимаю ? 1 сделать по external ID text полю на COUNTRY and CITY (только в новом орге) 2 забить оба поля данными прямо в CSV или Excel , используя старый SFDC ID t.e. рекорд COUNTRY будет иметь External text ID со значением SFDC ID в старом орге. По сути переименовать ID в ExternalId__c прямо в CSV. 3 загрузить парента вместе с новым External ID полем, загрузить чайлда используя связь по external ID (чайлда соответственно тянуть со старого орга вместе с parent ID) see link below 4 повторить для грандчайлда по той же схеме 5 удалить external ID поля с нового орга https://help.salesforce.com/articleView?id=000320964&type=1&mode=1[/quote] External Id в любом случае нужен, чтобы мапить значения правильно. Смысл скрипта в том, что все что нужно - это указать путь к csv и указать откуда какие поля/значения мапить. Просто я допустим хз как в Excel можно заменить значения в колонке используя мапу - старый айди: новый айди.
Вот - https://support.office.com/en-us/article/vlookup-function-0bbc8083-26fe-4963-8ab8-93a18ad188a1
Интересный видос, но я не понял как он мне поможет:
У меня есть файл Города, csv - 10000 строк; В нем лежит Country__c - айди Страны
Я выгружаю себе на орг файл Страны.csv
Мне нужно заменить в файле города.csv старые Id на новые (с моего орга)
На питоне я просто указываю путь к Города.csv + Страны_export.csv
И говорю что хочу заменить Город.Country__c на то что залилось в мой орг.
А с vlookup что-то не понятно
[quote="DevNull"]Вот - https://support.office.com/en-us/article/vlookup-function-0bbc8083-26fe-4963-8ab8-93a18ad188a1[/quote] Интересный видос, но я не понял как он мне поможет: У меня есть файл Города, csv - 10000 строк; В нем лежит Country__c - айди Страны Я выгружаю себе на орг файл Страны.csv Мне нужно заменить в файле города.csv старые Id на новые (с моего орга) На питоне я просто указываю путь к Города.csv + Страны_export.csv И говорю что хочу заменить Город.Country__c на то что залилось в мой орг. А с vlookup что-то не понятно
vlookup позволяет вытянуть данные из одного файла в другой основываясь на каком либо значении. Я tuj использую что бы смапить данные по External Id и Sf Id
vlookup позволяет вытянуть данные из одного файла в другой основываясь на каком либо значении. Я tuj использую что бы смапить данные по External Id и Sf Id
А зачем в файле City.csv обновлять Country__c новыми айдишками?
Почему бы не использовать старые id как externalId поля и по ним мапить в даталоадере?
А зачем в файле City.csv обновлять Country__c новыми айдишками? Почему бы не использовать старые id как externalId поля и по ним мапить в даталоадере?
Почему бы не использовать старые id как externalId поля и по ним мапить в даталоадере?
я и пытался обьяснить этот подход.. надо только переименовать header в csv и готово
[quote="Dummy"]А зачем в файле City.csv обновлять Country__c новыми айдишками? Почему бы не использовать старые id как externalId поля и по ним мапить в даталоадере?[/quote] я и пытался обьяснить этот подход.. надо только переименовать header в csv и готово
Почему бы не использовать старые id как externalId поля и по ним мапить в даталоадере?
я и пытался обьяснить этот подход.. надо только переименовать header в csv и готово
Да все верно, это так и работает, без велосипедов.
[quote="Андрей"][quote="Dummy"]А зачем в файле City.csv обновлять Country__c новыми айдишками? Почему бы не использовать старые id как externalId поля и по ним мапить в даталоадере?[/quote] я и пытался обьяснить этот подход.. надо только переименовать header в csv и готово[/quote] Да все верно, это так и работает, без велосипедов.
Что-то я не нашел в Dataloader место где можно замапить айдишки по другому объекту?
Может у меня приложение кривое? Все что позволяет мне оно сделать это замапить филды из CSV в филды выбранного объекта?
Или я иду, делаю ExternalCountry__c поле, делаю маппинг с City.csv|Country__c в City__c.ExternalCountry__c?
А дальше что?
Умоляю запишите видос для меня тупого, это не займет много вашего времени, но поможет мне разобраться.
Что-то я не нашел в Dataloader место где можно замапить айдишки по другому объекту? Может у меня приложение кривое? Все что позволяет мне оно сделать это замапить филды из CSV в филды выбранного объекта? Или я иду, делаю ExternalCountry__c поле, делаю маппинг с City.csv|Country__c в City__c.ExternalCountry__c? А дальше что? [color=red]Умоляю запишите видос для меня тупого, это не займет много вашего времени, но поможет мне разобраться.[/color]
нужно следовать принципам из туториала https://help.salesforce.com/articleView?id=000320964&type=1&mode=1
скорее всего ты пропустил чтото из этого :
1 поле которое temporary external id должно быть помечено как unique
2 надо выбирать именно UPSERT а не IMPORT. почему то в импорте нельзя замапить по external id а в апсерте можно
я создал обьекты CITYTEST и COUNTRYTEST в сэндбоксе.
На CITYTEST есть master detail COUNTRYTEST__C.
также создал по 1 data полю, Data на City и ParentData на паренте.
создал 10 рекордов парентов и 10 чайлдов и скачал. данные выглядят так.
https://i.imgur.com/YkD9gXD.jpg
дальше в другомсэндбоксе
переименовываем прямо в хедере на COUNTRYTEST ID в X__c и создаем это самое поле на COUNTRYTEST. Поле должно быть text, unique и external ID. Загружаем данные на орг. Старый ID загружается в новое тестовое поле X__с.
https://i.imgur.com/d2XWyPJ.jpg
на чайлде CITYTEST я удалил ID из csv, как из хедера так и из данных. Тебе надо повторить процесс, создать еще один external ID etc для того чтобы сделать grandchild, я не собирался возиться с этим. ID надо удалить или переименовать потому что он автоматически маппится во время upsert и от этого нельзя избавиться.
дальше нажимаем upsert и выбираем наш CITYTEST. Data loader детектит что на паренте есть пододящий для маппинга external id и дает нам его навыбор.
https://i.imgur.com/WJIdK7w.jpg
собственно выбираем наше поле X__c как External ID. потом еще раз маппим внутри mapping dialog. Конечный результат:
https://i.imgur.com/4t2VFLp.jpg
нажимаем finish и чайлды маппятся по старому парент ID загруженному в другое поле. После того как data load процесс закончен поле X__c можно удалить.
Если ты хочешь еще загрузить грандчайлда то надо вместо удаления ID с CITY создать новое поле Y__c и загрузить в него старые ID CITY чтобы повторить потом процесс.
нужно следовать принципам из туториала https://help.salesforce.com/articleView?id=000320964&type=1&mode=1 скорее всего ты пропустил чтото из этого : 1 поле которое temporary external id должно быть помечено как unique 2 надо выбирать именно UPSERT а не IMPORT. почему то в импорте нельзя замапить по external id а в апсерте можно я создал обьекты CITYTEST и COUNTRYTEST в сэндбоксе. На CITYTEST есть master detail COUNTRYTEST__C. также создал по 1 data полю, Data на City и ParentData на паренте. создал 10 рекордов парентов и 10 чайлдов и скачал. данные выглядят так. https://i.imgur.com/YkD9gXD.jpg дальше в другомсэндбоксе переименовываем прямо в хедере на COUNTRYTEST ID в X__c и создаем это самое поле на COUNTRYTEST. Поле должно быть text, unique и external ID. Загружаем данные на орг. Старый ID загружается в новое тестовое поле X__с. https://i.imgur.com/d2XWyPJ.jpg на чайлде CITYTEST я удалил ID из csv, как из хедера так и из данных. Тебе надо повторить процесс, создать еще один external ID etc для того чтобы сделать grandchild, я не собирался возиться с этим. ID надо удалить или переименовать потому что он автоматически маппится во время upsert и от этого нельзя избавиться. дальше нажимаем upsert и выбираем наш CITYTEST. Data loader детектит что на паренте есть пододящий для маппинга external id и дает нам его навыбор. https://i.imgur.com/WJIdK7w.jpg собственно выбираем наше поле X__c как External ID. потом еще раз маппим внутри mapping dialog. Конечный результат: https://i.imgur.com/4t2VFLp.jpg нажимаем finish и чайлды маппятся по старому парент ID загруженному в другое поле. После того как data load процесс закончен поле X__c можно удалить. Если ты хочешь еще загрузить грандчайлда то надо вместо удаления ID с CITY создать новое поле Y__c и загрузить в него старые ID CITY чтобы повторить потом процесс.
нужно следовать принципам из туториала https://help.salesforce.com/articleView?id=000320964&type=1&mode=1
БЛЯ!
Вот оно че! А я то только делал insert/updated, у них все одинаковое, а до upserta не дошел, подумал что там тоже самое! А в нем оказывается можно настраивать matching!! От оно че, Михалыч!
Спасибо!
[quote="Андрей"]нужно следовать принципам из туториала https://help.salesforce.com/articleView?id=000320964&type=1&mode=1[/quote] БЛЯ! Вот оно че! А я то только делал insert/updated, у них все одинаковое, а до upserta не дошел, подумал что там тоже самое! А в нем оказывается можно настраивать matching!! От оно че, Михалыч! [size=30][color=green]Спасибо![/color][/size]
Вообще если кому интересно, то можно легко автоматизировать миграцию данных на pure python (как и на любом другом ЯП) и скрипт будет не таким сложным. И не надо будет заморачиваться с дополнительными ExternalID полями. Понятно что для одноразового использования и для двух связанных объектов это перебор, но если миграцию данных надо автоматизировать и связанных объектов будет десятки то мутить скрипт самое то.
Используем следующие SF API enpdoints:
1. Достаем данные - https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm
2. Загружаем данные - https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_sobject_tree_flat.htm
Вся магия кроется в referenceId. Переносим Id в attributes.referenceId и после загрузки на орг получаем мапу в таком виде: referenceId (он же Old Id) -> New Id (по второй ссылке можно глянуть живой пример ответа с мапой). Проходимся по child рекордам, заменяем все parent old ID на новый ID и загружаем. Повторяем процедуру для все child объектов вниз по иерархии.
Профит!
Из особенностей которые немного усложняют скрипт:
- данные достаются пачками до 2000 записей, поэтому надо доставать в цикле пока все записи не достанутся.
- данные загружаются пачками по 200 записей, поэтому тоже делаем цикл для загрузки пачками по 200.
- self reference, циклические ссылки разруливаются немного сложнее, но тоже без проблем.
- ну и авторизацию для API замутить придется (либо либу использовать какую, хотя совсем не обязательно)
Способ рабочий и сильно кастомизируемый ввиду полного контроля над процессом в коде. Данные на лету можно менять, валидировать. Скрипт можно заливать куда угодно в отличии от всяких тулов.
Вообще если кому интересно, то можно легко автоматизировать миграцию данных на pure python (как и на любом другом ЯП) и скрипт будет не таким сложным. И не надо будет заморачиваться с дополнительными ExternalID полями. Понятно что для одноразового использования и для двух связанных объектов это перебор, но если миграцию данных надо автоматизировать и связанных объектов будет десятки то мутить скрипт самое то. Используем следующие SF API enpdoints: 1. Достаем данные - https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_query.htm 2. Загружаем данные - https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_sobject_tree_flat.htm [b]Вся магия кроется в referenceId[/b]. Переносим Id в attributes.referenceId и после загрузки на орг получаем мапу в таком виде: referenceId (он же Old Id) -> New Id (по второй ссылке можно глянуть живой пример ответа с мапой). Проходимся по child рекордам, заменяем все parent old ID на новый ID и загружаем. Повторяем процедуру для все child объектов вниз по иерархии. Профит! Из особенностей которые немного усложняют скрипт: - данные достаются пачками до 2000 записей, поэтому надо доставать в цикле пока все записи не достанутся. - данные загружаются пачками по 200 записей, поэтому тоже делаем цикл для загрузки пачками по 200. - self reference, циклические ссылки разруливаются немного сложнее, но тоже без проблем. - ну и авторизацию для API замутить придется (либо либу использовать какую, хотя совсем не обязательно) Способ рабочий и сильно кастомизируемый ввиду полного контроля над процессом в коде. Данные на лету можно менять, валидировать. Скрипт можно заливать куда угодно в отличии от всяких тулов.