
Ma ma szeretnĂ©m bemutatni a Habr olvasĂłinak egy Python nyelven kĂ©szĂŒlt eszközt, amely a PostgreSQL adatbĂĄzisok tĂĄblĂĄinak fĂŒggĆsĂ©geivel foglalkozik.
Az eszköz API-ja egyszerƱ, Ă©s hĂĄrom mĂłdszerbĆl ĂĄll:
- archive_table â rekurzĂv archĂvĂĄlĂĄs/törlĂ©s a megadott elsĆdleges kulcsokkal rendelkezĆ sorokbĂłl
- get_table_references â tĂĄblĂĄzatok fĂŒggĆsĂ©geinek keresĂ©se (megjelenĂti azokat a tĂĄblĂĄzatokat, amelyek hivatkoznak a megadottra, valamint azokat, amelyek hivatkoznak rĂĄ)
- get_rows_references â keresĂ©s mĂĄs tĂĄblĂĄzatokban, amelyek hivatkoznak a megadott tĂĄblĂĄzatban szereplĆ adott sorokra
Håttér
A nevem Oleg Borzov, CRM fejlesztĆ vagyok a jelzĂĄloghitel-kezelĆ csapatban a DomkliknĂ©l.
CRM rendszerĂŒnk fĆ adatbĂĄzisa az egyik legnagyobb a cĂ©g ajĂĄnlatain belĂŒl. Ez a legöregebb is: mĂĄr a projekt megkezdĂ©sĂ©nĂ©l lĂ©trejött, amikor a fĂĄk mĂ©g nagyok voltak, a Domklik egy startup, Ă©s a divatos, Python alapĂș aszinkron keretrendszer helyett egy hatalmas monolit futott PHP-n.
A PHP-rĂłl Pythonra valĂł ĂĄtĂĄllĂĄs nagyon hosszĂș folyamat volt, ami megkövetelte mindkĂ©t rendszer egyidejƱ tĂĄmogatĂĄsĂĄt, ami befolyĂĄsolta az adatbĂĄzis tervezĂ©sĂ©t.
Ennek eredmĂ©nyekĂ©nt egy olyan adatbĂĄzist kaptunk, amely rengeteg erĆsen összekapcsolt Ă©s hatalmas mĂ©retƱ tĂĄblĂĄbĂłl ĂĄll, kĂŒlönbözĆ tĂpusĂș lekĂ©rdezĂ©sekhez rengeteg indexszel. Mindez negatĂvan hat az adatbĂĄzis teljesĂtmĂ©nyĂ©re: a nagy tĂĄblĂĄk Ă©s a sok összefĂŒggĂ©s miatt folyamatosan nĆ a lekĂ©rdezĂ©sek összetettsĂ©ge, ami kĂŒlönösen kritikus a legnagyobb terhelĂ©s alatt ĂĄllĂł tĂĄblĂĄk esetĂ©ben.
Az adatbĂĄzis terhelĂ©sĂ©nek csökkentĂ©se Ă©rdekĂ©ben Ășgy döntöttĂŒnk, hogy Ărunk egy szkriptet, amely naponta, cron idĆzĂtĂ©ssel ĂĄthelyezi a rĂ©gi bejegyzĂ©seket a legnagyobb Ă©s legnagyobb terhelĂ©sƱ tĂĄblĂĄkbĂłl archĂv tĂĄblĂĄkba (pĂ©ldĂĄul a task be. task_archive).
Ez a feladat bonyolultabb a tĂĄblĂĄk közötti sok kapcsolat miatt: csupĂĄn ĂĄthelyezni a sorokat a task be. task_archive nem elegendĆ, elĆbb ugyanezt rekurzĂvan el kell vĂ©gezni minden hivatkozĂłval rendelkezĆ task tĂĄblĂĄn.
Megmutatom egy pĂ©lda segĂtsĂ©gĂ©vel :

