{"componentChunkName":"component---src-templates-post-tsx","path":"/blog/sql-to-json","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"7c9c91cb-5395-5a07-a567-7e03225e4c86","excerpt":"Disposer d’une veille permanente sur tous les évènements de la vie juridique de\nses prospects, clients et…","frontmatter":{"title":"Accès aux bases RNCS-SIRENE-BODACC","path":"/blog/bases-rncs-sirene-bodacc","tags":["product"],"date":"02.22.2021","description":"Profitez d'une information permanente sur la vie juridique de tous vos clients, prospects et fournisseurs","author":{"firstname":"Philippe","lastname":"BERNARD","jobTitle":"CEO","linkedin":"https://www.linkedin.com/in/philippe-bernard-0b776b205/","github":null,"twitter":null,"profilePic":{"childImageSharp":{"fixed":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAMEBQEC/8QAFwEAAwEAAAAAAAAAAAAAAAAAAAECA//aAAwDAQACEAMQAAAB0o63Feoqnn5nKJAz/8QAGxAAAgMAAwAAAAAAAAAAAAAAAQIAAxETITH/2gAIAQEAAQUCstAiXd8iy3cpBYz0IAq7P//EABYRAQEBAAAAAAAAAAAAAAAAABEBIP/aAAgBAwEBPwGBj//EABYRAQEBAAAAAAAAAAAAAAAAABABQf/aAAgBAgEBPwHSH//EABkQAAMAAwAAAAAAAAAAAAAAAAAQIQERMf/aAAgBAQAGPwKHYtvJF//EABwQAQADAAIDAAAAAAAAAAAAAAEAESExUUFhsf/aAAgBAQABPyEAHzMt2U9kNArOyeM5txEafkSm9QSGiWn/2gAMAwEAAgADAAAAEBD4ff/EABgRAAIDAAAAAAAAAAAAAAAAAAABECEx/9oACAEDAQE/EA0LI//EABgRAAIDAAAAAAAAAAAAAAAAAAABEBEh/9oACAECAQE/EHY2X//EABsQAQACAwEBAAAAAAAAAAAAAAEAESExQZFR/9oACAEBAAE/EK0DsuIFJ2BzeeT7PyPHXdDUrVozUwPCIhpOMFpF4CUC8dZZuvJ//9k=","width":44,"height":44,"src":"/static/1e9862a73c568a5a3252d8a78df9a5b6/0b3c4/philippe_bernard.jpg","srcSet":"/static/1e9862a73c568a5a3252d8a78df9a5b6/0b3c4/philippe_bernard.jpg 1x,\n/static/1e9862a73c568a5a3252d8a78df9a5b6/84a5f/philippe_bernard.jpg 1.5x,\n/static/1e9862a73c568a5a3252d8a78df9a5b6/6ac25/philippe_bernard.jpg 2x"}}}},"cover":{"childImageSharp":{"fluid":{"tracedSVG":"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='400'%20height='225'%20viewBox='0%200%20400%20225'%20preserveAspectRatio='none'%3e%3cpath%20d='M0%2043v44l7%201c8%201%2012%204%2012%207l-3-1-9-4-6-2-1%2068v68l5-3%204-2%203%203%202%203h88a485%20485%200%200088-1c10%202%20210%202%20210-1l1-112V0H254C123%200%20108%200%20111%202c3%201%205%203%205%204h-2c-4-4-16-6-34-6H63v5a23%2023%200%2001-2%2012c-1%202-5%203-5%201l1-2c1%200%203-11%202-14%200-2-2-2-30-2H0v43m153-30c-1%202-1%202%201%201a186%20186%200%200164%209%20510%20510%200%200117%202l-49-10c-25-5-30-5-33-2m67%2030l-1%205-1%204h-10l-13-1c-2-1-3%200-12%2020-11%2021-11%2021-9%2023%204%205%2015%208%2022%205%202-1%202-1%202-9l-3-37%205%201%209%201c7%201%207%203%200%2030-5%2021-5%2022-8%2023-11%202-10%204%204%207l14%201c0-2-4-6-6-6l-1-1a332%20332%200%20019-51l7%201%209%202%203%201-10%2020-10%2020%202%203c3%203%2012%205%2017%205%208-2%207-1%205-26-1-26-1-25-5-25l-11-3-8-3V43m-37%2032l-8%2016%205%201%205%201%203-17%203-17-8%2016m10-14l-6%2031%204%203%205%201-1-11-2-24m48%2011a10036%2010036%200%2001-7%2031l10%202a226%20226%200%2000-3-33m-10%2013l-8%2016%209%201%207-33-8%2016m98-4c-1%209-1%2010%203%2011%203%200%205%200%206-2h2c0%204%206%206%208%203h1c0%202%203%203%203%201%201-1%201-1%202%201%202%203%207%203%208%200%201-2%201-2%201%200s1%203%202%203c2%201%202%201%202-1%200-5%200-6%201-3%201%206%205%208%208%204%204-5%201-11-5-9-2%201-2%201-3-2%200-2-2-3-4%200h-9c-1%201-1%201-1-2%200-4-2-5-3-1%200%202-2%203-2%201s-5-2-7-1h-1c0-3-3-6-7-7-4%200-4%200-5%204M65%2099l-3%201h2a228%20228%200%200151%209c4%201%207%204%207%206l1%201c2-2-2-7-5-8a416%20416%200%2000-53-9m146%2056l-2%207-9-2-8-2v-3l-1-3-10%207%204%206%203%205%201-3%201-4%2012%202%2011%202c3-11%204-17%203-18-3-2-4-1-5%206m-151-1l-2%204-2%202v2l1%203c-2%202%200%203%202%202h1c0%202%202%201%205-2l2-4%201-1v-4c0-4-1-5-2-3-1%201-2%201-2-1-1-1-2-1-4%202m35%2052a160%20160%200%200026%205%201258%201258%200%2000-26-5'%20fill='%232B2B2F'%20fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":1.7857142857142858,"src":"/static/1f9873236da2b321ef7cc0ad003cc85a/64b17/juridique-steemit.jpg","srcSet":"/static/1f9873236da2b321ef7cc0ad003cc85a/e94f2/juridique-steemit.jpg 100w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/4fa6c/juridique-steemit.jpg 200w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/64b17/juridique-steemit.jpg 400w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/39f27/juridique-steemit.jpg 600w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/a1eb1/juridique-steemit.jpg 800w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/a2128/juridique-steemit.jpg 3870w","srcWebp":"/static/1f9873236da2b321ef7cc0ad003cc85a/40a1d/juridique-steemit.webp","srcSetWebp":"/static/1f9873236da2b321ef7cc0ad003cc85a/bef64/juridique-steemit.webp 100w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/9e195/juridique-steemit.webp 200w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/40a1d/juridique-steemit.webp 400w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/6ef99/juridique-steemit.webp 600w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/b0751/juridique-steemit.webp 800w,\n/static/1f9873236da2b321ef7cc0ad003cc85a/7dfd4/juridique-steemit.webp 3870w","sizes":"(max-width: 400px) 100vw, 400px"}}}}}},{"node":{"id":"105bb2c5-f3e1-597f-b8dd-b39af2b48303","excerpt":"Toute entrée en relation, que ce soit entre deux organisations, entre une organisation et une personne…","frontmatter":{"title":"Gestion des consentements","path":"/blog/gestion-de-consentements","tags":["product"],"date":"02.08.2021","description":"Simplifiez-vous la vie. Avec eKee maîtrisez et automatisez la diffusion de vos données et documents","author":{"firstname":"Alexandre","lastname":"BERNARD","jobTitle":"CTO","linkedin":"https://www.linkedin.com/in/alexandre-bernard-388379150/","github":"https://github.com/Dot-H","twitter":"https://twitter.com/AIex_Bernard","profilePic":{"childImageSharp":{"fixed":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAMEAQX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAeR3Qz1g2Kj0JEIJ/8QAHBAAAgICAwAAAAAAAAAAAAAAAQIAAwQQESFB/9oACAEBAAEFAlLCNWhjYdgIqYTssLHWecAa/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEQETH/2gAIAQMBAT8BWFT/AP/EABkRAAEFAAAAAAAAAAAAAAAAAAABEBESIf/aAAgBAgEBPwGdLK//xAAbEAACAgMBAAAAAAAAAAAAAAAAAREhAiIxEP/aAAgBAQAGPwLVlZM1hol0UR5w4f/EABsQAAMAAgMAAAAAAAAAAAAAAAABESFRMUFx/9oACAEBAAE/IcaxU7gvfY0+hYJLKCRZaoky42IJypExu8o/Uf/aAAwDAQACAAMAAAAQEAd9/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEREP/aAAgBAwEBPxBFVJHn/8QAFhEBAQEAAAAAAAAAAAAAAAAAEAFR/9oACAECAQE/EMBh/8QAHBABAQEAAgMBAAAAAAAAAAAAAREAITFBUYGx/9oACAEBAAE/EFl6Zx+6t2CDtHfeIF4yp9HeVMwa6mzBAhuoPqhqZKV5plzh2hgVS903/9k=","width":44,"height":44,"src":"/static/cfc8adc7696e65a5c44783a546b17d1b/0b3c4/alexandre_bernard.jpg","srcSet":"/static/cfc8adc7696e65a5c44783a546b17d1b/0b3c4/alexandre_bernard.jpg 1x,\n/static/cfc8adc7696e65a5c44783a546b17d1b/84a5f/alexandre_bernard.jpg 1.5x,\n/static/cfc8adc7696e65a5c44783a546b17d1b/6ac25/alexandre_bernard.jpg 2x"}}}},"cover":{"childImageSharp":{"fluid":{"tracedSVG":"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='400'%20height='136'%20viewBox='0%200%20400%20136'%20preserveAspectRatio='none'%3e%3cpath%20d='M228%201l-3%201%204%206c3%205%204%207%203%209l2%209c3%208%202%209-4%2017l-3%206c1%202-2%206-8%2014l-3%206-3%206c-1%203-2%204-1%205%202%201%2019%200%2026-1%2015-2%2026-1%2026%203%200%202%204%206%205%205l1-4c0-5%202-3%202%202%200%206%202%2010%205%2013l3%204c1%203%206%206%2013%207%203%200%204%201%205%203%203%205%208%206%2022%206l13%201%208%203c7%204%2017%2010%2018%2012l21%201%2021%201v-25c0-33-1-63-2-63l-4%203-4%202-3%201h-1c0-1-4-2-9-2l-8-1-8-2-5-3-1-1-6-3-8-4-4-1-5-2c-5%201-5%200-5-2l1-4%202-4v-4h-4c-3%200-4%200-4-2l-1-1c-6%203-6%203-4%200l4-7%202-3h-3l-9-2-6-1-1-2%201-2h-36a1006%201006%200%2001-42%200m19%2053c-3%204-5%205-6%205l-5%202c-1%202-2%202-2%201-1-1-1-1-1%201v3l-1-1c1-1%200-2-1-3s-5%203-4%206l-1%201-12%209%2010-2a75%2075%200%200119-5l7-2c3-1%203-1%202-3l-1-10-1-8-3%206M1%20102v34h107l-18-9c-24-11-33-17-63-39L1%2068v34'%20fill='%232B2B2F'%20fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":2.9411764705882355,"src":"/static/93779433d6cc3535dadfa46d8e2ecd3b/d786d/cover.png","srcSet":"/static/93779433d6cc3535dadfa46d8e2ecd3b/0d540/cover.png 100w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/5224a/cover.png 200w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/d786d/cover.png 400w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/f8eb5/cover.png 600w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/f9ff4/cover.png 800w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/bd797/cover.png 1079w","srcWebp":"/static/93779433d6cc3535dadfa46d8e2ecd3b/40a1d/cover.webp","srcSetWebp":"/static/93779433d6cc3535dadfa46d8e2ecd3b/bef64/cover.webp 100w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/9e195/cover.webp 200w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/40a1d/cover.webp 400w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/6ef99/cover.webp 600w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/b0751/cover.webp 800w,\n/static/93779433d6cc3535dadfa46d8e2ecd3b/b3e5f/cover.webp 1079w","sizes":"(max-width: 400px) 100vw, 400px"}}}}}},{"node":{"id":"4ec5d28e-a744-53c8-9f98-a894bf5af0b4","excerpt":"La gestion de documents est bien souvent limitée à leur stockage. Quelle que soit la solution\nutilisée, il est…","frontmatter":{"title":"Gestion de documents","path":"/blog/gestion-de-documents","tags":["product"],"date":"02.15.2021","description":"Une Gestion Électronique de Documents parfaitement intégrée. Récupérez et classez efficacement vos documents et ceux issus de vos contacts","author":{"firstname":"Alexandre","lastname":"BERNARD","jobTitle":"CTO","linkedin":"https://www.linkedin.com/in/alexandre-bernard-388379150/","github":"https://github.com/Dot-H","twitter":"https://twitter.com/AIex_Bernard","profilePic":{"childImageSharp":{"fixed":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAQEBAQAAAAAAAAAAAAAAAAMEAQX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAeR3Qz1g2Kj0JEIJ/8QAHBAAAgICAwAAAAAAAAAAAAAAAQIAAwQQESFB/9oACAEBAAEFAlLCNWhjYdgIqYTssLHWecAa/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEQETH/2gAIAQMBAT8BWFT/AP/EABkRAAEFAAAAAAAAAAAAAAAAAAABEBESIf/aAAgBAgEBPwGdLK//xAAbEAACAgMBAAAAAAAAAAAAAAAAAREhAiIxEP/aAAgBAQAGPwLVlZM1hol0UR5w4f/EABsQAAMAAgMAAAAAAAAAAAAAAAABESFRMUFx/9oACAEBAAE/IcaxU7gvfY0+hYJLKCRZaoky42IJypExu8o/Uf/aAAwDAQACAAMAAAAQEAd9/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEREP/aAAgBAwEBPxBFVJHn/8QAFhEBAQEAAAAAAAAAAAAAAAAAEAFR/9oACAECAQE/EMBh/8QAHBABAQEAAgMBAAAAAAAAAAAAAREAITFBUYGx/9oACAEBAAE/EFl6Zx+6t2CDtHfeIF4yp9HeVMwa6mzBAhuoPqhqZKV5plzh2hgVS903/9k=","width":44,"height":44,"src":"/static/cfc8adc7696e65a5c44783a546b17d1b/0b3c4/alexandre_bernard.jpg","srcSet":"/static/cfc8adc7696e65a5c44783a546b17d1b/0b3c4/alexandre_bernard.jpg 1x,\n/static/cfc8adc7696e65a5c44783a546b17d1b/84a5f/alexandre_bernard.jpg 1.5x,\n/static/cfc8adc7696e65a5c44783a546b17d1b/6ac25/alexandre_bernard.jpg 2x"}}}},"cover":{"childImageSharp":{"fluid":{"tracedSVG":"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='400'%20height='170'%20viewBox='0%200%20400%20170'%20preserveAspectRatio='none'%3e%3cpath%20d='M0%204l1%204v1L0%2090v80h160l1-2%201-2c0%202%205-2%205-4%201-3-3-4-5-2s-6%203-5%201v-2c-1-2-1-2%207-2%204%200%207%200%206-1-2%200-3-2-1-2%201-1%200-1-2-1l-5-1%202-1c1%201%202%200%202-1s-1-2-3-2h-2l2-2c2-2%202-2%200-3l-3-2c-2-1-2-1%200-1h3l-3-1h-7l-2-1h2c3%200%204-1%202-3s-13-5-14-3l-3%201c-2%200-2%200%200-2%204-3%203-4-1-3s-10%200-9-1c0-2-9%200-10%201l-3%201-10%204-8%203%2016-11c2%200%201-1-3-4l-3-4-5%204-8%204c-4%201-5%202-3%203v1l-2%201-4%201-4%201-5%201c-4%200-5%200-4%201%200%201-3%201-8-1l-3-1-4-2c-4-1-7-1-7%201v1l-2-1c0-1-1-2-3-2l-2-2-1-3-2-2h-2c-2%202-2%202-3-2-1-3-1-3%201-2%201%202%201%202%202%201l1-3%201-1c7%201%209%200%209-2v-2l2-1%201-2%201%201h1l3-1c2%202%207%202%207%201-1-2%207-4%208-2%201%201%201%201-1%201-2-1-2-1-1%201%202%203%204%204%205%203%200-2%201-1%204%201%204%202%203%202%2013%202%2013-1%2021%200%2022%201l1%201%201-1h3c4%200%205-1%203-3-2%200%201-2%204-2%201%200%202%200%201%202h2v1c-4%203%200%203%205%200%204-2%207-3%2010-2%204%200%2013-5%2011-7v-1l1-1h-7c-6%200-9-1-4-2v-1l-2-1c0-2-1-2-4-2l-7-1-4-2h3c3%200%203%200%202-1-4-2-31-1-33%202v3c0%202%200%202-2%200l-3-3c0-2-2-3-6-3-2%200-2%200-2-3l-1-2c-2-1%201-3%205-3s6-2%204-4H77c-9-3-13-1-9%203l1%203c-1%203%200%205%205%206%205%200%206%202%201%202l-12%203%202%202%201%201-4%202h-2l-1-1-1-1%202-1c2%200%201-3-2-4h-2l3-3c4-3%204-4%202-5l-2-4c-1-2-3-2-6-2l-1-1-3-1h-2l2%202c3%201%203%203%200%203-2%200-2%204%200%205%203%201%202%202-1%202l-6-2-8-4c-5-1-6-2%200-3l4-1c0-2-7-2-10-1h-4l-2-1c-1%200-3-1-3-3-2-4-2-5-1-5%203%200%207-4%206-6-2-2%201-5%204-5%204%200%204-1%202-3-3-3-5-3-6-1s-1%202-1-1l-1-4c-7-1-7-1%200-5%207-3%2010-7%208-10%200-2-2-3-2-3l-2-3c0-5-2-8-6-9l-6-4-3-4c-2-1-1-2%203-2%207-2%2011-1%2013%200v13l1%204c0%205%2012%2011%2025%2013%206%201%209%201%209-1%200-1%201-2%203-2l2-3%201-1%201-2v-2l-1-2-2-1c2%200%205-4%204-5l3-4%202-3h18c21%201%2023%200%2017-6-3-3-3-3-1-4l3%201%201%201%202%201%206%202%208%202c2%202%2015%203%2016%201l-1-2V9l2-2%201-1c1-1%201-1-1-3a2253%202253%200%2000-73-3H0v4m217-3v3l-1%206c-1%203-1%204%201%207%202%204%202%205%201%207-1%203-1%203%202%204l2%202%202%201c3%200%203%201%203%203s1%202%204%202l8%202%2010%201c9%200%2022%202%2029%204l5%202h-6l-9%201-5%202c-2%202-3%202-10%202l-9%201-5%203a213%20213%200%2000-13%202c-7%201-7%203%201%204l8%202%2015%201c14%200%2025%201%2025%202l-4%201-5%202-6%201h-4l16%2012%201-2c0-4%202-9%204-10h2l2-2c1-3%207-4%2020-3%2013%202%2039%202%2040%201l1-3c1-2%201-1%201%201v2l1%201-3%202h-2l-16-1c-15%201-17%201-18-1-1-1-8-1-9%201h1c2%200%202%200%202%202%200%201%201%202%203%202l4%201h-4c-4%200-4-2%201%2018l3%2017-8-5c-8-5-8-6-12-5l-8%204-3%201c-4%200-8%202-11%205l-4%203c-4%201-3%207%200%208%203%202%203%202%204%200h2c0%202-8%209-9%209v-2c2-3%201-4-1-1-2%202-2%202-1%203v3c-2%202-1%203%201%201l2-1-1%202c-2%201-2%202%200%204l2%205c0%203%200%204%202%204l2%203c0%201%2010%204%2016%204%205%200%208%202%206%205l1%201h2c0%203%203%206%204%204s5-3%208-2l2%201-4%204c-4%204-4%205-2%205l4-1c2-2%203-3%203-1l4-2%205-2c0%201%201%201-4%204l-3%202h4c4%200%204%200%203-1v-2l1%201%201%201h3l2-1c2%201%209-3%208-4l-4%202-3%201-4-2-4-1%203-3c3-2%205-3%203%200-2%202-1%202%202%201s4-3%201-3v-1l7-1c4%201%204%201%204-3%201-4%203-3%203%202l1%203c2-1%206%200%206%201l-1%201h-1l-2%203-1%203-1%201-1%201%2033%201h32V0h-91l-92%201m73%209l-4%206%202%203c2%200%202%201%202%203s7%206%2011%205l4%203c1%202%203%203%203%202l3%201h1l7-2c5-1%208-2%2010-4%203-2%204-2%207-2%205%201%206%201%203-2v-4c-1-1-2-2-1-4v-3l-2%203c-1%203-5%204-5%202h-5c-3%203-9%204-15%203s-7-2-7-6-9-7-14-4M97%2025l-4%203c-2%201-2%201%202%201l4-1%209-1c8%201%2013%200%2012-3-1-2-21-1-23%201m246%208l2%206c1%202%201%202-1%205-3%205-3%209-2%2010l1%203c0%203%200%203%201%202%202-2%202-2%202%200l5%2010v6c-1%204%200%205%202%202l1-1h2c1-1%202%200%204%201%203%202%202%200-1-3l-3-5-1-5c-3-4%200-13%203-13%202%200%202%200%200-1l-3-3-1-4c-1-2-2-4-1-5%201-4-2-8-7-8-3%200-3%200-3%203M185%2046c-2%203-2%203-1%205%204%203%2017%200%2017-4s-12-4-16-1m-64%207h-7c-3%200-3%200-2%204l1%203c0%202%208%200%209-1%201-2%2010%200%2011%202s2%203%204%202l2%201c1%202-3%204-12%205l-8%201%203%201%206%201c3%201%205%201%208-1l7-2%202-1-1-1-1-2%202-2c2%200%202%200%202-2-1-2%206-4%2012-4l3-1-2-1-9-1c-11-3-26-3-30-1m-61%207c-1%204%203%2010%207%2010%207%202%2023%201%2025-1l9-2c15-2%2016-2%2012-3l-3-2c2-4-18-5-24-2h-5l-12-2c-9%200-9%200-9%202m131%202l-4%201-2%201-1%201c-3%201-7%205-7%207%200%204%203%206%2011%206%2015%201%2015%201%205%202l-12%202-3%201-3%203c0%202%204%202%206%200h38l3%201c2%200%202%200%201%201-2%201-2%201%200%202h5c3-2%2012-2%2014-1%201%201%200%201-3%201l-8%201-2%201%203%201%208%204%205%202v-8l-1-10c0-2-1-2-7-2-4%200-6%200-4-1%204%200%205-2%202-3l-2-1-4-1h-6v-1l4-1v-2c-3%200-1-2%202-2%205-1%202-3-5-3-9%200-11%201-11%203l-1%201v7c-2%202-2%203%200%204%202%203%200%204-5%202-2-2-2-3%201-2l1-2c0-3-1-4-2-2-1%201-1%200-1-1l1-3c2-2%201-3-1-3l-3-1h-8l1-2c2%200%203-3%202-4-2-1-6-1-7%201m-27%205l-15%201c-4%200-4%201%200%202l4%202c1%202%2010%203%2014%201%203-2%203-7%200-7l-3%201m117%204c0%202-1%203-3%201-2-3-2%200%200%203%203%203%204%206%202%207-3%201-3%204%200%206%202%201%204%203%204%205l3%203c1%200%203-11%201-14s-1-6%201-6c2%201%206-2%204-3l-3-1-5-1c-3-2-4-2-4%200m-156%206l-7%201c-8-1-13%203-6%205l3%201%203%201c3%200%203%200%201%201-5%201%200%202%206%201h11v-1c-2%200-1-2%202-2l4-1h-4c-3%200-3%200-1-1h4c6%202%2029%200%2027-3a51%2051%200%2000-21-2l-4%201c-2%202-2%202-5%200-4-1-11-2-13-1m192%2026l-4%201c-2%200-4%202-2%202l1%203c0%201%202%203%205%204%204%203%204%203%206%201%201-1%202-2%206%200l4%201-4%201-3%203h3c0-2%203-3%203-1h4c5%200%203%202-3%203-3%201-2%201%206%201%204%200%207%200%205%201-12%201-20%204-11%204%202%200%203%200%203%202l1%202%201%201%202%202%202%201-8%202c-5%201-5%201-4%204%202%203%202%203-1%203-2%201-2%201%201%201%202%200%203%201%203%202l3%203%205%206c6%207%206%207%205%201%200-4%200-6-2-9l-2-2%204-2%206-1h2l-2-2c-2-2-2-2-1-3l1-2c-1-1%200-1%204-1%206%200%2010-1%2010-4%201-2%201-2-2-1h-8l-9%202a64%2064%200%200122-5c3-2-1-3-5-3h-4l3-1c3-2%204-4%201-3-4%200-4-2-1-2%202-1%203-1%202-2l1-2c3-2%204-3%201-4l-1-1c1-1-1-2-4-3l-8-3-6-1c-27-1-30%200-31%201'%20fill='%232B2B2F'%20fill-rule='evenodd'/%3e%3c/svg%3e","aspectRatio":2.380952380952381,"src":"/static/5da086e8606d19d30293f5da83ab96c5/d786d/documents.png","srcSet":"/static/5da086e8606d19d30293f5da83ab96c5/0d540/documents.png 100w,\n/static/5da086e8606d19d30293f5da83ab96c5/5224a/documents.png 200w,\n/static/5da086e8606d19d30293f5da83ab96c5/d786d/documents.png 400w,\n/static/5da086e8606d19d30293f5da83ab96c5/f8eb5/documents.png 600w,\n/static/5da086e8606d19d30293f5da83ab96c5/f9ff4/documents.png 800w,\n/static/5da086e8606d19d30293f5da83ab96c5/10bb3/documents.png 1177w","srcWebp":"/static/5da086e8606d19d30293f5da83ab96c5/40a1d/documents.webp","srcSetWebp":"/static/5da086e8606d19d30293f5da83ab96c5/bef64/documents.webp 100w,\n/static/5da086e8606d19d30293f5da83ab96c5/9e195/documents.webp 200w,\n/static/5da086e8606d19d30293f5da83ab96c5/40a1d/documents.webp 400w,\n/static/5da086e8606d19d30293f5da83ab96c5/6ef99/documents.webp 600w,\n/static/5da086e8606d19d30293f5da83ab96c5/b0751/documents.webp 800w,\n/static/5da086e8606d19d30293f5da83ab96c5/bb020/documents.webp 1177w","sizes":"(max-width: 400px) 100vw, 400px"}}}}}}]},"markdownRemark":{"html":"<p>Toute la technologie des <a href=\"/blog/gestion-de-consentements\">consentements eKee</a> consiste à être capable de partager des sous ensembles de données avec une granulartié infinie tout en laissant la requête dicter la structure. En bref, utiliser un langage de requêtage zero config.</p>\n<p>Ce qui signifie qu'eKee est constamment en train de compiler une requête JSON vers du SQL puis de re-traduire le résultat SQL vers la structure JSON. Or cette opération doit se faire en temps réel, rendant ses performances critiques.</p>\n<p>Récemment, nous avons été confronté à un problème lors du passage <em>Résultat SQL</em> vers <em>JSON</em> : À partir d'environ 50Mo de donnée, la réponse pouvait mettre plus de 30 secondes à arriver.</p>\n<p>Dans cet article, nous allons vous présenter comment un changement d'algorithme a pu nous faire passer de 30s de traitement à moins de 200ms.</p>\n<h2>La problématique</h2>\n<p>Le but de la transformation est de reconstruire des objets JSON à partir des résultats d'une requête SQL. Dans notre syntaxe, un objet JSON représente une entrée d'une table. Tous ses champs représentent soit des colonnes, soit des entrées de table en relation avec l'objet (la nouvelle table est un sous-objet)</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/b0e26aa6b324cb80c2ec25bd552042a7/0787c/json-sql.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 37.23404255319149%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3QUD/8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQABBQJ//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQAGPwJ//8QAFxABAAMAAAAAAAAAAAAAAAAAAAERMf/aAAgBAQABPyFqLf/aAAwDAQACAAMAAAAQgA//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAACAgMBAAAAAAAAAAAAAAABEQAhMUFRkf/aAAgBAQABPxBnp8ELYMsY1KLAc//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Transformation d&#39;un résultat attendu\"\n        title=\"Transformation d&#39;un résultat attendu\"\n        src=\"/static/b0e26aa6b324cb80c2ec25bd552042a7/88df8/json-sql.jpg\"\n        srcset=\"/static/b0e26aa6b324cb80c2ec25bd552042a7/20e77/json-sql.jpg 188w,\n/static/b0e26aa6b324cb80c2ec25bd552042a7/f21ed/json-sql.jpg 375w,\n/static/b0e26aa6b324cb80c2ec25bd552042a7/88df8/json-sql.jpg 750w,\n/static/b0e26aa6b324cb80c2ec25bd552042a7/b2f64/json-sql.jpg 1125w,\n/static/b0e26aa6b324cb80c2ec25bd552042a7/0787c/json-sql.jpg 1223w\"\n        sizes=\"(max-width: 750px) 100vw, 750px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<center style=\"margin-top: -12px\"><i>Fig 1: Transformation en résultat attendu</i></center>\n<p>Deux problématiques majeures sont rencontrées durant la transformation de résultats SQL en JSON :</p>\n<ul>\n<li>Atomicité d'une entrée: les colonnes d'une même entrée ne doivent pas être séparées entre plusieurs objets. Une ligne du résultat doit être découpée en groupes de colonnes en fonction de l'entrée à laquelle chaque colonne appartient. Les colonnes d'un groupe sont considérées comme un seul élément pendant les opérations de comparaison (<em>country</em>, <em>city</em>, <em>street</em> dans fig. 1) ;</li>\n<li>Fusion des entrées identiques: Comme pour <em>country.city</em> et <em>country.city.street</em> (fig. 1), quand plusieurs éléments d'une relation entre deux tables <strong>A</strong> et <strong>B</strong> existent (i.e. one-to-many), une ligne SQL est renvoyée par élements de <strong>B</strong> sélectionnés. L'entrée de <strong>A</strong> est alors présente dans chacune des lignes mais ne doit apparaitre qu'une fois dans le résultat final. Tandis que les entrées de <strong>B</strong> doivent être fusionnée dans un tableau.</li>\n</ul>\n<h2>Génération et fusion d'arbre</h2>\n<p>Une première approche est de traiter ces points les uns après les autres. En commençant par construire une arborescence d'objet JSON pour chaque ligne du résultat puis en fusionnant les arborescences entre elles.</p>\n<p>L'avantage de cette solution est sa simplicité, un algorithme récursif parcourant les arborescences permet de réduire le problème à la fusion d'un seul noeud de l'arbre. Il suffit alors de détecter les conflits de valeur entre deux objets et de définir une méthode de résolution de ces conflits (i.e. génération de tableaux contenant les deux valeurs).</p>\n<p>Mais, cette solution implique de construire un nombre incalculable d'objets intermédiaires qui seront supprimés pendant la fusion. Cette utilisation de la mémoire est très néfaste aux performances d'un programme écrit en go. Go reposant sur un garbage collector, allouer puis libérer des objets en grande quantité force le garbage collector à faire des poses plus longues et plus fréquentes.</p>\n<p>De plus, même si l'algorithme récursif est assez simple, son optimisation est limitée. Chaque fois qu'une arborescence est fusionnée avec le résultat, une détection de conflit doit être faite entre chaque noeud des deux arborescences. Ainsi, si un conflit génère un branchement dans l'arbre (un tableau), les futures comparaisons doivent être faites avec les deux branches de l'arbre.</p>\n<p>Cette solution a rapidement montré ses limites lors du traitement de résultat contenant de nombreux tableaux. Transformer plusieurs dixaines de Mo de lignes SQL peut prendre bien plus de 30 secondes. Il nous a donc fallut trouver une autre approche.</p>\n<h2>Vers un processus plus linéaire</h2>\n<p>L'algorithme précédent passait la quasi totalité de son temps sur le parcours et la comparaison des objets issus des lignes SQL. Toute la problématique est donc de réussir à supprimer les parcours du JSON final et limiter au maximum la comparaison nécessaire lors de l'ajout d'éléments.</p>\n<p>La nouvelle solution explorée consiste à construire tous les objets dans un premier temps puis à les rattacher à leur parent. Plus aucun parcours d'arborescence n'est nécessaire. Par contre, cette solution repose sur la génération de clefs d'identification uniques pour chaque objet JSON. Cette solution n'est applicable que si les différents objets à fusionner sont constitués des mêmes colonnes. Dans le cas d'une réponse SQL, l'ensemble et l'ordre des colonnes sont fixés pour toutes les lignes résultantes. La deuxième solution est donc applicable.</p>\n<p>L'ensemble du processus est réalisé en trois passages. Le premier construit les objets et leurs identifiants. Le deuxième itère sur les identifiants pour supprimer les duplicatas et enregistre les liens entre les objets (au moyen de leurs identifiants). Le dernier relie les objets finaux grâce aux métadonnées générées pendant la deuxième étape.</p>\n<h3>Construction des objets et de leur identifiant</h3>\n<pre class=\"grvsc-container default-dark\" data-language=\"go\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"1\"></span><span class=\"grvsc-source\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Route</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">string</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"2\"></span><span class=\"grvsc-source\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">RowElement</span><span class=\"mtk1\"> = {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"3\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    object: Object</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"4\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    hash: Hash</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"5\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    parentRoute: Route</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"6\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"7\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"8\"></span><span class=\"grvsc-source\"><span class=\"mtk12\">objects</span><span class=\"mtk1\"> := </span><span class=\"mtk4\">map</span><span class=\"mtk1\">[Route]RowElement</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"9\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"10\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// Format SQL rows into JSON object</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"11\"></span><span class=\"grvsc-source\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> </span><span class=\"mtk12\">col</span><span class=\"mtk1\">, </span><span class=\"mtk12\">value</span><span class=\"mtk1\"> := </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> SQLrows {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"12\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk12\">path</span><span class=\"mtk1\"> := </span><span class=\"mtk11\">unalias</span><span class=\"mtk1\">(col)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"13\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// path = &quot;country.city.street.name&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"14\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Route: &quot;country.city.street&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"15\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// TableName: &quot;street&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"16\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Column: &quot;name&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"17\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// ParentRoute: &quot;country.city&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"18\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// ParentName: &quot;city&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"19\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk12\">route</span><span class=\"mtk1\">, </span><span class=\"mtk12\">key</span><span class=\"mtk1\"> := strings.</span><span class=\"mtk11\">splitLast</span><span class=\"mtk1\">(path,</span><span class=\"mtk8\">&quot;.&quot;</span><span class=\"mtk1\">)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"20\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"21\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// build hash + add RowElement/field if needed</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"22\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    objects.</span><span class=\"mtk11\">AddKeyToObject</span><span class=\"mtk1\">(route, key, val)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"23\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<p>Pour rendre la construction du JSON réalisable, toutes les colonnes de la requête SQL ont été préalablement remplacées par un chemin vers l'endroit où les valeurs devront être utilisées dans le JSON final. Il est ainsi possible de tracer la position d'un champ mais également celle de l'objet possédant le champ, son objet parent, etc. Par contre le nombre de colonnes dans chaque objet est inconnu avant la fin du traitement. Les identifiants des objets générés pour une ligne ne peuvent être utilisés qu'après le traitement de toutes les colonnes de la ligne.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0538862857b6b3d1bba7967a71439626/3cd43/sql-to-object.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.91489361702128%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAQAF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3SRiP//EABYQAAMAAAAAAAAAAAAAAAAAAAABIP/aAAgBAQABBQKUf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABkQAAMBAQEAAAAAAAAAAAAAAAABETEhYf/aAAgBAQABPyGeMfGJEJpg/9oADAMBAAIAAwAAABBgD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAECAQE/EIf/xAAcEAEAAQQDAAAAAAAAAAAAAAABABFRcZExQWH/2gAIAQEAAT8QRX1vCAXO1ghy7iKuYimEBtef/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Découpe d&#39;une ligne en objets\"\n        title=\"Découpe d&#39;une ligne en objets\"\n        src=\"/static/0538862857b6b3d1bba7967a71439626/88df8/sql-to-object.jpg\"\n        srcset=\"/static/0538862857b6b3d1bba7967a71439626/20e77/sql-to-object.jpg 188w,\n/static/0538862857b6b3d1bba7967a71439626/f21ed/sql-to-object.jpg 375w,\n/static/0538862857b6b3d1bba7967a71439626/88df8/sql-to-object.jpg 750w,\n/static/0538862857b6b3d1bba7967a71439626/3cd43/sql-to-object.jpg 796w\"\n        sizes=\"(max-width: 750px) 100vw, 750px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<center style=\"margin-top: -12px\"><i>Découpe d'une ligne en objets</i></center>\n<p>L'identifiant d'un objet est enrichi au fur et à mesure que des colonnes lui sont ajoutées. Les noms des champs sont omis durant la génération de l'identifiant pour limiter la taille de la donnée à traiter. L'association du chemin menant à l'objet et à ses valeurs garantit que deux objets provenant de tables différentes ne peuvent pas être confondus même s'ils sont constitués des mêmes valeurs.</p>\n<p>Comme certaines tables n'ont pas forcément de colonne sélectionnée, les appels à <em>AddKeyToObject</em> vont garantir que tous les objets sur la route du champ sont créés. Dans notre exemple (country.city.street.name), ajouter le champ <em>name</em> va créer des objets vides pour les routes <em>country.city</em> et <em>country</em> en plus d'ajouter un champ <em>name</em> à l'objet <em>country.city.street</em></p>\n<h3>Suppression des duplicatas et création des liens entre les objets</h3>\n<pre class=\"grvsc-container default-dark\" data-language=\"go\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"1\"></span><span class=\"grvsc-source\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">AllElements</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">map</span><span class=\"mtk1\">[TableName]HashList</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"2\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"3\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// Use generated hash to reduce the number of JSON objects</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"4\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// and link objects</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"5\"></span><span class=\"grvsc-source\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> </span><span class=\"mtk12\">objRoute</span><span class=\"mtk1\">, </span><span class=\"mtk12\">obj</span><span class=\"mtk1\"> := </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> objects {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"6\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Append to known json objects</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"7\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// permitting to use the same memory</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"8\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// for all equal objects (same structure &amp; values)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"9\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk12\">jsonObj</span><span class=\"mtk1\">, </span><span class=\"mtk12\">has</span><span class=\"mtk1\"> := objectsMap.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(objRoute, obj.hash)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"10\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> !has {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"11\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        objectsMap.</span><span class=\"mtk11\">put</span><span class=\"mtk1\">(objRoute, obj.hash, obj.object)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"12\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    }</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"13\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"14\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk12\">parent</span><span class=\"mtk1\"> := objects[obj.parentRoute]</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"15\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"16\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Inserting in the hash list, to remove duplicat objects</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"17\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// (Behaves like a hashset)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"18\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// One hashset per table</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"19\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk12\">objHashList</span><span class=\"mtk1\"> := allElements[objRoute]</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"20\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    objHashList.</span><span class=\"mtk11\">Insert</span><span class=\"mtk1\">(Table{</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"21\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        parentHash: parent.hash,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"22\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        parentTable: obj.parentRoute,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"23\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        hash: obj.hash,</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"24\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    })</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"25\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span></code></pre>\n<p>Le point important de cette deuxième étape est la manière dont est gérée la table de hash. L'ordre d'arrivée des éléments doit être conservé pour que, en cas d'utilisation de <strong>ORDER BY</strong> dans la requête SQL, l'ordre des éléments dans le JSON soient bien triés. Les objets sont groupés en fonction de leur <em>parentHash</em> et <em>parentTable</em> puis l'ordre d'arrivée est utilisé. Le <em>hash</em> est donc uniquement utilisé pour vérifier l'égalité entre deux objets.</p>\n<h3>Construction de la représentation final</h3>\n<pre class=\"grvsc-container default-dark\" data-language=\"go\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"1\"></span><span class=\"grvsc-source\"><span class=\"mtk4\">type</span><span class=\"mtk1\"> </span><span class=\"mtk10\">ObjectsMap</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">map</span><span class=\"mtk1\">[Route][Hash]Object</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"2\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"3\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// Prepare the destination object for all the Table which</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"4\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// do not have a parent</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"5\"></span><span class=\"grvsc-source\"><span class=\"mtk12\">res</span><span class=\"mtk1\"> = {}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"6\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">ObjectsMap[</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">][</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">] = res</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"7\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"8\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// Link final objects together</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"9\"></span><span class=\"grvsc-source\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> </span><span class=\"mtk12\">objectRoute</span><span class=\"mtk1\">, </span><span class=\"mtk12\">hashList</span><span class=\"mtk1\"> := </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> allElements {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"10\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk12\">hashMap</span><span class=\"mtk1\"> := ObjectsMap[objectRoute]</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"11\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> </span><span class=\"mtk12\">_</span><span class=\"mtk1\">, </span><span class=\"mtk12\">el</span><span class=\"mtk1\"> := </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> hashList {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"12\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        </span><span class=\"mtk12\">currentObj</span><span class=\"mtk1\"> := hashMap[el.hash]</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"13\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        </span><span class=\"mtk12\">parent</span><span class=\"mtk1\"> := ObjectsMap[el.parentTable][el.parentHash]</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"14\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">, </span><span class=\"mtk12\">tableName</span><span class=\"mtk1\"> := strings.</span><span class=\"mtk11\">splitLast</span><span class=\"mtk1\">(path,</span><span class=\"mtk8\">&quot;.&quot;</span><span class=\"mtk1\">)</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"15\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// Insert Or Append field if already present</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"16\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">        parent[tableName] = currentObj</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"17\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">    }</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"18\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"19\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"20\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// return the only object whose route is &quot;&quot;</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"21\"></span><span class=\"grvsc-source\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> </span><span class=\"mtk12\">_</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\"> := </span><span class=\"mtk15\">range</span><span class=\"mtk1\"> ObjectMap[</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">] {</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"22\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> []Object{res}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"23\"></span><span class=\"grvsc-source\"><span class=\"mtk1\">}</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"24\"></span><span class=\"grvsc-source\"></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"25\"></span><span class=\"grvsc-source\"><span class=\"mtk3\">// return an empty array representing nothing found</span></span></span>\n<span class=\"grvsc-line\"><span class=\"grvsc-gutter-pad\"></span><span class=\"grvsc-gutter grvsc-line-number\" aria-hidden=\"true\" data-content=\"26\"></span><span class=\"grvsc-source\"><span class=\"mtk15\">return</span><span class=\"mtk1\"> []Object{}</span></span></span></code></pre>\n<p><em>ObjectsMap</em> contient tous les objets JSON générés et <em>AllElements</em> les liens entre ces objets. Pendant cette dernière étape, il ne reste plus de calculs ou d'algorithmes complexes à appliquer. L'insertion des nouveaux éléments est peu intéressante mais néanmoins verbeuse, c'est pourquoi le code d'insertion est omis. Il faut créer ou non des tableaux si un élément est déjà présent dans le champ <em>tableName</em>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 750px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/1972ec8a91fe204b3f57762e2fcdd0c9/38ca7/object-links.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 32.97872340425532%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAHABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB3oAH/8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQABBQJ//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQAGPwJ//8QAGRAAAwADAAAAAAAAAAAAAAAAAAERIVFh/9oACAEBAAE/Ic7HYK9P/9oADAMBAAIAAwAAABDzz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAAICAgMAAAAAAAAAAAAAAAERACExQWFxof/aAAgBAQABPxBLg+oO5nioCX6E/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Liaisons entre les objets finaux\"\n        title=\"Liaisons entre les objets finaux\"\n        src=\"/static/1972ec8a91fe204b3f57762e2fcdd0c9/88df8/object-links.jpg\"\n        srcset=\"/static/1972ec8a91fe204b3f57762e2fcdd0c9/20e77/object-links.jpg 188w,\n/static/1972ec8a91fe204b3f57762e2fcdd0c9/f21ed/object-links.jpg 375w,\n/static/1972ec8a91fe204b3f57762e2fcdd0c9/88df8/object-links.jpg 750w,\n/static/1972ec8a91fe204b3f57762e2fcdd0c9/38ca7/object-links.jpg 774w\"\n        sizes=\"(max-width: 750px) 100vw, 750px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<center style=\"margin-top: -12px\"><i>Liaisons entre les objets finaux</i></center>\n<p>Dans l'exemple ci-dessus, deux objets differents vont être raccrochés à un même objet parent en utilisant le champ <em>street</em>. Un tableau va permettre de conserver les deux objets.</p>\n<h2>Résultats</h2>\n<p>Passer de la première solution à la seconde nous a permis de considérablement réduire le temps d'exécution de certaines de nos requêtes. Précédemment, le traitement d'environ 50Mo de résultat SQL pouvait prendre plus de 30 secondes. Désormais, ce même traitement s'exécute constamment en moins de 200 millisecondes.</p>\n<p>Pour autant, l'implémentation présentée aujourd'hui reste naïve et largement optimisable. Parmis les optimisations les plus impactantes on peut penser à :</p>\n<ul>\n<li>Utiliser une représentation plus compactes pour les hash,</li>\n<li>Remplacer les <em>Map</em> par des tableau afin de supprimer la génération des hash Go et profiter d'un stockage contigu en mémoire,</li>\n<li>Utiliser des pools de mémoire lors de la création des objets,</li>\n<li>Implémenter de la vectorisation lors des comparaisons</li>\n</ul>\n<p>Toutes ces optimisations et bien d'autres arriveront lorsque le besoin s'en fera sentir. Bien entendu, nous ne manquerons pas de vous les présenter ici !</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    position: relative;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n    line-height: 1.4;\n  }\n  \n  .grvsc-code {\n    display: table;\n  }\n  \n  .grvsc-line {\n    display: table-row;\n    box-sizing: border-box;\n    width: 100%;\n    position: relative;\n  }\n  \n  .grvsc-line > * {\n    position: relative;\n  }\n  \n  .grvsc-gutter-pad {\n    display: table-cell;\n    padding-left: 0.75rem;\n    padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2);\n  }\n  \n  .grvsc-gutter {\n    display: table-cell;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n  }\n  \n  .grvsc-gutter::before {\n    content: attr(data-content);\n  }\n  \n  .grvsc-source {\n    display: table-cell;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-source:empty::after {\n    content: ' ';\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    user-select: none;\n  }\n  \n  .grvsc-gutter + .grvsc-source {\n    padding-left: 0.75rem;\n    padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2);\n  }\n  \n  /* Line transformer styles */\n  \n  .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before {\n    content: ' ';\n    position: absolute;\n    width: 100%;\n  }\n  \n  .grvsc-line-diff-add::before {\n    background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2));\n  }\n  \n  .grvsc-line-diff-del::before {\n    background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2));\n  }\n  \n  .grvsc-line-number {\n    padding: 0 2px;\n    text-align: right;\n    opacity: 0.7;\n  }\n  \n  .default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .default-dark .mtk4 { color: #569CD6; }\n  .default-dark .mtk1 { color: #D4D4D4; }\n  .default-dark .mtk10 { color: #4EC9B0; }\n  .default-dark .mtk12 { color: #9CDCFE; }\n  .default-dark .mtk3 { color: #6A9955; }\n  .default-dark .mtk15 { color: #C586C0; }\n  .default-dark .mtk11 { color: #DCDCAA; }\n  .default-dark .mtk8 { color: #CE9178; }\n  .default-dark .grvsc-line-highlighted::before {\n    background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1));\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5));\n  }\n</style>","excerpt":"Toute la technologie des consentements eKee consiste à être capable de partager des sous ensembles de données…","frontmatter":{"date":"2021-03-22","title":"Optimisation de conversion SQL vers JSON","tags":["engineering"],"path":"/blog/sql-to-json","author":{"firstname":"Julien","lastname":"MOUNIER","jobTitle":"Software Engineer","linkedin":"https://www.linkedin.com/in/julien-mounier/","github":"https://github.com/JMounier","twitter":null,"profilePic":{"childImageSharp":{"fixed":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAQF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQD/2gAMAwEAAhADEAAAAdiW2IdEJmTE6oj/xAAbEAADAAIDAAAAAAAAAAAAAAABAgMAEQQSIv/aAAgBAQABBQKrdVmSrY42syC2cmjBifMTuX//xAAVEQEBAAAAAAAAAAAAAAAAAAABEP/aAAgBAwEBPwEhP//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAAICAwEAAAAAAAAAAAAAAAABEBIRITEy/9oACAEBAAY/AtHuycMUVXBCyf/EABoQAQADAQEBAAAAAAAAAAAAAAEAESEQQVH/2gAIAQEAAT8ha3CtX8h8X5HzlWl4ZvEDVSIbRkq2f//aAAwDAQACAAMAAAAQd8C+/8QAFxEBAQEBAAAAAAAAAAAAAAAAARARMf/aAAgBAwEBPxAGM4Z//8QAGBEAAgMAAAAAAAAAAAAAAAAAAAEQMUH/2gAIAQIBAT8Qdw8Gf//EABsQAQADAQEBAQAAAAAAAAAAAAEAETEhQRCR/9oACAEBAAE/EG6UReX9i/1D1DiQgs1ll5zsMKjHMfD9+DRbqjrzLjUItI3RLtW3Wf/Z","width":88,"height":88,"src":"/static/9cbe8fd90feb2a7ba6cb23cc46423031/6ac25/julien_mounier.jpg","srcSet":"/static/9cbe8fd90feb2a7ba6cb23cc46423031/6ac25/julien_mounier.jpg 1x,\n/static/9cbe8fd90feb2a7ba6cb23cc46423031/0df9e/julien_mounier.jpg 1.5x,\n/static/9cbe8fd90feb2a7ba6cb23cc46423031/ea0c1/julien_mounier.jpg 2x"}}}},"cover":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE00lEQVQ4y22Ua2wUVRTHb5DwoQa+GEkKIu3SnX3M7uyr++qy753t7rLdvlZosdAUCtVVRKu8o9DwMFSwMWqCoIItgiDP3a28CkaS2i2FNErRaEJM9IuJooREQevM3zNrieExyT/n3jtzf/ece84ZlrD5v0/GXFet1XVjvLdmzGj2j/HW0H0KTig0pp/Qg9+ErpF0LGkNIF7tgiHSgNn2FCr4ALTWMCkEnTlQlNYcgsYUpnEIvCUAntZ4SxAEuF8h5pzrQ0uNc7y5wSd1driltgUuyWX1Sw5bULJ75kkOX0pyeELSXH+IbFji3QmJ9yQlgysmCZURyUgS7OLfBlsYekvQx8w2P2prG6VV67qwav1atCfj2BCOocMdQG1iPurT7XgqacWKVivSNU6Ux1pQ3tgOTpwPgSBGuygTcJzACtDPlFAiiXpp66Zn0drxPKxPr0Hdhm7Y6trwZLARXHIxdPFF0ESaoYsuhEChKqAJGBTQPUDeKiKVcEubV6rRucyI+qYAYi0rsCizBkte6YI/vRS8vxZCqAFCmFRJMIeoQIqwB4CuqgBWNpulLRkDlqWq8FI4gEysDovjjdiSasQzXhE2dwxGJUkUjbFShM4SLVrB/hBgpTOItrRdeqHNCjEeRFmiDWW1rTBG0ljYvBzOZAv09UuKHkVEP8zOCETRV7R3ofcA3eRhfdQtcaYonSzCRGVhorJQPOJMig1CawjB7Q3i2tFSnNtdhh/y05Guq4LKEIPJcf8d2kSquWpJeWFSQrBTOI4o3VMUFlcUnCWOprQHhd6ZOLijAqs6LNjVpcWVAzPwYrsVFUIUZkfkf6AyIJBSU8WsKVawhYrZNFn80Ol8iIkeDPbOwuIFTsxUx6kRvBj86Am0LnA8HEguS8USUOSiBLjj0C9dDT6zAeVNnVi4PI4fD5dgdcZKh4fR2uTE9dx0rH/ODJWx+qHAfyhMWTDMlfl5LTL33lFoXt8ja3p6JdU7R2R3905s3tUof/3pDPnc7tlFS2HLsWqvrLeKMkV4F+grApV7E5T+VDrgjb3QbP9AVh8cQMXxQWj6TqFsxwG5vLsP73dxWJuxoG87hypfEHP+866Y7YnWCynAP8m73wXBd5NvytzWvHtoXP3JeZnb139b37HuFrf/7B3u4zOytqd3fHbnzj/mcMGbM3WJn7Xm6C+GSvEGeXiDSucmcW7Rz8HMBHd8mslbM80ydVaJ+uD5E9zRi6cr8peg331sXinAtPv6m9Q01+YKp/kLoykwxoaPqL3n9qj0G9dVlW5bby/VmaJTLa7qEqY81JPMQ1bb08fUZ0bjmvylvDpb+EvdP3JCd/knA8EGaH6DgAPlJy/vZJPBcPnRQVyZsgejbBNp6bHXHmNsynIG5TQqYKZ968Aj6vNXmTY7lOKyhREuN3yIIHdIIP3G5QoXaL3fnbtYwnbcmbx3oEV8++wyoyt/tj6eP2Q2j3zLTK92T3L7wozpssNMny2wimxhkoqsJlsI0ebrmtzwEdLnBP+C5ocJ+jJ3cogZcgXVrOzVN8tyX21U50ZGVdmRNSpikCY1fEMulh7/sgjU54YZny9qqjY3rCfAVlIPwbbR3EkHsrITQ4+U7P+Msc208cNfmed04fFg/6nJxtwQM+WHmOU7sH8B3gfFkyQMSz8AAAAASUVORK5CYII=","aspectRatio":1.016,"src":"/static/e430d93a3ed8e82e1b6b2932db6dfd59/747b8/cover.png","srcSet":"/static/e430d93a3ed8e82e1b6b2932db6dfd59/e4f20/cover.png 127w,\n/static/e430d93a3ed8e82e1b6b2932db6dfd59/34f97/cover.png 254w,\n/static/e430d93a3ed8e82e1b6b2932db6dfd59/747b8/cover.png 487w","srcWebp":"/static/e430d93a3ed8e82e1b6b2932db6dfd59/4dc8b/cover.webp","srcSetWebp":"/static/e430d93a3ed8e82e1b6b2932db6dfd59/288c8/cover.webp 127w,\n/static/e430d93a3ed8e82e1b6b2932db6dfd59/ca6b9/cover.webp 254w,\n/static/e430d93a3ed8e82e1b6b2932db6dfd59/4dc8b/cover.webp 487w","sizes":"(max-width: 487px) 100vw, 487px","maxHeight":480,"maxWidth":487},"resize":{"src":"/static/e430d93a3ed8e82e1b6b2932db6dfd59/aecaf/cover.png"}}}}}},"pageContext":{"pathSlug":"/blog/sql-to-json","relatedPosts":["/blog/bases-rncs-sirene-bodacc","/blog/gestion-de-documents","/blog/gestion-de-consentements"]}},"staticQueryHashes":["1022643890","4276689922"]}