TegyĂŒk fel, hogy törölni kell a bejegyzĂ©seket a Flights. Ez nem lesz lehetsĂ©ges a Postgres szĂĄmĂĄra: elĆször is a hivatkozĂł tĂĄblĂĄkbĂłl kell törölni a bejegyzĂ©seket, Ă©s ezt rekurzĂvan kell folytatni a hivatkozott tĂĄblĂĄkig, amelyeket senki sem hivatkozott.
PĂ©ldĂĄnkban hivatkozik a Flights Ticket_flights -ra, Ă©s arra hivatkozik aBoarding_passes EzĂ©rt Ăgy kell törölni:.
Megkapjuk az elsĆdleges kulcsok (Primary Keys, PK) Ă©rtĂ©keit a
- , amelyek hivatkoznak a törlendĆ sorokra a
-ra, Ă©s arra hivatkozik aMegkapjuk a PK sorait.Flights. - Megkapjuk a törlendĆ sorok PK-jĂ©t.
EzĂ©rt Ăgy kell törölni:, amelyek a-ra, Ă©s arra hivatkozik a. - Sorok eltĂĄvolĂtĂĄsa PK alapjĂĄn a 2. pontbĂłl a tĂĄblĂĄzatban
EzĂ©rt Ăgy kell törölni:. - Sorok eltĂĄvolĂtĂĄsa PK alapjĂĄn az 1. pontban
-ra, Ă©s arra hivatkozik a. - Sorok eltĂĄvolĂtĂĄsa a
Flights.
VĂ©gĂŒl a PgGraph nevƱ eszköz szĂŒletett, amelyet nyĂlt forrĂĄskĂłdĂșvĂĄ akartunk tenni.
HasznĂĄlati ĂștmutatĂł
Az eszköz két hasznålati módot tåmogat:
- HĂvĂĄs a parancssorbĂłl (
pggraph âŠ). - HasznĂĄlat Python kĂłdban (osztĂĄly
PgGraphApi).
TelepĂtĂ©s Ă©s beĂĄllĂtĂĄs
ElĆször telepĂteni kell az eszközt a Pypi-tĂĄrolĂłbĂłl:
pip3 install pggraphEzutån létre kell hozni egy config.ini fåjlt a helyi gépen az adatbåzis és a mentési szkriptek konfiguråciójåval:
[db]
host = localhost
port = 5432
user = postgres
password = postgres
dbname = postgres
schema = public ; Opcionålis paraméter, alapértelmezett értékkel megadva
[archive] ; Ezt a rĂ©szt nem szĂŒksĂ©ges kitölteni, az alĂĄbbiak az alapĂ©rtelmezett Ă©rtĂ©kek
is_debug = false
chunk_size = 1000
max_depth = 20
to_archive = true
archive_suffix = 'archive'FuttatĂĄs a konzolbĂłl
BeĂĄllĂtĂĄsok
$ pggraph -h
usage: pggraph action [-h] --table TABLE [--ids IDS] [--config_path CONFIG_PATH]
positional arguments:
action kötelezĆ tevĂ©kenysĂ©g: archive_table, get_table_references, get_rows_references
optional arguments:
-h, --help ez a sĂșgĂł megjelenĂtĂ©se Ă©s kilĂ©pĂ©s
--table TABLE tĂĄblĂĄzat neve
--ids IDS elsĆdleges kulcs azonosĂtĂłk, vesszĆvel elvĂĄlasztva, pl. 1,2,3
--config_path CONFIG_PATH path a config.ini-hez
--log_path LOG_PATH naplĂł könyvtĂĄrĂĄnak elĂ©rĂ©si Ăștja
--log_level LOG_LEVEL naplĂłzĂĄsi szint (debug, info, error)PozicionĂĄlis argumentumok:
actionâ szĂŒksĂ©ges tevĂ©kenysĂ©g:archive_table,get_table_referencesvagyget_rows_references.
Név szerint argumentumok:
--config_pathâ az elĂ©rĂ©si Ășt a konfigurĂĄciĂłs fĂĄjlhoz;--tableâ a tĂĄblĂĄzat, amelyen a mƱveletet vĂ©gre szeretnĂ©d hajtani;--idsâ id-k listĂĄja vesszĆvel elvĂĄlasztva, pĂ©ldĂĄul,1,2,3(opcionĂĄlis paramĂ©ter);--log_pathâ a naplĂłkhoz tartozĂł mappa elĂ©rĂ©si Ăștja (opcionĂĄlis paramĂ©ter, alapĂ©rtelmezett â a felhasznĂĄlĂłi mappa);--log_levelâ naplĂłzĂĄsi szint (opcionĂĄlis paramĂ©ter, alapĂ©rtelmezett â INFO).
ParancsmintĂĄk
TĂĄbla archivĂĄlĂĄsa
Az eszköz fĆ funkciĂłja az adatok archivĂĄlĂĄsa, azaz a sorok ĂĄthelyezĂ©se a fĆ tĂĄblĂĄbĂłl az archĂvumba (pĂ©ldĂĄul a books be. books_archive).
Emellett tĂĄmogatja az archivĂĄlĂĄs nĂ©lkĂŒli törlĂ©st is: ehhez a config.ini fĂĄjlban a to_archive = false).
KötelezĆ paramĂ©terek â config_path, table Ă©s ids.
A futtatĂĄs utĂĄn rekurzĂvan törlĂ©sre kerĂŒlnek a bejegyzĂ©sek ids a tĂĄblĂĄzatban table Ă©s minden hivatkozĂł tĂĄblĂĄban.
$ pggraph archive_table --config_path config.hw.local.ini --table flights --ids 1,2,3
2020-06-20 19:27:44 INFO: flights - KEZDĂS
2020-06-20 19:27:44 INFO: flights - kezdje el archive_recursive 3 sor (mélység=0)
2020-06-20 19:27:44 INFO: KEZDĂS ARCHĂVUM HĂVĂ TĂBLĂK
2020-06-20 19:27:44 INFO: ticket_flights - kezdje el archive_recursive 3 sor (mélység=1)
2020-06-20 19:27:44 INFO: KEZDĂS ARCHĂVUM HĂVĂ TĂBLĂK
2020-06-20 19:27:44 INFO: boarding_passes - kezdje el archive_recursive 3 sor (mélység=2)
2020-06-20 19:27:44 INFO: KEZDĂS ARCHĂVUM HĂVĂ TĂBLĂK
2020-06-20 19:27:44 INFO: ARCHĂVUM HĂVĂ TĂBLĂK VĂGE
2020-06-20 19:27:44 INFO: boarding_passes - archive_by_ids 3 sor ticket_no, flight_id szerint
2020-06-20 19:27:44 INFO: boarding_passes - kezdje el archive_recursive 3 sor (mélység=2)
2020-06-20 19:27:44 INFO: KEZDĂS ARCHĂVUM HĂVĂ TĂBLĂK
2020-06-20 19:27:44 INFO: ARCHĂVUM HĂVĂ TĂBLĂK VĂGE
2020-06-20 19:27:44 INFO: boarding_passes - archive_by_ids 3 sor ticket_no, flight_id szerint
2020-06-20 19:27:44 INFO: boarding_passes - kezdje el archive_recursive 3 sor (mélység=2)
2020-06-20 19:27:44 INFO: KEZDĂS ARCHĂVUM HĂVĂ TĂBLĂK
2020-06-20 19:27:44 INFO: ARCHĂVUM HĂVĂ TĂBLĂK VĂGE
2020-06-20 19:27:44 INFO: boarding_passes - archive_by_ids 3 sor ticket_no, flight_id szerint
2020-06-20 19:27:44 INFO: boarding_passes - kezdje el archive_recursive 3 sor (mélység=2)
2020-06-20 19:27:44 INFO: KEZDĂS ARCHĂVUM HĂVĂ TĂBLĂK
2020-06-20 19:27:44 INFO: ARCHĂVUM HĂVĂ TĂBLĂK VĂGE
2020-06-20 19:27:44 INFO: boarding_passes - archive_by_ids 3 sor ticket_no, flight_id szerint
2020-06-20 19:27:44 INFO: ARCHĂVUM HĂVĂ TĂBLĂK VĂGE
2020-06-20 19:27:44 INFO: ticket_flights - archive_by_ids 3 sor ticket_no, flight_id szerint
2020-06-20 19:27:44 INFO: ARCHĂVUM HĂVĂ TĂBLĂK VĂGE
2020-06-20 19:27:44 INFO: flights - archive_by_ids 3 sor id szerint
2020-06-20 19:27:44 INFO: flights - VĂGEA megadott tĂĄbla fĂŒggĆsĂ©geinek keresĂ©se
FĂŒggĆsĂ©gek keresĂ©sĂ©re szolgĂĄlĂł funkciĂł a megadott tĂĄblĂĄhoz table. KötelezĆ paramĂ©terek â config_path Ă©s table.
A futtatĂĄs utĂĄn a kĂ©pernyĆre egy szĂłtĂĄr kerĂŒl kiĂrĂĄsra, ahol:
in_refsâ a szĂłtar, amely a megadott tĂĄblĂĄra hivatkozĂł tĂĄblĂĄkat tartalmazza, ahol a kulcs â a tĂĄbla neve, az Ă©rtĂ©k â a KĂŒlsĆ Kulcs objektumok listĂĄja (pk_mainâ az elsĆdleges kulcs a fĆ tĂĄblĂĄban,pk_refâ az elsĆdleges kulcs a hivatkozĂł tĂĄblĂĄban,fk_refâ a megadott tĂĄblĂĄra hivatkozĂł kĂŒlsĆ kulcs neve);out_refsâ a tĂĄblĂĄk szĂłtĂĄra, amelyekre ez a tĂĄbla hivatkozik.
$ pggraph get_table_references --config_path config.hw.local.ini --table flights
{'in_refs': {'ticket_flights': [ForeignKey(pk_main='flight_id', pk_ref='ticket_no, flight_id', fk_ref='flight_id')]},
'out_refs': {'aircrafts': [ForeignKey(pk_main='aircraft_code', pk_ref='flight_id', fk_ref='aircraft_code')],
'airports': [ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='arrival_airport'),
ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='departure_airport')]}}HivatkozĂĄsok keresĂ©se a megadott elsĆdleges kulcsĂș sorokra
FĂŒggvĂ©ny sorok keresĂ©sĂ©re mĂĄs tĂĄblĂĄkban, amelyek kĂŒlsĆ kulcskĂ©nt hivatkoznak a sorokra ids a tĂĄblĂĄkban table. KötelezĆ paramĂ©terek â config_path, table Ă©s ids.
A program indĂtĂĄsakor egy szĂłtĂĄr jelenik meg a következĆ struktĂșrĂĄval:
{
pk_id_1: {
reffering_table_name_1: {
foreign_key_1: [
{row_pk_1: value, row_pk_2: value},
...
],
...
},
...
},
pk_id_2: {...},
...
}PĂ©lda hĂvĂĄsra:
$ pggraph get_rows_references --config_path config.hw.local.ini --table flights --ids 1,2,3
{1: {'ticket_flights': {'flight_id': [{'flight_id': 1,
'ticket_no': '0005432816945'},
{'flight_id': 1,
'ticket_no': '0005432816941'}]}},
2: {'ticket_flights': {'flight_id': [{'flight_id': 2,
'ticket_no': '0005433101832'},
{'flight_id': 2,
'ticket_no': '0005433101864'},
{'flight_id': 2,
'ticket_no': '0005432919715'}]}},
3: {'ticket_flights': {'flight_id': [{'flight_id': 3,
'ticket_no': '0005432817560'},
{'flight_id': 3,
'ticket_no': '0005432817568'},
{'flight_id': 3,
'ticket_no': '0005432817559'}]}}}HasznĂĄlat kĂłdban
A konzolon valĂł indĂtĂĄson kĂvĂŒl a könyvtĂĄrat Python kĂłdban is hasznĂĄlhatjuk. Az alĂĄbbiakban az interaktĂv iPython környezetben valĂł hĂvĂĄs pĂ©ldĂĄi lĂĄthatĂłk.
TĂĄbla archivĂĄlĂĄsa
>>> from pg_graph.main import setup_logging
>>> setup_logging(log_level='DEBUG')
>>> from pg_graph.api import PgGraphApi
>>> api = PgGraphApi('config.hw.local.ini')
>>> api.archive_table('flights', [4,5])
2020-06-20 23:12:08 INFO: flights - KEZDĆDIK
2020-06-20 23:12:08 INFO: flights - elkezd archive_recursive 2 sor (mélység=0)
2020-06-20 23:12:08 INFO: KEZDĆDIK AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA
2020-06-20 23:12:08 DEBUG: ticket_flights - ForeignKey(pk_main='flight_id', pk_ref='flight_id, ticket_no', fk_ref='flight_id')
2020-06-20 23:12:08 DEBUG: SQL('SELECT flight_id, ticket_no FROM bookings.ticket_flights WHERE (flight_id) IN (%s, %s)')
2020-06-20 23:12:08 INFO: ticket_flights - elkezd archive_recursive 30 sor (mélység=1)
2020-06-20 23:12:08 INFO: KEZDĆDIK AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA
2020-06-20 23:12:08 DEBUG: boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: boarding_passes - archive_by_fk 30 sor ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no') szerint
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS boarding_passes by FK flight_id, ticket_no - 30 sor
2020-06-20 23:12:08 INFO: AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA VĂGEZTETT
2020-06-20 23:12:08 INFO: ticket_flights - archive_by_ids 30 sor by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS ticket_flights by flight_id, ticket_no - 30 sor
2020-06-20 23:12:08 DEBUG: INSERT INTO ticket_flights_archive - 30 sor
2020-06-20 23:12:08 INFO: ticket_flights - elkezd archive_recursive 30 sor (mélység=1)
2020-06-20 23:12:08 INFO: KEZDĆDIK AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA
2020-06-20 23:12:08 DEBUG: boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: boarding_passes - archive_by_fk 30 sor ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no') szerint
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS boarding_passes by FK flight_id, ticket_no - 30 sor
2020-06-20 23:12:08 INFO: AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA VĂGEZTETT
2020-06-20 23:12:08 INFO: ticket_flights - archive_by_ids 30 sor by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS ticket_flights by flight_id, ticket_no - 30 sor
2020-06-20 23:12:08 DEBUG: INSERT INTO ticket_flights_archive - 30 sor
2020-06-20 23:12:08 INFO: ticket_flights - elkezd archive_recursive 30 sor (mélység=1)
2020-06-20 23:12:08 INFO: KEZDĆDIK AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA
2020-06-20 23:12:08 DEBUG: boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: boarding_passes - archive_by_fk 30 sor ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no') szerint
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS boarding_passes by FK flight_id, ticket_no - 30 sor
2020-06-20 23:12:08 INFO: AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA VĂGEZTETT
2020-06-20 23:12:08 INFO: ticket_flights - archive_by_ids 30 sor by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS ticket_flights by flight_id, ticket_no - 30 sor
2020-06-20 23:12:08 DEBUG: INSERT INTO ticket_flights_archive - 30 sor
2020-06-20 23:12:08 INFO: ticket_flights - elkezd archive_recursive 3 sor (mélység=1)
2020-06-20 23:12:08 INFO: KEZDĆDIK AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA
2020-06-20 23:12:08 DEBUG: boarding_passes - ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no')
2020-06-20 23:12:08 INFO: boarding_passes - archive_by_fk 3 sor ForeignKey(pk_main='flight_id, ticket_no', pk_ref='flight_id, ticket_no', fk_ref='flight_id, ticket_no') szerint
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.boarding_passes_archive (LIKE bookings.boarding_passes)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS boarding_passes by FK flight_id, ticket_no - 3 sor
2020-06-20 23:12:08 INFO: AZ REFERENCIA TĂBLĂK ARCHIVĂLĂSA VĂGEZTETT
2020-06-20 23:12:08 INFO: ticket_flights - archive_by_ids 3 sor by flight_id, ticket_no
2020-06-20 23:12:08 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.ticket_flights_archive (LIKE bookings.ticket_flights)')
2020-06-20 23:12:08 DEBUG: TĂRLĂS ticket_flights by flight_id, ticket_no - 3 sor
2020-06-20 23:12:08 DEBUG: INSERT INTO ticket_flights_archive - 3 sor
2020-06-20 23:12:08 INFO: AZ ARCHIVĂLĂS REFERENCIA TĂBLĂK VĂGEZTEK
2020-06-20 23:12:08 INFO: flights - archive_by_ids 2 sor by flight_id
2020-06-20 23:12:09 DEBUG: SQL('CREATE TABLE IF NOT EXISTS bookings.flights_archive (LIKE bookings.flights)')
2020-06-20 23:12:09 DEBUG: TĂRLĂS flights by flight_id - 2 sor
2020-06-20 23:12:09 DEBUG: INSERT INTO flights_archive - 2 sor
2020-06-20 23:12:09 INFO: flights - ARCHIVĂLĂS VĂGEA megadott tĂĄbla fĂŒggĆsĂ©geinek keresĂ©se
>>> from pg_graph.api import PgGraphApi
>>> from pprint import pprint
>>> api = PgGraphApi('config.hw.local.ini')
>>> res = api.get_table_references('flights')
>>> pprint(res)
{'in_refs': {'ticket_flights': [ForeignKey(pk_main='flight_id', pk_ref='flight_id, ticket_no', fk_ref='flight_id')]},
'out_refs': {'aircrafts': [ForeignKey(pk_main='aircraft_code', pk_ref='flight_id', fk_ref='aircraft_code')],
'airports': [ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='arrival_airport'),
ForeignKey(pk_main='airport_code', pk_ref='flight_id', fk_ref='departure_airport')]}}HivatkozĂĄsok keresĂ©se a megadott elsĆdleges kulcsĂș sorokra
>>> from pg_graph.api import PgGraphApi
>>> from pprint import pprint
>>> api = PgGraphApi('config.hw.local.ini')
>>> rows = api.get_rows_references('flights', [1,2,3])
>>> pprint(rows)
{1: {'ticket_flights': {'flight_id': [{'flight_id': 1,
'ticket_no': '0005432816945'},
{'flight_id': 1,
'ticket_no': '0005432816941'}]}},
2: {'ticket_flights': {'flight_id': [{'flight_id': 2,
'ticket_no': '0005433101832'},
{'flight_id': 2,
'ticket_no': '0005433101864'},
{'flight_id': 2,
'ticket_no': '0005432919715'}]}},
3: {'ticket_flights': {'flight_id': [{'flight_id': 3,
'ticket_no': '0005432817560'},
{'flight_id': 3,
'ticket_no': '0005432817568'},
{'flight_id': 3,
'ticket_no': '0005432817559'}]}}}A könyvtĂĄr forrĂĄskĂłdja elĂ©rhetĆ a MIT licenc alatt, valamint a következĆ tĂĄrolĂłban .
Ărömmel vĂĄrom a megjegyzĂ©seket, hozzĂĄjĂĄrulĂĄsokat Ă©s javaslatokat.
A kĂ©rdĂ©sekre igyekszem vĂĄlaszolni a lehetĆsĂ©geim szerint itt Ă©s a tĂĄrolĂłban.
ForrĂĄs: habr.com
