[{"data":1,"prerenderedAt":43234},["ShallowReactive",2],{"navigation_docs":3,"-aws-dynamodb":3338,"-aws-dynamodb-surround":43229},[4,1707,1904,2358,2539,2608,2815,2937,2987,3044,3078,3204,3281,3334],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","\u002Fcsharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1364,1654,1703],{"title":11,"path":7,"stem":12},"C# та .NET","01.csharp\u002Findex",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","\u002Fcsharp\u002Ffundamentals","01.csharp\u002F01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","\u002Fcsharp\u002Ffundamentals\u002Fintroduction-to-ecosystem","01.csharp\u002F01.fundamentals\u002F01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","\u002Fcsharp\u002Ffundamentals\u002Fprogram-structure","01.csharp\u002F01.fundamentals\u002F02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","\u002Fcsharp\u002Ffundamentals\u002Fvariables-data-types","01.csharp\u002F01.fundamentals\u002F03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","\u002Fcsharp\u002Ffundamentals\u002Farrays","01.csharp\u002F01.fundamentals\u002F04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","\u002Fcsharp\u002Ffundamentals\u002Fstrings-text-handling","01.csharp\u002F01.fundamentals\u002F05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","\u002Fcsharp\u002Ffundamentals\u002Fdates-time-handling","01.csharp\u002F01.fundamentals\u002F06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","\u002Fcsharp\u002Ffundamentals\u002Fcontrol-flow","01.csharp\u002F01.fundamentals\u002F07.control-flow",{"title":48,"path":49,"stem":50},"Методи","\u002Fcsharp\u002Ffundamentals\u002Fmethods","01.csharp\u002F01.fundamentals\u002F08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","\u002Fcsharp\u002Ffundamentals\u002Fdebugging-basics","01.csharp\u002F01.fundamentals\u002F09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","\u002Fcsharp\u002Ffundamentals\u002Finteractive-console","01.csharp\u002F01.fundamentals\u002F10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","\u002Fcsharp\u002Foop","01.csharp\u002F02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","\u002Fcsharp\u002Foop\u002Fpackage-management","01.csharp\u002F02.oop\u002F01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","\u002Fcsharp\u002Foop\u002Fclasses-objects","01.csharp\u002F02.oop\u002F02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","\u002Fcsharp\u002Foop\u002Fproperties-fields","01.csharp\u002F02.oop\u002F03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","\u002Fcsharp\u002Foop\u002Foop-pillars","01.csharp\u002F02.oop\u002F04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","\u002Fcsharp\u002Foop\u002Fadvanced-types","01.csharp\u002F02.oop\u002F05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","\u002Fcsharp\u002Foop\u002Fnamespaces","01.csharp\u002F02.oop\u002F06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","\u002Fcsharp\u002Fadvanced-core","01.csharp\u002F03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","\u002Fcsharp\u002Fadvanced-core\u002Fgenerics","01.csharp\u002F03.advanced-core\u002F01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","\u002Fcsharp\u002Fadvanced-core\u002Fdelegates-events-lambdas","01.csharp\u002F03.advanced-core\u002F02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","\u002Fcsharp\u002Fadvanced-core\u002Finterfaces-deep-dive","01.csharp\u002F03.advanced-core\u002F03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","\u002Fcsharp\u002Fadvanced-core\u002Fexception-handling","01.csharp\u002F03.advanced-core\u002F04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","\u002Fcsharp\u002Fadvanced-core\u002Fpattern-matching","01.csharp\u002F03.advanced-core\u002F05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","\u002Fcsharp\u002Fadvanced-core\u002Fadditional-features","01.csharp\u002F03.advanced-core\u002F06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","\u002Fcsharp\u002Farchitecture-best-practices","01.csharp\u002F04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fsoftware-design-principles","01.csharp\u002F04.architecture-best-practices\u002F01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fsingleton","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fbuilder","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","\u002Fcsharp\u002Farchitecture-best-practices\u002Fbuilding-professional-clis","01.csharp\u002F04.architecture-best-practices\u002F03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","\u002Fcsharp\u002Farchitecture-best-practices\u002Fvalidation-flow-control","01.csharp\u002F04.architecture-best-practices\u002F04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fmodern-dotnet-host","01.csharp\u002F04.architecture-best-practices\u002F05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part1","01.csharp\u002F04.architecture-best-practices\u002F06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part2","01.csharp\u002F04.architecture-best-practices\u002F07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fthe-dependency-problem","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fbuild-your-own-container","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-locator-pattern","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdependency-injection-patterns","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fmicrosoft-di-deep-dive","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-lifetimes-and-scopes","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdi-anti-patterns-and-best-practices","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","\u002Fcsharp\u002Fstandard-library","01.csharp\u002F05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","\u002Fcsharp\u002Fstandard-library\u002Fcollections","01.csharp\u002F05.standard-library\u002F01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","\u002Fcsharp\u002Fstandard-library\u002Fhigh-performance-types","01.csharp\u002F05.standard-library\u002F02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","\u002Fcsharp\u002Fstandard-library\u002Flinq","01.csharp\u002F05.standard-library\u002F03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","\u002Fcsharp\u002Fsystem-internals-concurrency","01.csharp\u002F06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmemory-management","01.csharp\u002F06.system-internals-concurrency\u002F01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Freflection-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fattributes-dynamic","01.csharp\u002F06.system-internals-concurrency\u002F03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fexpression-trees-compiled","01.csharp\u002F06.system-internals-concurrency\u002F04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsource-generators","01.csharp\u002F06.system-internals-concurrency\u002F05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmultithreading-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsynchronization-primitives","01.csharp\u002F06.system-internals-concurrency\u002F07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","\u002Fcsharp\u002Fsystem-programming-windows","01.csharp\u002F07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","\u002Fcsharp\u002Fsystem-programming-windows\u002Fhow-os-works","01.csharp\u002F07.system-programming-windows\u002F01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","\u002Fcsharp\u002Fsystem-programming-windows\u002Fprocesses-in-dotnet","01.csharp\u002F07.system-programming-windows\u002F02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","\u002Fcsharp\u002Fsystem-programming-windows\u002F02a.processes-ipc","01.csharp\u002F07.system-programming-windows\u002F02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","\u002Fcsharp\u002Fsystem-programming-windows\u002Fappdomains-assemblies","01.csharp\u002F07.system-programming-windows\u002F03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","\u002Fcsharp\u002Fsystem-programming-windows\u002F03a.appdomains-plugin-system","01.csharp\u002F07.system-programming-windows\u002F03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-fundamentals","01.csharp\u002F07.system-programming-windows\u002F04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","\u002Fcsharp\u002Fsystem-programming-windows\u002F04a.thread-lifecycle-priorities","01.csharp\u002F07.system-programming-windows\u002F04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","\u002Fcsharp\u002Fsystem-programming-windows\u002Fshared-state-problems","01.csharp\u002F07.system-programming-windows\u002F05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","\u002Fcsharp\u002Fsystem-programming-windows\u002F05a.shared-state-memory-model","01.csharp\u002F07.system-programming-windows\u002F05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-fundamentals","01.csharp\u002F07.system-programming-windows\u002F06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","\u002Fcsharp\u002Fsystem-programming-windows\u002F06a.synchronization-walkthrough","01.csharp\u002F07.system-programming-windows\u002F06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-advanced","01.csharp\u002F07.system-programming-windows\u002F07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002F07a.synchronization-advanced-walkthrough","01.csharp\u002F07.system-programming-windows\u002F07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002Finterlocked-cas-lockfree","01.csharp\u002F07.system-programming-windows\u002F08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","\u002Fcsharp\u002Fsystem-programming-windows\u002F08a.volatile-memory-model","01.csharp\u002F07.system-programming-windows\u002F08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-pool","01.csharp\u002F07.system-programming-windows\u002F09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","\u002Fcsharp\u002Fsystem-programming-windows\u002F09a.thread-pool-advanced","01.csharp\u002F07.system-programming-windows\u002F09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","\u002Fcsharp\u002Fsystem-programming-windows\u002Fconcurrent-collections","01.csharp\u002F07.system-programming-windows\u002F10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","\u002Fcsharp\u002Fsystem-programming-windows\u002Ftpl-parallel-plinq","01.csharp\u002F07.system-programming-windows\u002F11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","\u002Fcsharp\u002Fsystem-programming-windows\u002F11a.tpl-parallel-plinq-advanced","01.csharp\u002F07.system-programming-windows\u002F11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async\u002FAwait — Фундамент Асинхронного Програмування","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-fundamentals","01.csharp\u002F07.system-programming-windows\u002F12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-context-configureawait","01.csharp\u002F07.system-programming-windows\u002F13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-advanced","01.csharp\u002F07.system-programming-windows\u002F14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","\u002Fcsharp\u002Fsystem-programming-windows\u002Fchannels","01.csharp\u002F07.system-programming-windows\u002F15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-synchronization","01.csharp\u002F07.system-programming-windows\u002F16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","\u002Fcsharp\u002Fsystem-programming-windows\u002Funsafe-code","01.csharp\u002F07.system-programming-windows\u002F17.unsafe-code",{"title":364,"path":365,"stem":366},"P\u002FInvoke та Windows API — Міст між .NET та Native Code","\u002Fcsharp\u002Fsystem-programming-windows\u002Fpinvoke-winapi","01.csharp\u002F07.system-programming-windows\u002F18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-registry","01.csharp\u002F07.system-programming-windows\u002F19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-hooks-services","01.csharp\u002F07.system-programming-windows\u002F20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","\u002Fcsharp\u002Fsystem-programming-windows\u002Fimplementation_plan","01.csharp\u002F07.system-programming-windows\u002Fimplementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","\u002Fcsharp\u002Fio","01.csharp\u002F08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","\u002Fcsharp\u002Fio\u002Ffile-system-basics","01.csharp\u002F08.io\u002F01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","\u002Fcsharp\u002Fio\u002Fstreams-serialization","01.csharp\u002F08.io\u002F02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","\u002Fcsharp\u002Fio\u002Fjson-serialization","01.csharp\u002F08.io\u002F03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","\u002Fcsharp\u002Fio\u002Fxml-serialization","01.csharp\u002F08.io\u002F04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","\u002Fcsharp\u002Fio\u002Fbinary-serialization","01.csharp\u002F08.io\u002F05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","\u002Fcsharp\u002Fado-net","01.csharp\u002F09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","\u002Fcsharp\u002Fado-net\u002Fintroduction-to-adonet","01.csharp\u002F09.ado-net\u002F01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","\u002Fcsharp\u002Fado-net\u002Fconnection","01.csharp\u002F09.ado-net\u002F02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","\u002Fcsharp\u002Fado-net\u002Fcommand-and-queries","01.csharp\u002F09.ado-net\u002F03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","\u002Fcsharp\u002Fado-net\u002Fdatareader","01.csharp\u002F09.ado-net\u002F04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","\u002Fcsharp\u002Fado-net\u002Fparameters-and-sql-injection","01.csharp\u002F09.ado-net\u002F05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","\u002Fcsharp\u002Fado-net\u002Ftransactions","01.csharp\u002F09.ado-net\u002F06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","\u002Fcsharp\u002Fado-net\u002Fprovider-factory","01.csharp\u002F09.ado-net\u002F07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","\u002Fcsharp\u002Fado-net\u002Fasync-data-access","01.csharp\u002F09.ado-net\u002F08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","\u002Fcsharp\u002Fado-net\u002Fdisconnected-mode-dataset","01.csharp\u002F09.ado-net\u002F09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","\u002Fcsharp\u002Fado-net\u002Fdata-adapter","01.csharp\u002F09.ado-net\u002F10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","\u002Fcsharp\u002Fado-net\u002Fdata-mapper-repository","01.csharp\u002F09.ado-net\u002F11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","\u002Fcsharp\u002Fado-net\u002Fadvanced-patterns","01.csharp\u002F09.ado-net\u002F12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","\u002Fcsharp\u002Fef-core","01.csharp\u002F10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","\u002Fcsharp\u002Fef-core\u002Fwhat-is-orm","01.csharp\u002F10.ef-core\u002F01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","\u002Fcsharp\u002Fef-core\u002Ffirst-project","01.csharp\u002F10.ef-core\u002F02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","\u002Fcsharp\u002Fef-core\u002Fdbcontext-deep-dive","01.csharp\u002F10.ef-core\u002F03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","\u002Fcsharp\u002Fef-core\u002Fdatabase-providers","01.csharp\u002F10.ef-core\u002F04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","\u002Fcsharp\u002Fef-core\u002Fconventions","01.csharp\u002F10.ef-core\u002F05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","\u002Fcsharp\u002Fef-core\u002Ffluent-api-vs-annotations","01.csharp\u002F10.ef-core\u002F06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","\u002Fcsharp\u002Fef-core\u002Frelationships-basics","01.csharp\u002F10.ef-core\u002F07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","\u002Fcsharp\u002Fef-core\u002Frelationships-advanced","01.csharp\u002F10.ef-core\u002F08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part1","01.csharp\u002F10.ef-core\u002F09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part2","01.csharp\u002F10.ef-core\u002F09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part1","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part2","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part1","01.csharp\u002F10.ef-core\u002F11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part2","01.csharp\u002F10.ef-core\u002F11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finheritance-part1","01.csharp\u002F10.ef-core\u002F12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finheritance-part2","01.csharp\u002F10.ef-core\u002F12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part1","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part2","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fseeding-part1","01.csharp\u002F10.ef-core\u002F14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fseeding-part2","01.csharp\u002F10.ef-core\u002F14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part1","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part2","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part1","01.csharp\u002F10.ef-core\u002F16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part2","01.csharp\u002F10.ef-core\u002F16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part1","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part2","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part1","01.csharp\u002F10.ef-core\u002F18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part2","01.csharp\u002F10.ef-core\u002F18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part1","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part2","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part1","01.csharp\u002F10.ef-core\u002F20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part2","01.csharp\u002F10.ef-core\u002F20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part1","01.csharp\u002F10.ef-core\u002F21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part2","01.csharp\u002F10.ef-core\u002F21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part1","01.csharp\u002F10.ef-core\u002F22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part2","01.csharp\u002F10.ef-core\u002F22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part1","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part2","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part1","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part2","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part1","01.csharp\u002F10.ef-core\u002F25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part2","01.csharp\u002F10.ef-core\u002F25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fperformance-fundamentals-part1","01.csharp\u002F10.ef-core\u002F26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part1","01.csharp\u002F10.ef-core\u002F29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part2","01.csharp\u002F10.ef-core\u002F29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","\u002Fcsharp\u002Fef-core\u002Fimplementation_plan","01.csharp\u002F10.ef-core\u002Fimplementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","\u002Fcsharp\u002Faspnet","01.csharp\u002F11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289,1346],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","\u002Fcsharp\u002Faspnet\u002Fminimal-api","01.csharp\u002F11.aspnet\u002F01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fintroduction","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Ffirst-application","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fwebapplication-builder","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frequest-pipeline-middleware","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-files","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-assets","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-fundamentals","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-options","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstate-management","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fsession-state","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fproject-structure","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fscalar-openapi-fluent","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger \u002F Swashbuckle у Minimal API: окремий класичний шлях","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fswagger-swashbuckle","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","\u002Fcsharp\u002Faspnet\u002Fapi","01.csharp\u002F11.aspnet\u002F02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fwhat-is-api","01.csharp\u002F11.aspnet\u002F02.api\u002F01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fdata-formats","01.csharp\u002F11.aspnet\u002F02.api\u002F02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-paradigms-rest","01.csharp\u002F11.aspnet\u002F02.api\u002F03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fhttp-methods-status-codes","01.csharp\u002F11.aspnet\u002F02.api\u002F04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Frest-organizing","01.csharp\u002F11.aspnet\u002F02.api\u002F05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","\u002Fcsharp\u002Faspnet\u002Fapi\u002Furl-nomenclature-crud","01.csharp\u002F11.aspnet\u002F02.api\u002F06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-naming","01.csharp\u002F11.aspnet\u002F02.api\u002F07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-validation","01.csharp\u002F11.aspnet\u002F02.api\u002F08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Ferror-handling-http","01.csharp\u002F11.aspnet\u002F02.api\u002F09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fidempotency-sync","01.csharp\u002F11.aspnet\u002F02.api\u002F10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fpagination-lists","01.csharp\u002F11.aspnet\u002F02.api\u002F11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fsecurity-auth","01.csharp\u002F11.aspnet\u002F02.api\u002F12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-process","01.csharp\u002F11.aspnet\u002F02.api\u002F13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fopenapi","01.csharp\u002F11.aspnet\u002F02.api\u002F14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","\u002Fcsharp\u002Faspnet\u002Fauth","01.csharp\u002F11.aspnet\u002F03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauth-fundamentals","01.csharp\u002F11.aspnet\u002F03.auth\u002F01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fjwt-authentication","01.csharp\u002F11.aspnet\u002F03.auth\u002F02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauthorization-policies","01.csharp\u002F11.aspnet\u002F03.auth\u002F03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcookie-auth-identity","01.csharp\u002F11.aspnet\u002F03.auth\u002F04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","\u002Fcsharp\u002Faspnet\u002Fauth\u002F04b.identity-auth-jwt","01.csharp\u002F11.aspnet\u002F03.auth\u002F04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-email-confirmation","01.csharp\u002F11.aspnet\u002F03.auth\u002F05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-two-factor","01.csharp\u002F11.aspnet\u002F03.auth\u002F06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-internals","01.csharp\u002F11.aspnet\u002F03.auth\u002F07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-external-providers","01.csharp\u002F11.aspnet\u002F03.auth\u002F08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fsecurity-hardening","01.csharp\u002F11.aspnet\u002F03.auth\u002F09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-theory","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foidc-keycloak","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fapi-keys","01.csharp\u002F11.aspnet\u002F03.auth\u002F11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frate-limiting","01.csharp\u002F11.aspnet\u002F03.auth\u002F12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frefresh-token-rotation","01.csharp\u002F11.aspnet\u002F03.auth\u002F13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcertificate-auth","01.csharp\u002F11.aspnet\u002F03.auth\u002F14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frbac-abac-rebac","01.csharp\u002F11.aspnet\u002F03.auth\u002F15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fmulti-tenancy","01.csharp\u002F11.aspnet\u002F03.auth\u002F16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","\u002Fcsharp\u002Faspnet\u002Fnotifications","01.csharp\u002F11.aspnet\u002F04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fin-app-database-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fpolling","01.csharp\u002F11.aspnet\u002F04.notifications\u002F02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fserver-sent-events","01.csharp\u002F11.aspnet\u002F04.notifications\u002F03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fwebsockets","01.csharp\u002F11.aspnet\u002F04.notifications\u002F04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fsignalr","01.csharp\u002F11.aspnet\u002F04.notifications\u002F05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fbackground-services","01.csharp\u002F11.aspnet\u002F04.notifications\u002F06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fweb-push","01.csharp\u002F11.aspnet\u002F04.notifications\u002F07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Femail-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fchoosing-the-right-approach","01.csharp\u002F11.aspnet\u002F04.notifications\u002F09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire","01.csharp\u002F11.aspnet\u002F04.notifications\u002F10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-image-webp","01.csharp\u002F11.aspnet\u002F04.notifications\u002F11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-video-hls","01.csharp\u002F11.aspnet\u002F04.notifications\u002F12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Ftelegram-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","\u002Fcsharp\u002Faspnet\u002Fi18n","01.csharp\u002F11.aspnet\u002F05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Finternationalization","01.csharp\u002F11.aspnet\u002F05.i18n\u002F01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Fhumanizer","01.csharp\u002F11.aspnet\u002F05.i18n\u002F02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","\u002Fcsharp\u002Faspnet\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching\u002F01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fmemory-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fdistributed-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fresponse-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Foutput-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","\u002Fcsharp\u002Faspnet\u002Ftesting","01.csharp\u002F11.aspnet\u002F07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-is-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-pyramid","01.csharp\u002F11.aspnet\u002F07.testing\u002F02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-schools","01.csharp\u002F11.aspnet\u002F07.testing\u002F03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftdd-and-bdd","01.csharp\u002F11.aspnet\u002F07.testing\u002F04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-to-test","01.csharp\u002F11.aspnet\u002F07.testing\u002F05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftest-frameworks","01.csharp\u002F11.aspnet\u002F07.testing\u002F06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-basics","01.csharp\u002F11.aspnet\u002F07.testing\u002F07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fmocking-with-moq","01.csharp\u002F11.aspnet\u002F07.testing\u002F09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fdatabase-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","\u002Fcsharp\u002Faspnet\u002Ftesting\u002F11a.integration-testing-practice","01.csharp\u002F11.aspnet\u002F07.testing\u002F11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fpostman-professional","01.csharp\u002F11.aspnet\u002F07.testing\u002F13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fhttpclient-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwiremock-net","01.csharp\u002F11.aspnet\u002F07.testing\u002F15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-patterns","01.csharp\u002F11.aspnet\u002F07.testing\u002F16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fadvanced-testing-tools","01.csharp\u002F11.aspnet\u002F07.testing\u002F17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Farchitecture-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fperformance-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fremaining_plan","01.csharp\u002F11.aspnet\u002F07.testing\u002Fremaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","\u002Fcsharp\u002Faspnet\u002Fpayments","01.csharp\u002F11.aspnet\u002F08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-fundamentals","01.csharp\u002F11.aspnet\u002F08.payments\u002F01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-methods-ukraine","01.csharp\u002F11.aspnet\u002F08.payments\u002F02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpci-dss-security","01.csharp\u002F11.aspnet\u002F08.payments\u002F03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-architecture","01.csharp\u002F11.aspnet\u002F08.payments\u002F04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fliqpay-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fmonobank-acquiring","01.csharp\u002F11.aspnet\u002F08.payments\u002F06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fstripe-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fwebhooks-deep-dive","01.csharp\u002F11.aspnet\u002F08.payments\u002F08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fsubscriptions-recurring","01.csharp\u002F11.aspnet\u002F08.payments\u002F09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Frefunds-disputes","01.csharp\u002F11.aspnet\u002F08.payments\u002F10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Ftesting-payments","01.csharp\u002F11.aspnet\u002F08.payments\u002F11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fproduction-checklist","01.csharp\u002F11.aspnet\u002F08.payments\u002F12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","\u002Fcsharp\u002Faspnet\u002Flibraries","01.csharp\u002F11.aspnet\u002F09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-validation","01.csharp\u002F11.aspnet\u002F09.libraries\u002F01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmapster","01.csharp\u002F11.aspnet\u002F09.libraries\u002F02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ferroror-result-pattern","01.csharp\u002F11.aspnet\u002F09.libraries\u002F03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fserilog","01.csharp\u002F11.aspnet\u002F09.libraries\u002F04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmediatr","01.csharp\u002F11.aspnet\u002F09.libraries\u002F05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fpolly","01.csharp\u002F11.aspnet\u002F09.libraries\u002F06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F09.libraries\u002F07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffeature-management","01.csharp\u002F11.aspnet\u002F09.libraries\u002F08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-email","01.csharp\u002F11.aspnet\u002F09.libraries\u002F09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fquest-pdf","01.csharp\u002F11.aspnet\u002F09.libraries\u002F10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fbogus","01.csharp\u002F11.aspnet\u002F09.libraries\u002F11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhumanizer-guard","01.csharp\u002F11.aspnet\u002F09.libraries\u002F12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fplan","01.csharp\u002F11.aspnet\u002F09.libraries\u002Fplan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","\u002Fcsharp\u002Faspnet\u002Frazor-pages","01.csharp\u002F11.aspnet\u002F10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ffrom-minimal-api","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fpage-model","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Frazor-syntax","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ftag-helpers","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fforms-validation","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fproject-task-manager","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc","01.csharp\u002F11.aspnet\u002F11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-pattern","01.csharp\u002F11.aspnet\u002F11.mvc\u002F01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffrom-razor-pages","01.csharp\u002F11.aspnet\u002F11.mvc\u002F02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fcontrollers-actions","01.csharp\u002F11.aspnet\u002F11.mvc\u002F03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Frouting-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmodel-binding","01.csharp\u002F11.aspnet\u002F11.mvc\u002F05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fviews-viewdata-tempdata","01.csharp\u002F11.aspnet\u002F11.mvc\u002F06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffilters","01.csharp\u002F11.aspnet\u002F11.mvc\u002F07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fareas","01.csharp\u002F11.aspnet\u002F11.mvc\u002F08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fview-components","01.csharp\u002F11.aspnet\u002F11.mvc\u002F09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fdisplay-editor-templates","01.csharp\u002F11.aspnet\u002F11.mvc\u002F10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fvalidation-advanced","01.csharp\u002F11.aspnet\u002F11.mvc\u002F11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx","01.csharp\u002F11.aspnet\u002F11.mvc\u002F12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fajax-htmx-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffile-upload","01.csharp\u002F11.aspnet\u002F11.mvc\u002F15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fglobalization-localization","01.csharp\u002F11.aspnet\u002F11.mvc\u002F16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fplan","01.csharp\u002F11.aspnet\u002F11.mvc\u002Fplan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","\u002Fcsharp\u002Faspnet\u002Fweb-api","01.csharp\u002F11.aspnet\u002F12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffrom-minimal-api-to-controllers","01.csharp\u002F11.aspnet\u002F12.web-api\u002F01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontroller-base-actionresult","01.csharp\u002F11.aspnet\u002F12.web-api\u002F02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontent-negotiation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-versioning","01.csharp\u002F11.aspnet\u002F12.web-api\u002F04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fproblemdetails-error-handling","01.csharp\u002F11.aspnet\u002F12.web-api\u002F05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffilters-for-api","01.csharp\u002F11.aspnet\u002F12.web-api\u002F06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fpagination-filtering-sorting","01.csharp\u002F11.aspnet\u002F12.web-api\u002F07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhateoas-resource-expansion","01.csharp\u002F11.aspnet\u002F12.web-api\u002F08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fminimal-api-vs-controllers-hybrid","01.csharp\u002F11.aspnet\u002F12.web-api\u002F09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-documentation-generation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhealth-checks-monitoring","01.csharp\u002F11.aspnet\u002F12.web-api\u002F11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fweb-api-project","01.csharp\u002F11.aspnet\u002F12.web-api\u002F12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fplan","01.csharp\u002F11.aspnet\u002F12.web-api\u002Fplan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Моніторинг","i-lucide-activity","\u002Fcsharp\u002Faspnet\u002Fmonitoring","01.csharp\u002F11.aspnet\u002F13.monitoring",[1352,1356,1360],{"title":1353,"path":1354,"stem":1355},"Спостережуваність: від console.log до production-систем","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fobservability-intro","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F01.observability-intro",{"title":1357,"path":1358,"stem":1359},"Health Checks: перший рівень observability","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F02.health-checks",{"title":1361,"path":1362,"stem":1363},"Вбудовані метрики .NET 10 та System.Diagnostics.Metrics","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fdotnet-metrics","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F03.dotnet-metrics",{"title":1365,"icon":1366,"path":1367,"stem":1368,"children":1369,"page":59},"Desktop UI","i-lucide-app-window","\u002Fcsharp\u002Fdesktop-ui","01.csharp\u002F12.desktop-ui",[1370,1374,1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1474,1478,1482,1486,1490,1494,1498,1502,1506,1510,1514,1518,1522,1526,1530,1534,1538,1542,1546,1550,1554,1558,1562,1566,1570,1574,1578,1582,1586,1590,1594,1598,1602,1606,1610,1614,1618,1622,1626,1630,1634,1638,1642,1646,1650],{"title":1371,"path":1372,"stem":1373},"Що таке десктопна розробка?","\u002Fcsharp\u002Fdesktop-ui\u002Fwhat-is-desktop-dev","01.csharp\u002F12.desktop-ui\u002F01.what-is-desktop-dev",{"title":1375,"path":1376,"stem":1377},"Архітектура WPF — як влаштований графічний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-architecture","01.csharp\u002F12.desktop-ui\u002F02.wpf-architecture",{"title":1379,"path":1380,"stem":1381},"Перший WPF-проєкт — від нуля до вікна","\u002Fcsharp\u002Fdesktop-ui\u002Ffirst-wpf-app","01.csharp\u002F12.desktop-ui\u002F03.first-wpf-app",{"title":1383,"path":1384,"stem":1385},"Перший Avalonia-проєкт: WPF для всіх платформ","\u002Fcsharp\u002Fdesktop-ui\u002F03a.first-avalonia-app","01.csharp\u002F12.desktop-ui\u002F03a.first-avalonia-app",{"title":1387,"path":1388,"stem":1389},"XAML: декларативний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-basics","01.csharp\u002F12.desktop-ui\u002F04.xaml-basics",{"title":1391,"path":1392,"stem":1393},"Fluent UI у WPF — сучасний дизайн Windows 11","\u002Fcsharp\u002Fdesktop-ui\u002F04a.wpf-fluent-ui","01.csharp\u002F12.desktop-ui\u002F04a.wpf-fluent-ui",{"title":1395,"path":1396,"stem":1397},"WPF UI — сучасна бібліотека Fluent контролів","\u002Fcsharp\u002Fdesktop-ui\u002F04b.wpf-ui-library","01.csharp\u002F12.desktop-ui\u002F04b.wpf-ui-library",{"title":1399,"path":1400,"stem":1401},"HandyControl — велика бібліотека UI контролів для WPF","\u002Fcsharp\u002Fdesktop-ui\u002F04c.handycontrol-library","01.csharp\u002F12.desktop-ui\u002F04c.handycontrol-library",{"title":1403,"path":1404,"stem":1405},"Простори імен та ресурси XAML","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-namespaces-resources","01.csharp\u002F12.desktop-ui\u002F05.xaml-namespaces-resources",{"title":1407,"path":1408,"stem":1409},"XAML в Avalonia: ключові відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F05a.avalonia-xaml-differences","01.csharp\u002F12.desktop-ui\u002F05a.avalonia-xaml-differences",{"title":1411,"path":1412,"stem":1413},"Розширення розмітки XAML (Markup Extensions)","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-markup-extensions","01.csharp\u002F12.desktop-ui\u002F06.xaml-markup-extensions",{"title":1415,"path":1416,"stem":1417},"Панелі Layout: StackPanel, WrapPanel, DockPanel","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part1","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part1",{"title":1419,"path":1420,"stem":1421},"Grid, Canvas, UniformGrid","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part2","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part2",{"title":1423,"path":1424,"stem":1425},"Просунуті техніки Layout","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-advanced","01.csharp\u002F12.desktop-ui\u002F08.layout-advanced",{"title":1427,"path":1428,"stem":1429},"Адаптивний Layout та найкращі практики","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-responsive","01.csharp\u002F12.desktop-ui\u002F09.layout-responsive",{"title":1431,"path":1432,"stem":1433},"Layout в Avalonia: відмінності та нові можливості","\u002Fcsharp\u002Fdesktop-ui\u002F09a.layout-avalonia","01.csharp\u002F12.desktop-ui\u002F09a.layout-avalonia",{"title":1435,"path":1436,"stem":1437},"Button, Image, ProgressBar та інші базові контроли","\u002Fcsharp\u002Fdesktop-ui\u002Fbasic-controls","01.csharp\u002F12.desktop-ui\u002F10.basic-controls",{"title":1439,"path":1440,"stem":1441},"Контроли в Avalonia: відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F10a.controls-avalonia","01.csharp\u002F12.desktop-ui\u002F10a.controls-avalonia",{"title":1443,"path":1444,"stem":1445},"Текстові контроли — TextBlock, TextBox, RichTextBox","\u002Fcsharp\u002Fdesktop-ui\u002Ftext-controls","01.csharp\u002F12.desktop-ui\u002F11.text-controls",{"title":1447,"path":1448,"stem":1449},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","\u002Fcsharp\u002Fdesktop-ui\u002Fselection-controls","01.csharp\u002F12.desktop-ui\u002F12.selection-controls",{"title":1451,"path":1452,"stem":1453},"Content Model — GroupBox, Expander, TabControl, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fcontent-controls","01.csharp\u002F12.desktop-ui\u002F13.content-controls",{"title":1455,"path":1456,"stem":1457},"UI\u002FUX принципи десктопних застосунків","\u002Fcsharp\u002Fdesktop-ui\u002F13a.ui-ux-principles","01.csharp\u002F12.desktop-ui\u002F13a.ui-ux-principles",{"title":1459,"path":1460,"stem":1461},"Dependency Properties — Концепція та Value Resolution","\u002Fcsharp\u002Fdesktop-ui\u002Fdependency-properties-part1","01.csharp\u002F12.desktop-ui\u002F14.dependency-properties-part1",{"title":1463,"path":1464,"stem":1465},"Avalonia Property System — StyledProperty та DirectProperty","\u002Fcsharp\u002Fdesktop-ui\u002F14a.avalonia-property-system","01.csharp\u002F12.desktop-ui\u002F14a.avalonia-property-system",{"title":1467,"path":1468,"stem":1469},"Attached Properties — Властивості без меж","\u002Fcsharp\u002Fdesktop-ui\u002Fattached-properties","01.csharp\u002F12.desktop-ui\u002F15.attached-properties",{"title":1471,"path":1472,"stem":1473},"Routed Events — Маршрутизація подій у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Frouted-events","01.csharp\u002F12.desktop-ui\u002F16.routed-events",{"title":1475,"path":1476,"stem":1477},"Data Binding — Від Code-Behind до Декларативності","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part1","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part1",{"title":1479,"path":1480,"stem":1481},"INotifyPropertyChanged — Живе оновлення UI","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part2","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part2",{"title":1483,"path":1484,"stem":1485},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","\u002Fcsharp\u002Fdesktop-ui\u002F17a.avalonia-compiled-bindings","01.csharp\u002F12.desktop-ui\u002F17a.avalonia-compiled-bindings",{"title":1487,"path":1488,"stem":1489},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-advanced","01.csharp\u002F12.desktop-ui\u002F18.data-binding-advanced",{"title":1491,"path":1492,"stem":1493},"Value Converters — Перетворення типів даних у Data Binding","\u002Fcsharp\u002Fdesktop-ui\u002Fvalue-converters","01.csharp\u002F12.desktop-ui\u002F19.value-converters",{"title":1495,"path":1496,"stem":1497},"Data Templates — Візуалізація об'єктів у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-templates","01.csharp\u002F12.desktop-ui\u002F20.data-templates",{"title":1499,"path":1500,"stem":1501},"Collections Binding Part 1 — ObservableCollection та ItemsControl","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part1","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part1",{"title":1503,"path":1504,"stem":1505},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part2","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part2",{"title":1507,"path":1508,"stem":1509},"MVVM Pattern — Від Spaghetti Code до архітектури","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-pattern","01.csharp\u002F12.desktop-ui\u002F22.mvvm-pattern",{"title":1511,"path":1512,"stem":1513},"ViewModel Implementation — Від BaseViewModel до валідації","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-implementation","01.csharp\u002F12.desktop-ui\u002F23.viewmodel-implementation",{"title":1515,"path":1516,"stem":1517},"Commands — Від event handlers до декларативних команд","\u002Fcsharp\u002Fdesktop-ui\u002Fcommands","01.csharp\u002F12.desktop-ui\u002F24.commands",{"title":1519,"path":1520,"stem":1521},"MVVM Toolkit — MVVM без boilerplate через Source Generators","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-toolkit","01.csharp\u002F12.desktop-ui\u002F25.mvvm-toolkit",{"title":1523,"path":1524,"stem":1525},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","\u002Fcsharp\u002Fdesktop-ui\u002Fmessenger-pattern","01.csharp\u002F12.desktop-ui\u002F26.messenger-pattern",{"title":1527,"path":1528,"stem":1529},"Стилі WPF — CSS для десктопу","\u002Fcsharp\u002Fdesktop-ui\u002Fstyles-basics","01.csharp\u002F12.desktop-ui\u002F27.styles-basics",{"title":1531,"path":1532,"stem":1533},"CSS-like стилі Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F27a.avalonia-css-styling","01.csharp\u002F12.desktop-ui\u002F27a.avalonia-css-styling",{"title":1535,"path":1536,"stem":1537},"Control Templates — Частина 1. Концепція та TemplateBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part1","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part1",{"title":1539,"path":1540,"stem":1541},"Control Templates — Частина 2. Named Parts та ContentPresenter","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part2","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part2",{"title":1543,"path":1544,"stem":1545},"Control Themes в Avalonia — нова ера стилізації","\u002Fcsharp\u002Fdesktop-ui\u002F28a.avalonia-control-themes","01.csharp\u002F12.desktop-ui\u002F28a.avalonia-control-themes",{"title":1547,"path":1548,"stem":1549},"Triggers та Visual State Manager у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Ftriggers-visual-states","01.csharp\u002F12.desktop-ui\u002F29.triggers-visual-states",{"title":1551,"path":1552,"stem":1553},"Pseudo-classes в Avalonia — замість WPF Triggers","\u002Fcsharp\u002Fdesktop-ui\u002F29a.avalonia-pseudo-classes","01.csharp\u002F12.desktop-ui\u002F29a.avalonia-pseudo-classes",{"title":1555,"path":1556,"stem":1557},"Теми та ресурсні словники у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fresources-themes","01.csharp\u002F12.desktop-ui\u002F30.resources-themes",{"title":1559,"path":1560,"stem":1561},"Avalonia Themes — Fluent Design та система тематизації","\u002Fcsharp\u002Fdesktop-ui\u002F30a.avalonia-themes-fluent","01.csharp\u002F12.desktop-ui\u002F30a.avalonia-themes-fluent",{"title":1563,"path":1564,"stem":1565},"Контроли колекцій — глибоке занурення","\u002Fcsharp\u002Fdesktop-ui\u002Fcollection-controls","01.csharp\u002F12.desktop-ui\u002F31.collection-controls",{"title":1567,"path":1568,"stem":1569},"DataGrid — колонки та базове відображення","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part1","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part1",{"title":1571,"path":1572,"stem":1573},"DataGrid — сортування, фільтрація, редагування","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part2","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part2",{"title":1575,"path":1576,"stem":1577},"TreeView та GridView","\u002Fcsharp\u002Fdesktop-ui\u002Ftreeview-listview","01.csharp\u002F12.desktop-ui\u002F33.treeview-listview",{"title":1579,"path":1580,"stem":1581},"Меню, Toolbar, ContextMenu, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fmenus-toolbars","01.csharp\u002F12.desktop-ui\u002F34.menus-toolbars",{"title":1583,"path":1584,"stem":1585},"Навігація та керування вікнами. Частина 1: вікна та сторінки","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part1","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part1",{"title":1587,"path":1588,"stem":1589},"Навігація та керування вікнами. Частина 2: MVVM-навігація","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part2","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part2",{"title":1591,"path":1592,"stem":1593},"Avalonia — Навігація та діалоги","\u002Fcsharp\u002Fdesktop-ui\u002F35a.avalonia-navigation-dialogs","01.csharp\u002F12.desktop-ui\u002F35a.avalonia-navigation-dialogs",{"title":1595,"path":1596,"stem":1597},"Діалоги та File Pickers у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdialogs-file-pickers","01.csharp\u002F12.desktop-ui\u002F36.dialogs-file-pickers",{"title":1599,"path":1600,"stem":1601},"UserControl: компонентний підхід у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fuser-controls","01.csharp\u002F12.desktop-ui\u002F37.user-controls",{"title":1603,"path":1604,"stem":1605},"Custom Controls: Lookless Controls у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fcustom-controls","01.csharp\u002F12.desktop-ui\u002F38.custom-controls",{"title":1607,"path":1608,"stem":1609},"Avalonia TemplatedControl — Lookless Controls","\u002Fcsharp\u002Fdesktop-ui\u002F38a.avalonia-templated-controls","01.csharp\u002F12.desktop-ui\u002F38a.avalonia-templated-controls",{"title":1611,"path":1612,"stem":1613},"Анімації у WPF: Storyboard та Easing Functions","\u002Fcsharp\u002Fdesktop-ui\u002Fanimations-transitions","01.csharp\u002F12.desktop-ui\u002F39.animations-transitions",{"title":1615,"path":1616,"stem":1617},"Анімації в Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F39a.avalonia-animations","01.csharp\u002F12.desktop-ui\u002F39a.avalonia-animations",{"title":1619,"path":1620,"stem":1621},"2D Графіка та Мультимедіа у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fmedia-graphics","01.csharp\u002F12.desktop-ui\u002F40.media-graphics",{"title":1623,"path":1624,"stem":1625},"Dependency Injection у WPF та Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Fdi-integration","01.csharp\u002F12.desktop-ui\u002F41.di-integration",{"title":1627,"path":1628,"stem":1629},"SQLite та EF Core у десктопних додатках","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part1","01.csharp\u002F12.desktop-ui\u002F42.data-persistence-part1",{"title":1631,"path":1632,"stem":1633},"Repository Pattern та Unit of Work","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part2","01.csharp\u002F12.desktop-ui\u002F43.data-persistence-part2",{"title":1635,"path":1636,"stem":1637},"Тестування ViewModels","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-testing","01.csharp\u002F12.desktop-ui\u002F44.viewmodel-testing",{"title":1639,"path":1640,"stem":1641},"Avalonia Headless Testing — тестування UI без вікон","\u002Fcsharp\u002Fdesktop-ui\u002F44a.avalonia-headless-testing","01.csharp\u002F12.desktop-ui\u002F44a.avalonia-headless-testing",{"title":1643,"path":1644,"stem":1645},"Кросплатформна розробка з Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-cross-platform","01.csharp\u002F12.desktop-ui\u002F45.avalonia-cross-platform",{"title":1647,"path":1648,"stem":1649},"Пакування та розгортання Avalonia додатків","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F46.avalonia-packaging-deployment",{"title":1651,"path":1652,"stem":1653},"Розгортання WPF застосунків","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F47.wpf-packaging-deployment",{"title":1655,"icon":658,"path":1656,"stem":1657,"children":1658,"page":59},"Network Programming","\u002Fcsharp\u002Fnetwork-programming","01.csharp\u002F13.network-programming",[1659,1663,1667,1671,1675,1679,1683,1687,1691,1695,1699],{"title":1660,"path":1661,"stem":1662},"Основи комп'ютерних мереж","\u002Fcsharp\u002Fnetwork-programming\u002Ffoundations","01.csharp\u002F13.network-programming\u002F01.foundations",{"title":1664,"path":1665,"stem":1666},"Модель OSI та стек TCP\u002FIP","\u002Fcsharp\u002Fnetwork-programming\u002Fosi-model","01.csharp\u002F13.network-programming\u002F02.osi-model",{"title":1668,"path":1669,"stem":1670},"IP-протокол та адресація","\u002Fcsharp\u002Fnetwork-programming\u002Fip-addressing","01.csharp\u002F13.network-programming\u002F03.ip-addressing",{"title":1672,"path":1673,"stem":1674},"UDP — протокол без з'єднання","\u002Fcsharp\u002Fnetwork-programming\u002Fudp","01.csharp\u002F13.network-programming\u002F05.udp",{"title":1676,"path":1677,"stem":1678},"UDP Broadcast та Multicast","\u002Fcsharp\u002Fnetwork-programming\u002Fudp-broadcast-multicast","01.csharp\u002F13.network-programming\u002F06.udp-broadcast-multicast",{"title":1680,"path":1681,"stem":1682},"HTTP — протокол вебу","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-fundamentals","01.csharp\u002F13.network-programming\u002F07.http-fundamentals",{"title":1684,"path":1685,"stem":1686},"HttpListener — вбудований HTTP-сервер .NET","\u002Fcsharp\u002Fnetwork-programming\u002F07a.http-listener","01.csharp\u002F13.network-programming\u002F07a.http-listener",{"title":1688,"path":1689,"stem":1690},"HTTP Advanced — cookies, аутентифікація та HTTPS","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-advanced","01.csharp\u002F13.network-programming\u002F08.http-advanced",{"title":1692,"path":1693,"stem":1694},"SMTP та протоколи електронної пошти","\u002Fcsharp\u002Fnetwork-programming\u002Fsmtp","01.csharp\u002F13.network-programming\u002F09.smtp",{"title":1696,"path":1697,"stem":1698},"WebSocket — повнодуплексний протокол реального часу","\u002Fcsharp\u002Fnetwork-programming\u002Fwebsockets","01.csharp\u002F13.network-programming\u002F10.websockets",{"title":1700,"path":1701,"stem":1702},"TLS\u002FSSL — криптографічний захист мережевих з'єднань","\u002Fcsharp\u002Fnetwork-programming\u002Ftls-ssl","01.csharp\u002F13.network-programming\u002F11.tls-ssl",{"title":1704,"path":1705,"stem":1706},"C# & .NET: The Ultimate Roadmap","\u002Fcsharp\u002Froadmap","01.csharp\u002Froadmap",{"title":1708,"icon":1709,"path":1710,"stem":1711,"children":1712,"page":59},"C++","i-devicon-cplusplus","\u002Fcpp","02.cpp",[1713,1717,1721,1725,1729,1733,1737,1741,1745,1748,1752,1756,1760,1764,1768,1772,1776,1780,1784,1788,1792,1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892,1896,1900],{"title":1714,"path":1715,"stem":1716},"Вступ у програмування та алгоритми","\u002Fcpp\u002Fintro-algorithms","02.cpp\u002F01.intro-algorithms",{"title":1718,"path":1719,"stem":1720},"Code Style: угоди про оформлення коду","\u002Fcpp\u002Fcode-style","02.cpp\u002F02.code-style",{"title":1722,"path":1723,"stem":1724},"Середовище розробки та перший проєкт","\u002Fcpp\u002Fide-setup","02.cpp\u002F03.ide-setup",{"title":1726,"path":1727,"stem":1728},"Вивід даних на екран","\u002Fcpp\u002Fdata-output","02.cpp\u002F04.data-output",{"title":1730,"path":1731,"stem":1732},"Типи даних, змінні та константи","\u002Fcpp\u002Fdata-types-variables","02.cpp\u002F05.data-types-variables",{"title":1734,"path":1735,"stem":1736},"Ввід даних з клавіатури","\u002Fcpp\u002Fdata-input","02.cpp\u002F06.data-input",{"title":1738,"path":1739,"stem":1740},"Оператори, перетворення типів та логічні операції","\u002Fcpp\u002Foperators-type-conversion","02.cpp\u002F07.operators-type-conversion",{"title":1742,"path":1743,"stem":1744},"Цикли","\u002Fcpp\u002Floops","02.cpp\u002F08.loops",{"title":32,"path":1746,"stem":1747},"\u002Fcpp\u002Farrays","02.cpp\u002F09.arrays",{"title":1749,"path":1750,"stem":1751},"Алгоритми сортування та аналіз складності","\u002Fcpp\u002Fsorting","02.cpp\u002F10.sorting",{"title":1753,"path":1754,"stem":1755},"Алгоритми пошуку","\u002Fcpp\u002Fsearching","02.cpp\u002F11.searching",{"title":1757,"path":1758,"stem":1759},"Функції: основи","\u002Fcpp\u002Ffunctions-basics","02.cpp\u002F12.functions-basics",{"title":1761,"path":1762,"stem":1763},"Функції: прототипи, область видимості та додаткові можливості","\u002Fcpp\u002Ffunctions-scope","02.cpp\u002F13.functions-scope",{"title":1765,"path":1766,"stem":1767},"Функції: перевантаження та шаблони","\u002Fcpp\u002Ffunctions-overloading-templates","02.cpp\u002F14.functions-overloading-templates",{"title":1769,"path":1770,"stem":1771},"Вказівники: основи","\u002Fcpp\u002Fpointers-basics","02.cpp\u002F15.pointers-basics",{"title":1773,"path":1774,"stem":1775},"Посилання (References)","\u002Fcpp\u002Freferences","02.cpp\u002F16.references",{"title":1777,"path":1778,"stem":1779},"Вказівники, const і масиви","\u002Fcpp\u002Fpointers-const-arrays","02.cpp\u002F17.pointers-const-arrays",{"title":1781,"path":1782,"stem":1783},"Адресна арифметика","\u002Fcpp\u002Fpointer-arithmetic","02.cpp\u002F18.pointer-arithmetic",{"title":1785,"path":1786,"stem":1787},"Динамічна пам'ять","\u002Fcpp\u002Fdynamic-memory","02.cpp\u002F19.dynamic-memory",{"title":1789,"path":1790,"stem":1791},"Вказівники типу void","\u002Fcpp\u002Fvoid-pointers","02.cpp\u002F20.void-pointers",{"title":1793,"path":1794,"stem":1795},"Вказівники на вказівники","\u002Fcpp\u002Fpointers-to-pointers","02.cpp\u002F21.pointers-to-pointers",{"title":1797,"path":1798,"stem":1799},"Оператор доступу до членів через вказівник (->)","\u002Fcpp\u002Fmember-access-operator","02.cpp\u002F22.member-access-operator",{"title":1801,"path":1802,"stem":1803},"Цикл for-each (Range-based for)","\u002Fcpp\u002Fforeach-loop","02.cpp\u002F23.foreach-loop",{"title":1805,"path":1806,"stem":1807},"Вказівники на функції","\u002Fcpp\u002Ffunction-pointers","02.cpp\u002F24.function-pointers",{"title":1809,"path":1810,"stem":1811},"Лямбда-вирази","\u002Fcpp\u002Flambdas","02.cpp\u002F25.lambdas",{"title":1813,"path":1814,"stem":1815},"Лямбда-захоплення","\u002Fcpp\u002Flambda-captures","02.cpp\u002F26.lambda-captures",{"title":1817,"path":1818,"stem":1819},"Еліпсис","\u002Fcpp\u002Fellipsis","02.cpp\u002F27.ellipsis",{"title":1821,"path":1822,"stem":1823},"Безпечні альтернативи еліпсису","\u002Fcpp\u002F27a.ellipsis","02.cpp\u002F27a.ellipsis",{"title":1825,"path":1826,"stem":1827},"Аргументи командного рядка","\u002Fcpp\u002Fcommand-line-arguments","02.cpp\u002F28.command-line-arguments",{"title":1829,"path":1830,"stem":1831},"Перерахування (enum)","\u002Fcpp\u002Fenum","02.cpp\u002F29.enum",{"title":1833,"path":1834,"stem":1835},"Класи-перерахування (enum class)","\u002Fcpp\u002Fenum-class","02.cpp\u002F30.enum-class",{"title":1837,"path":1838,"stem":1839},"Псевдоніми типів (typedef і using)","\u002Fcpp\u002Ftype-aliases","02.cpp\u002F31.type-aliases",{"title":1841,"path":1842,"stem":1843},"Системи числення та двійкова арифметика","\u002Fcpp\u002Fnumber-systems","02.cpp\u002F32.number-systems",{"title":1845,"path":1846,"stem":1847},"Структури (struct): агрегування даних","\u002Fcpp\u002Fstruct","02.cpp\u002F33.struct",{"title":1849,"path":1850,"stem":1851},"Структури у функціях","\u002Fcpp\u002Fstruct-functions","02.cpp\u002F34.struct-functions",{"title":1853,"path":1854,"stem":1855},"Масиви структур і вкладені структури","\u002Fcpp\u002Fstruct-arrays","02.cpp\u002F35.struct-arrays",{"title":1857,"path":1858,"stem":1859},"Патерни struct та межі застосування","\u002Fcpp\u002Fstruct-patterns","02.cpp\u002F36.struct-patterns",{"title":1861,"path":1862,"stem":1863},"Символи та таблиця ASCII","\u002Fcpp\u002Fascii-characters","02.cpp\u002F37.ascii-characters",{"title":1865,"path":1866,"stem":1867},"Unicode та кодування UTF","\u002Fcpp\u002Funicode-utf","02.cpp\u002F38.unicode-utf",{"title":1869,"path":1870,"stem":1871},"C-style рядки","\u002Fcpp\u002Fc-strings","02.cpp\u002F39.c-strings",{"title":1873,"path":1874,"stem":1875},"Вступ до std::string","\u002Fcpp\u002Fstd-string-intro","02.cpp\u002F40.std-string-intro",{"title":1877,"path":1878,"stem":1879},"Довжина, ємність та доступ до символів std::string","\u002Fcpp\u002Fstd-string-capacity-access","02.cpp\u002F41.std-string-capacity-access",{"title":1881,"path":1882,"stem":1883},"Модифікація std::string: присвоювання, додавання, вставка, видалення та заміна","\u002Fcpp\u002Fstd-string-modification","02.cpp\u002F42.std-string-modification",{"title":1885,"path":1886,"stem":1887},"Пошук у std::string: find, npos та практичні патерни","\u002Fcpp\u002Fstd-string-search","02.cpp\u002F43.std-string-search",{"title":1889,"path":1890,"stem":1891},"std::string_view: невласницький погляд на рядок без копіювання","\u002Fcpp\u002Fstd-string-view","02.cpp\u002F44.std-string-view",{"title":1893,"path":1894,"stem":1895},"Об'єднання (union): один блок пам'яті, кілька інтерпретацій","\u002Fcpp\u002Funion","02.cpp\u002F45.union",{"title":1897,"path":1898,"stem":1899},"Організація коду: файли, препроцесор, простори імен","\u002Fcpp\u002Fmultifile-programs","02.cpp\u002F46.multifile-programs",{"title":1901,"path":1902,"stem":1903},"План навчання: Курс C++ — Продовження (Статті 29–60+)","\u002Fcpp\u002Fcurriculum-plan","02.cpp\u002Fcurriculum-plan",{"title":1905,"icon":1906,"path":1907,"stem":1908,"children":1909,"page":59},"JavaScript","i-devicon-javascript","\u002Fjavascript","03.javascript",[1910,1936,1990,2012,2316,2354],{"title":1911,"icon":1912,"path":1913,"stem":1914,"children":1915,"page":59},"Events","i-lucide-mouse-pointer-click","\u002Fjavascript\u002Fevents","03.javascript\u002F01.events",[1916,1920,1924,1928,1932],{"title":1917,"path":1918,"stem":1919},"Вступ до подій браузера","\u002Fjavascript\u002Fevents\u002Fintro","03.javascript\u002F01.events\u002F01.intro",{"title":1921,"path":1922,"stem":1923},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","\u002Fjavascript\u002Fevents\u002Fbubbling-capturing","03.javascript\u002F01.events\u002F02.bubbling-capturing",{"title":1925,"path":1926,"stem":1927},"Делегування подій (Event Delegation)","\u002Fjavascript\u002Fevents\u002Fdelegate-events","03.javascript\u002F01.events\u002F03.delegate-events",{"title":1929,"path":1930,"stem":1931},"Типові дії браузера та preventDefault()","\u002Fjavascript\u002Fevents\u002Fprevent-default","03.javascript\u002F01.events\u002F04.prevent-default",{"title":1933,"path":1934,"stem":1935},"Запуск користувацьких подій (Custom Events)","\u002Fjavascript\u002Fevents\u002Fcustom-events","03.javascript\u002F01.events\u002F05.custom-events",{"title":1937,"icon":1938,"path":1939,"stem":1940,"children":1941,"page":59},"Network","i-lucide-globe","\u002Fjavascript\u002Fnetwork","03.javascript\u002F02.network",[1942,1946,1950,1954,1958,1962,1966,1970,1974,1978,1982,1986],{"title":1943,"path":1944,"stem":1945},"Fetch API - Сучасний підхід до HTTP-запитів","\u002Fjavascript\u002Fnetwork\u002F01-fetch-api","03.javascript\u002F02.network\u002F01-fetch-api",{"title":1947,"path":1948,"stem":1949},"FormData - Робота з формами та файлами","\u002Fjavascript\u002Fnetwork\u002F02-formdata","03.javascript\u002F02.network\u002F02-formdata",{"title":1951,"path":1952,"stem":1953},"Відстеження прогресу завантаження","\u002Fjavascript\u002Fnetwork\u002F03-download-progress","03.javascript\u002F02.network\u002F03-download-progress",{"title":1955,"path":1956,"stem":1957},"Переривання fetch-запитів","\u002Fjavascript\u002Fnetwork\u002F04-abort-requests","03.javascript\u002F02.network\u002F04-abort-requests",{"title":1959,"path":1960,"stem":1961},"CORS - Запити між різними джерелами","\u002Fjavascript\u002Fnetwork\u002F05-cors","03.javascript\u002F02.network\u002F05-cors",{"title":1963,"path":1964,"stem":1965},"Fetch API - Повний довідник опцій","\u002Fjavascript\u002Fnetwork\u002F06-fetch-options","03.javascript\u002F02.network\u002F06-fetch-options",{"title":1967,"path":1968,"stem":1969},"URL Objects - Робота з посиланнями","\u002Fjavascript\u002Fnetwork\u002F07-url-objects","03.javascript\u002F02.network\u002F07-url-objects",{"title":1971,"path":1972,"stem":1973},"XMLHttpRequest - AJAX та низькорівневі запити","\u002Fjavascript\u002Fnetwork\u002F08-xmlhttprequest","03.javascript\u002F02.network\u002F08-xmlhttprequest",{"title":1975,"path":1976,"stem":1977},"Відновлюване завантаження файлів","\u002Fjavascript\u002Fnetwork\u002F09-resumable-upload","03.javascript\u002F02.network\u002F09-resumable-upload",{"title":1979,"path":1980,"stem":1981},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","\u002Fjavascript\u002Fnetwork\u002F10-cookies","03.javascript\u002F02.network\u002F10-cookies",{"title":1983,"path":1984,"stem":1985},"js-cookie: Керування Cookies без Болю","\u002Fjavascript\u002Fnetwork\u002F11-js-cookie","03.javascript\u002F02.network\u002F11-js-cookie",{"title":1987,"path":1988,"stem":1989},"Axios: Потужний HTTP-клієнт для JavaScript","\u002Fjavascript\u002Fnetwork\u002F12-axios","03.javascript\u002F02.network\u002F12-axios",{"title":1991,"icon":1992,"path":1993,"stem":1994,"children":1995,"page":59},"Bom","i-lucide-monitor","\u002Fjavascript\u002Fbom","03.javascript\u002F03.bom",[1996,2000,2004,2008],{"title":1997,"path":1998,"stem":1999},"LocalStorage, SessionStorage та patterns збереження даних","\u002Fjavascript\u002Fbom\u002F01-localstorage","03.javascript\u002F03.bom\u002F01-localstorage",{"title":2001,"path":2002,"stem":2003},"Location Object - Керування адресою сторінки","\u002Fjavascript\u002Fbom\u002F02-location-object","03.javascript\u002F03.bom\u002F02-location-object",{"title":2005,"path":2006,"stem":2007},"History API - Керування історією браузера","\u002Fjavascript\u002Fbom\u002F03-history-api","03.javascript\u002F03.bom\u002F03-history-api",{"title":2009,"path":2010,"stem":2011},"Navigator Object - Ідентифікація та Можливості Пристрою","\u002Fjavascript\u002Fbom\u002F04-navigator-object","03.javascript\u002F03.bom\u002F04-navigator-object",{"title":2013,"icon":2014,"path":2015,"stem":2016,"children":2017},"React","i-devicon-react","\u002Fjavascript\u002Freact","03.javascript\u002F04.react\u002Findex",[2018,2019,2023,2027,2031,2035,2098,2133,2285],{"title":2013,"path":2015,"stem":2016},{"title":2020,"path":2021,"stem":2022},"Робота з Формами в React","\u002Fjavascript\u002Freact\u002Freact-forms","03.javascript\u002F04.react\u002F01.react-forms",{"title":2024,"path":2025,"stem":2026},"React Hook Form: Професійна Робота з Формами","\u002Fjavascript\u002Freact\u002Freact-hook-form","03.javascript\u002F04.react\u002F02.react-hook-form",{"title":2028,"path":2029,"stem":2030},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","\u002Fjavascript\u002Freact\u002Freact-hook-form-new","03.javascript\u002F04.react\u002F02.react-hook-form-new",{"title":2032,"path":2033,"stem":2034},"Axios та React: Професійна Архітектура Запитів","\u002Fjavascript\u002Freact\u002Fdata-fetching-axios","03.javascript\u002F04.react\u002F03.data-fetching-axios",{"title":2036,"icon":132,"path":2037,"stem":2038,"children":2039},"Tanstack Query","\u002Fjavascript\u002Freact\u002Ftanstack-query","03.javascript\u002F04.react\u002F04.tanstack-query\u002Findex",[2040,2042,2046,2050,2054,2058,2062,2066,2070,2074,2078,2082,2086,2090,2094],{"title":2041,"path":2037,"stem":2038},"TanStack Query: Майстерність Керування Станом Сервера",{"title":2043,"path":2044,"stem":2045},"Парадигма Server State: Чому useEffect недостатньо","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-state-paradigm","03.javascript\u002F04.react\u002F04.tanstack-query\u002F01.server-state-paradigm",{"title":2047,"path":2048,"stem":2049},"Встановлення та Налаштування: Фундамент","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Finstallation-and-devtools","03.javascript\u002F04.react\u002F04.tanstack-query\u002F02.installation-and-devtools",{"title":2051,"path":2052,"stem":2053},"Основи Запитів та Магія Ключів","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fquery-basics-and-keys","03.javascript\u002F04.react\u002F04.tanstack-query\u002F03.query-basics-and-keys",{"title":2055,"path":2056,"stem":2057},"Синхронізація Даних: Життєвий Цикл Запиту","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fdata-synchronization","03.javascript\u002F04.react\u002F04.tanstack-query\u002F04.data-synchronization",{"title":2059,"path":2060,"stem":2061},"Мутації та Інвалідація: Зміна Даних","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fmutations-and-invalidation","03.javascript\u002F04.react\u002F04.tanstack-query\u002F05.mutations-and-invalidation",{"title":2063,"path":2064,"stem":2065},"Оптимістичні Оновлення: Швидше за Світло","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Foptimistic-updates","03.javascript\u002F04.react\u002F04.tanstack-query\u002F06.optimistic-updates",{"title":2067,"path":2068,"stem":2069},"Пагінація та Infinite Scroll","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fpagination-and-load-more","03.javascript\u002F04.react\u002F04.tanstack-query\u002F07.pagination-and-load-more",{"title":2071,"path":2072,"stem":2073},"Просунуті Патерни та Оптимізація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F04.tanstack-query\u002F08.advanced-patterns",{"title":2075,"path":2076,"stem":2077},"Архітектура та Best Practices","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Farchitecture-and-best-practices","03.javascript\u002F04.react\u002F04.tanstack-query\u002F09.architecture-and-best-practices",{"title":2079,"path":2080,"stem":2081},"Server-Side Rendering (SSR) та Гідратація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-side-rendering","03.javascript\u002F04.react\u002F04.tanstack-query\u002F10.server-side-rendering",{"title":2083,"path":2084,"stem":2085},"Стратегії Тестування","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Ftesting-strategies","03.javascript\u002F04.react\u002F04.tanstack-query\u002F11.testing-strategies",{"title":2087,"path":2088,"stem":2089},"Аутентифікація та Обробка Помилок","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fauthentication-and-errors","03.javascript\u002F04.react\u002F04.tanstack-query\u002F12.authentication-and-errors",{"title":2091,"path":2092,"stem":2093},"React Suspense та Майбутнє","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Freact-suspense","03.javascript\u002F04.react\u002F04.tanstack-query\u002F13.react-suspense",{"title":2095,"path":2096,"stem":2097},"Глибоке Занурення в Продуктивність","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fperformance-deep-dive","03.javascript\u002F04.react\u002F04.tanstack-query\u002F14.performance-deep-dive",{"title":2099,"icon":2014,"path":2100,"stem":2101,"children":2102},"React Router","\u002Fjavascript\u002Freact\u002Freact-router","03.javascript\u002F04.react\u002F05.react-router\u002Findex",[2103,2105,2109,2113,2117,2121,2125,2129],{"title":2104,"path":2100,"stem":2101},"React Router: Навігаційна система сучасного вебу",{"title":2106,"path":2107,"stem":2108},"Налаштування та Базовий Роутинг","\u002Fjavascript\u002Freact\u002Freact-router\u002Fsetup-and-basic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F01.setup-and-basic-routing",{"title":2110,"path":2111,"stem":2112},"Динамічна Навігація","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnavigation-and-links","03.javascript\u002F04.react\u002F05.react-router\u002F02.navigation-and-links",{"title":2114,"path":2115,"stem":2116},"Вкладені Маршрути та Макети","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnested-routes-and-layouts","03.javascript\u002F04.react\u002F05.react-router\u002F03.nested-routes-and-layouts",{"title":2118,"path":2119,"stem":2120},"Динамічні Маршрути та Параметри","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdynamic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F04.dynamic-routing",{"title":2122,"path":2123,"stem":2124},"Data APIs: Loaders та Actions","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdata-loading","03.javascript\u002F04.react\u002F05.react-router\u002F05.data-loading",{"title":2126,"path":2127,"stem":2128},"Просунуті Патерни","\u002Fjavascript\u002Freact\u002Freact-router\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F05.react-router\u002F06.advanced-patterns",{"title":2130,"path":2131,"stem":2132},"Legacy Routing: Компонентний підхід","\u002Fjavascript\u002Freact\u002Freact-router\u002Flegacy-routing","03.javascript\u002F04.react\u002F05.react-router\u002F07.legacy-routing",{"title":2134,"icon":132,"path":2135,"stem":2136,"children":2137},"Redux","\u002Fjavascript\u002Freact\u002Fredux","03.javascript\u002F04.react\u002F06.redux\u002Findex",[2138,2140,2156,2185,2194,2215,2231,2260],{"title":2139,"path":2135,"stem":2136},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2141,"stem":2142,"children":2143,"page":59},"\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals",[2144,2148,2152],{"title":2145,"path":2146,"stem":2147},"Вступ до State Management","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fintro-state-management","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F01.intro-state-management",{"title":2149,"path":2150,"stem":2151},"Філософія Redux та Три Принципи","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fredux-philosophy","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F02.redux-philosophy",{"title":2153,"path":2154,"stem":2155},"Чисті функції та Іммутабельність","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fpure-functions-immutability","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F03.pure-functions-immutability",{"title":2157,"icon":132,"path":2158,"stem":2159,"children":2160,"page":59},"Classic Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux",[2161,2165,2169,2173,2177,2181],{"title":2162,"path":2163,"stem":2164},"Створення Store (Classic Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fstore-setup","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F01.store-setup",{"title":2166,"path":2167,"stem":2168},"Actions, Constants та Action Creators","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Factions-constants","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F02.actions-constants",{"title":2170,"path":2171,"stem":2172},"Логіка Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freducers","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F03.reducers",{"title":2174,"path":2175,"stem":2176},"Комбінування Reducers (Root Reducer)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fdata-flow","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F04.data-flow",{"title":2178,"path":2179,"stem":2180},"Підключення до React (React-Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freact-redux-connection","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F05.react-redux-connection",{"title":2182,"path":2183,"stem":2184},"Middleware та Асинхронність (Redux Thunk)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fmiddleware-thunk","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F06.middleware-thunk",{"title":2186,"icon":132,"path":2187,"stem":2188,"children":2189,"page":59},"Transition To Rtk","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk",[2190],{"title":2191,"path":2192,"stem":2193},"Проблеми класичного Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk\u002Fproblems-with-classic","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk\u002F01.problems-with-classic",{"title":2195,"icon":132,"path":2196,"stem":2197,"children":2198,"page":59},"Redux Toolkit","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit",[2199,2203,2207,2211],{"title":2200,"path":2201,"stem":2202},"Налаштування Store з configureStore","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fconfigure-store","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F01.configure-store",{"title":2204,"path":2205,"stem":2206},"createSlice: Революція в Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fcreate-slice","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F02.create-slice",{"title":2208,"path":2209,"stem":2210},"Асинхронність з createAsyncThunk","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fasync-thunks","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F03.async-thunks",{"title":2212,"path":2213,"stem":2214},"04. Entity Adapter: Керування нормалізованим станом","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fentity-adapter","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F04.entity-adapter",{"title":2216,"icon":92,"path":2217,"stem":2218,"children":2219,"page":59},"Advanced","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced",[2220,2224,2228],{"title":2221,"path":2222,"stem":2223},"Мемоізація та Селектори: Повний Гайд по Reselect","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Fselectors-reselect","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F01.selectors-reselect",{"title":2225,"path":2226,"stem":2227},"RTK Query: Архітектура Серверного Кешу","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Frtk-query-intro","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F02.rtk-query-intro",{"title":2075,"path":2229,"stem":2230},"\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Farchitecture-best-practices","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F03.architecture-best-practices",{"title":2232,"icon":132,"path":2233,"stem":2234,"children":2235,"page":59},"Project Kanban","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban",[2236,2240,2244,2248,2252,2256],{"title":2237,"path":2238,"stem":2239},"Проєкт: Kanban Board (Trello Clone)","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fproject-overview","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F01.project-overview",{"title":2241,"path":2242,"stem":2243},"Налаштування та Типізація","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fsetup-and-types","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F02.setup-and-types",{"title":2245,"path":2246,"stem":2247},"Board Slice: Серце Дошки","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fboard-slice","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F03.board-slice",{"title":2249,"path":2250,"stem":2251},"Логіка Drag & Drop","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fdrag-and-drop-logic","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F04.drag-and-drop-logic",{"title":2253,"path":2254,"stem":2255},"Інтеграція з RTK Query","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Frtk-query-integration","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F05.rtk-query-integration",{"title":2257,"path":2258,"stem":2259},"Optimistic Updates","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Foptimistic-updates","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F06.optimistic-updates",{"title":2261,"icon":132,"path":2262,"stem":2263,"children":2264,"page":59},"Testing","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting","03.javascript\u002F04.react\u002F06.redux\u002F07.testing",[2265,2269,2273,2277,2281],{"title":2266,"path":2267,"stem":2268},"Тестування Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Fintro-testing","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F01.intro-testing",{"title":2270,"path":2271,"stem":2272},"Тестування Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-reducers","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F02.testing-reducers",{"title":2274,"path":2275,"stem":2276},"Тестування Селекторів","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-selectors","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F03.testing-selectors",{"title":2278,"path":2279,"stem":2280},"Тестування Компонентів (Integration)","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-components","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F04.testing-components",{"title":2282,"path":2283,"stem":2284},"Тестування Async Thunks","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-thunks","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F05.testing-thunks",{"title":2286,"icon":132,"path":2287,"stem":2288,"children":2289},"Ui Libraries","\u002Fjavascript\u002Freact\u002Fui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002Findex",[2290,2292,2296,2300,2304,2308,2312],{"title":2291,"path":2287,"stem":2288},"UI Бібліотеки в React",{"title":2293,"path":2294,"stem":2295},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fintroduction-to-ui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002F01.introduction-to-ui-libraries",{"title":2297,"path":2298,"stem":2299},"Філософія shadcn\u002Fui: \"Not a Component Library\"","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-philosophy","03.javascript\u002F04.react\u002F07.ui-libraries\u002F02.shadcn-philosophy",{"title":2301,"path":2302,"stem":2303},"Установка та Налаштування shadcn\u002Fui","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-installation","03.javascript\u002F04.react\u002F07.ui-libraries\u002F03.shadcn-installation",{"title":2305,"path":2306,"stem":2307},"Базові Компоненти shadcn\u002Fui: Фундамент Інтерфейсу","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-basics","03.javascript\u002F04.react\u002F07.ui-libraries\u002F04.shadcn-components-basics",{"title":2309,"path":2310,"stem":2311},"Компоненти Форм: Побудова Інтерактивних Form","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-forms","03.javascript\u002F04.react\u002F07.ui-libraries\u002F05.shadcn-components-forms",{"title":2313,"path":2314,"stem":2315},"Складні Компоненти: Dialog, Dropdown, Table та Command","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-advanced","03.javascript\u002F04.react\u002F07.ui-libraries\u002F06.shadcn-components-advanced",{"title":2317,"icon":2318,"path":2319,"stem":2320,"children":2321,"page":59},"TypeScript","i-devicon-typescript","\u002Fjavascript\u002Ftypescript","03.javascript\u002F05.typescript",[2322,2326,2330,2334,2338,2342,2346,2350],{"title":2323,"path":2324,"stem":2325},"TypeScript: Броня для вашого коду","\u002Fjavascript\u002Ftypescript\u002Fintro-and-basic-types","03.javascript\u002F05.typescript\u002F01.intro-and-basic-types",{"title":2327,"path":2328,"stem":2329},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","\u002Fjavascript\u002Ftypescript\u002Finterfaces-and-advanced-types","03.javascript\u002F05.typescript\u002F02.interfaces-and-advanced-types",{"title":2331,"path":2332,"stem":2333},"Алхімія Типів: Generics та Utility Types","\u002Fjavascript\u002Ftypescript\u002Fgenerics-and-utilities","03.javascript\u002F05.typescript\u002F03.generics-and-utilities",{"title":2335,"path":2336,"stem":2337},"Архітектура та Шаблони: Класи в TypeScript","\u002Fjavascript\u002Ftypescript\u002Fclasses-and-oop","03.javascript\u002F05.typescript\u002F04.classes-and-oop",{"title":2339,"path":2340,"stem":2341},"Продакшн та Екосистема: Advanced Config & Workflow","\u002Fjavascript\u002Ftypescript\u002Fadvanced-patterns-and-config","03.javascript\u002F05.typescript\u002F05.advanced-patterns-and-config",{"title":2343,"path":2344,"stem":2345},"TypeScript у світі React","\u002Fjavascript\u002Ftypescript\u002Freact-basics","03.javascript\u002F05.typescript\u002F06.react-basics",{"title":2347,"path":2348,"stem":2349},"React + TypeScript: Продвинуті патерни","\u002Fjavascript\u002Ftypescript\u002Freact-advanced","03.javascript\u002F05.typescript\u002F07.react-advanced",{"title":2351,"path":2352,"stem":2353},"React + TypeScript: Екосистема та бібліотеки","\u002Fjavascript\u002Ftypescript\u002Freact-ecosystem","03.javascript\u002F05.typescript\u002F08.react-ecosystem",{"title":2355,"path":2356,"stem":2357},"Atomic Design","\u002Fjavascript\u002Fatomic-design","03.javascript\u002F2.atomic-design",{"title":2359,"icon":2360,"path":2361,"stem":2362,"children":2363,"page":59},"Java","i-devicon-java","\u002Fjava","04.java",[2364,2367,2370,2374,2378,2382,2386],{"title":162,"path":2365,"stem":2366},"\u002Fjava\u002Fdata-mapper-part1","04.java\u002F01.data-mapper-part1",{"title":166,"path":2368,"stem":2369},"\u002Fjava\u002Fdata-mapper-part2","04.java\u002F02.data-mapper-part2",{"title":2371,"path":2372,"stem":2373},"Service Layer: Організація бізнес-логіки","\u002Fjava\u002Fservice-layer","04.java\u002F03.service-layer",{"title":2375,"path":2376,"stem":2377},"Rich Domain Model та State Pattern","\u002Fjava\u002Frich-domain-model","04.java\u002F04.rich-domain-model",{"title":2379,"path":2380,"stem":2381},"Патерни для складної бізнес-логіки","\u002Fjava\u002Fbusiness-logic-patterns","04.java\u002F05.business-logic-patterns",{"title":2383,"path":2384,"stem":2385},"Обробка помилок та валідація","\u002Fjava\u002Ferror-handling-validation","04.java\u002F06.error-handling-validation",{"title":2387,"path":2388,"stem":2389,"children":2390,"page":59},"Проектування баз даних","\u002Fjava\u002Fpr2","04.java\u002Fpr2",[2391,2395,2399,2403,2407,2411,2415,2419,2423,2427,2431,2435,2439,2443,2447,2451,2455,2459,2463,2467,2471,2475,2479,2483,2487,2491,2495,2499,2503,2507,2511,2515,2519,2523,2527,2531,2535],{"title":2392,"path":2393,"stem":2394},"Концептуальне моделювання: Мистецтво розуміння предметної області","\u002Fjava\u002Fpr2\u002Fconceptual-modeling","04.java\u002Fpr2\u002F01.conceptual-modeling",{"title":2396,"path":2397,"stem":2398},"Логічне моделювання: Від бізнес-ідей до структур даних","\u002Fjava\u002Fpr2\u002Flogical-modeling","04.java\u002Fpr2\u002F02.logical-modeling",{"title":2400,"path":2401,"stem":2402},"Нормалізація: Гігієна даних та боротьба з аномаліями","\u002Fjava\u002Fpr2\u002Fnormalization","04.java\u002Fpr2\u002F03.normalization",{"title":2404,"path":2405,"stem":2406},"Фізична схема: Від абстракції до DDL","\u002Fjava\u002Fpr2\u002Fphysical-schema","04.java\u002Fpr2\u002F04.physical-schema",{"title":2408,"path":2409,"stem":2410},"Архітектурна класифікація таблиць","\u002Fjava\u002Fpr2\u002Ftable-classification","04.java\u002Fpr2\u002F05.table-classification",{"title":2412,"path":2413,"stem":2414},"Database Migrations: Версіонування схеми з Flyway","\u002Fjava\u002Fpr2\u002Fdatabase-migrations","04.java\u002Fpr2\u002F06.database-migrations",{"title":2416,"path":2417,"stem":2418},"А що, якби це була не реляційна БД?","\u002Fjava\u002Fpr2\u002Fbeyond-relational","04.java\u002Fpr2\u002F07.beyond-relational",{"title":2420,"path":2421,"stem":2422},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","\u002Fjava\u002Fpr2\u002Fimpedance-mismatch","04.java\u002Fpr2\u002F09.impedance-mismatch",{"title":2424,"path":2425,"stem":2426},"JDBC: Перший контакт із базою даних","\u002Fjava\u002Fpr2\u002Fjdbc-fundamentals","04.java\u002Fpr2\u002F10.jdbc-fundamentals",{"title":2428,"path":2429,"stem":2430},"Якість коду: Spotless, SpotBugs та SonarQube","\u002Fjava\u002Fpr2\u002F10a.code-quality","04.java\u002Fpr2\u002F10a.code-quality",{"title":2432,"path":2433,"stem":2434},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","\u002Fjava\u002Fpr2\u002Fconnection-pool","04.java\u002Fpr2\u002F11.connection-pool",{"title":2436,"path":2437,"stem":2438},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","\u002Fjava\u002Fpr2\u002Frow-data-gateway","04.java\u002Fpr2\u002F12.row-data-gateway",{"title":2440,"path":2441,"stem":2442},"Table Data Gateway: Фасад таблиці як архітектурний відступ","\u002Fjava\u002Fpr2\u002Ftable-data-gateway","04.java\u002Fpr2\u002F13.table-data-gateway",{"title":2444,"path":2445,"stem":2446},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","\u002Fjava\u002Fpr2\u002Frepository-data-mapper","04.java\u002Fpr2\u002F14.repository-data-mapper",{"title":2448,"path":2449,"stem":2450},"Identity Map: Кешування сутностей у рамках сесії","\u002Fjava\u002Fpr2\u002Fidentity-map","04.java\u002Fpr2\u002F15.identity-map",{"title":2452,"path":2453,"stem":2454},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","\u002Fjava\u002Fpr2\u002Funit-of-work","04.java\u002Fpr2\u002F16.unit-of-work",{"title":2456,"path":2457,"stem":2458},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","\u002Fjava\u002Fpr2\u002Fstrategy-sql","04.java\u002Fpr2\u002F17.strategy-sql",{"title":2460,"path":2461,"stem":2462},"Proxy: Lazy Loading для One-To-Many колекцій","\u002Fjava\u002Fpr2\u002Fproxy-lazy-loading","04.java\u002Fpr2\u002F18.proxy-lazy-loading",{"title":2464,"path":2465,"stem":2466},"Generic Repository через Java Reflection: анотації та динамічний SQL","\u002Fjava\u002Fpr2\u002Fgeneric-repository-reflection","04.java\u002Fpr2\u002F19.generic-repository-reflection",{"title":2468,"path":2469,"stem":2470},"Specification Pattern: Композиція бізнес-правил для складних запитів","\u002Fjava\u002Fpr2\u002Fspecification-pattern","04.java\u002Fpr2\u002F20.specification-pattern",{"title":2472,"path":2473,"stem":2474},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","\u002Fjava\u002Fpr2\u002F20a.advanced-specifications","04.java\u002Fpr2\u002F20a.advanced-specifications",{"title":2476,"path":2477,"stem":2478},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","\u002Fjava\u002Fpr2\u002Fasynchronous-jdbc","04.java\u002Fpr2\u002F21.asynchronous-jdbc",{"title":2480,"path":2481,"stem":2482},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","\u002Fjava\u002Fpr2\u002Fintegration-testing-h2","04.java\u002Fpr2\u002F22.integration-testing-h2",{"title":2484,"path":2485,"stem":2486},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","\u002Fjava\u002Fpr2\u002Fintegration-testing-testcontainers","04.java\u002Fpr2\u002F23.integration-testing-testcontainers",{"title":2488,"path":2489,"stem":2490},"Google Guice: Впровадження залежностей у JavaFX-проєкті","\u002Fjava\u002Fpr2\u002Fdependency-injection-guice","04.java\u002Fpr2\u002F24.dependency-injection-guice",{"title":2492,"path":2493,"stem":2494},"JavaFX: Основи побудови графічних інтерфейсів","\u002Fjava\u002Fpr2\u002Fjavafx-fundamentals","04.java\u002Fpr2\u002F25.javafx-fundamentals",{"title":2496,"path":2497,"stem":2498},"Properties та Bindings: Реактивність у JavaFX","\u002Fjava\u002Fpr2\u002Fjavafx-properties-bindings","04.java\u002Fpr2\u002F26.javafx-properties-bindings",{"title":2500,"path":2501,"stem":2502},"MVC vs MVP vs MVVM: Еволюція архітектурних патернів UI","\u002Fjava\u002Fpr2\u002Fui-architecture-patterns","04.java\u002Fpr2\u002F27.ui-architecture-patterns",{"title":2504,"path":2505,"stem":2506},"MVVM на практиці: Побудова ViewModel","\u002Fjava\u002Fpr2\u002Fmvvm-viewmodel-implementation","04.java\u002Fpr2\u002F28.mvvm-viewmodel-implementation",{"title":2508,"path":2509,"stem":2510},"View та Controller: Зв'язування з ViewModel через FXML","\u002Fjava\u002Fpr2\u002Fmvvm-view-controller","04.java\u002Fpr2\u002F29.mvvm-view-controller",{"title":2512,"path":2513,"stem":2514},"Інтеграція MVVM з Guice: Автоматична ін'єкція залежностей","\u002Fjava\u002Fpr2\u002Fmvvm-guice-integration","04.java\u002Fpr2\u002F30.mvvm-guice-integration",{"title":2516,"path":2517,"stem":2518},"Валідація та обробка помилок у MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-validation-error-handling","04.java\u002Fpr2\u002F31.mvvm-validation-error-handling",{"title":2520,"path":2521,"stem":2522},"Навігація та управління екранами у JavaFX MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-navigation-screen-management","04.java\u002Fpr2\u002F32.mvvm-navigation-screen-management",{"title":2524,"path":2525,"stem":2526},"Тестування JavaFX MVVM-додатків","\u002Fjava\u002Fpr2\u002Fmvvm-testing","04.java\u002Fpr2\u002F33.mvvm-testing",{"title":2528,"path":2529,"stem":2530},"Стилізація та теми у JavaFX: CSS та User Experience","\u002Fjava\u002Fpr2\u002Fjavafx-styling-themes","04.java\u002Fpr2\u002F34.javafx-styling-themes",{"title":2532,"path":2533,"stem":2534},"AtlantaFX: Сучасні теми для JavaFX додатків","\u002Fjava\u002Fpr2\u002Fatlantafx-modern-themes","04.java\u002Fpr2\u002F35.atlantafx-modern-themes",{"title":2536,"path":2537,"stem":2538},"Пакування та розповсюдження JavaFX-додатків","\u002Fjava\u002Fpr2\u002Fjar-packaging-distribution","04.java\u002Fpr2\u002F36.jar-packaging-distribution",{"title":2540,"icon":2541,"path":2542,"stem":2543,"children":2544,"page":59},"Python","i-devicon-python","\u002Fpython","05.python",[2545,2549,2552,2556,2560,2564,2568,2572,2576,2580,2584,2588,2592,2596,2600,2604],{"title":2546,"path":2547,"stem":2548},"Модулі, Пакети та Віртуальні Середовища","\u002Fpython\u002Fmodules-packages-venv","05.python\u002F00.modules-packages-venv",{"title":71,"path":2550,"stem":2551},"\u002Fpython\u002Fclasses-objects","05.python\u002F01.classes-objects",{"title":2553,"path":2554,"stem":2555},"Інкапсуляція, Керування Доступом та Властивості","\u002Fpython\u002Fencapsulation","05.python\u002F02.encapsulation",{"title":2557,"path":2558,"stem":2559},"Наслідування, MRO та суперсила super()","\u002Fpython\u002Finheritance-mro","05.python\u002F03.inheritance-mro",{"title":2561,"path":2562,"stem":2563},"Абстракція — ABC проти Статичних Протоколів (PEP 544)","\u002Fpython\u002Fabstraction-protocols","05.python\u002F04.abstraction-protocols",{"title":2565,"path":2566,"stem":2567},"Магічні методи (Dunder) та Емуляція протоколів","\u002Fpython\u002Fdunder-methods","05.python\u002F05.dunder-methods",{"title":2569,"path":2570,"stem":2571},"Декоратори та Керування життєвим циклом методів","\u002Fpython\u002Fdecorators-static-class","05.python\u002F06.decorators-static-class",{"title":2573,"path":2574,"stem":2575},"Дескриптори — Магія доступу до атрибутів","\u002Fpython\u002Fdescriptors","05.python\u002F07.descriptors",{"title":2577,"path":2578,"stem":2579},"Метакласи — Динамічне створення класів під капотом CPython","\u002Fpython\u002Fmetaclasses","05.python\u002F08.metaclasses",{"title":2581,"path":2582,"stem":2583},"Dataclasses, NamedTuple та сучасні контейнери Python","\u002Fpython\u002Fmodern-containers","05.python\u002F09.modern-containers",{"title":2585,"path":2586,"stem":2587},"GIL та модель конкурентності CPython — фундамент перед потоками і процесами","\u002Fpython\u002Fgil-concurrency-intro","05.python\u002F11.gil-concurrency-intro",{"title":2589,"path":2590,"stem":2591},"Threading — конкурентність для I\u002FO-bound задач","\u002Fpython\u002Fthreading","05.python\u002F12.threading",{"title":2593,"path":2594,"stem":2595},"Multiprocessing — справжній паралелізм для CPU-bound задач","\u002Fpython\u002Fmultiprocessing","05.python\u002F13.multiprocessing",{"title":2597,"path":2598,"stem":2599},"asyncio — кооперативна конкурентність та event loop","\u002Fpython\u002Fasyncio","05.python\u002F14.asyncio",{"title":2601,"path":2602,"stem":2603},"📦 Повний посібник з модулів, пакетів та віртуальних середовищ у Python","\u002Fpython\u002Flesson_9","05.python\u002Flesson_9",{"title":2605,"path":2606,"stem":2607},"[object Object]","\u002Fpython\u002Foop-plan","05.python\u002Foop-plan",{"title":2609,"icon":2610,"path":2611,"stem":2612,"children":2613,"page":59},"Бази даних","i-lucide-database","\u002Fdatabases","06.databases",[2614,2644,2667,2704,2733,2751,2785,2797,2806],{"title":2615,"icon":2616,"path":2617,"stem":2618,"children":2619,"page":59},"Intro","i-lucide-play","\u002Fdatabases\u002Fintro","06.databases\u002F01.intro",[2620,2624,2628,2632,2636,2640],{"title":2621,"path":2622,"stem":2623},"Введення в теорію баз даних","\u002Fdatabases\u002Fintro\u002Fintroduction-to-databases","06.databases\u002F01.intro\u002F01.introduction-to-databases",{"title":2625,"path":2626,"stem":2627},"Реляційна модель даних","\u002Fdatabases\u002Fintro\u002Frelational-model-theory","06.databases\u002F01.intro\u002F02.relational-model-theory",{"title":2629,"path":2630,"stem":2631},"ER-моделювання","\u002Fdatabases\u002Fintro\u002Fer-modeling","06.databases\u002F01.intro\u002F03.er-modeling",{"title":2633,"path":2634,"stem":2635},"Логічне проектування БД","\u002Fdatabases\u002Fintro\u002Flogical-schema","06.databases\u002F01.intro\u002F04.logical-schema",{"title":2637,"path":2638,"stem":2639},"Класифікація таблиць","\u002Fdatabases\u002Fintro\u002Ftable-classification","06.databases\u002F01.intro\u002F05.table-classification",{"title":2641,"path":2642,"stem":2643},"PlantUML для баз даних","\u002Fdatabases\u002Fintro\u002Fplantuml-diagrams","06.databases\u002F01.intro\u002F06.plantuml-diagrams",{"title":2645,"icon":2610,"path":2646,"stem":2647,"children":2648,"page":59},"MS SQL Server Start","\u002Fdatabases\u002Fms-sql-server-start","06.databases\u002F02.ms-sql-server-start",[2649,2653,2659,2663],{"title":2650,"path":2651,"stem":2652},"Типи даних у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fdata-types","06.databases\u002F02.ms-sql-server-start\u002F01.data-types",{"title":2654,"path":2655,"stem":2656,"children":2657},"Індекси у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-indexes","06.databases\u002F02.ms-sql-server-start\u002F02.sql-indexes",[2658],{"title":2654,"path":2655,"stem":2656},{"title":2660,"path":2661,"stem":2662},"Системні бази даних MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsystem-databases","06.databases\u002F02.ms-sql-server-start\u002F03.system-databases",{"title":2664,"path":2665,"stem":2666},"Огляд мови SQL та запитів","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-queries-overview","06.databases\u002F02.ms-sql-server-start\u002F04.sql-queries-overview",{"title":2668,"icon":2610,"path":2669,"stem":2670,"children":2671,"page":59},"SQL","\u002Fdatabases\u002Fsql","06.databases\u002F03.sql",[2672,2676,2680,2684,2688,2692,2696,2700],{"title":2673,"path":2674,"stem":2675},"Налаштування демонстраційної бази даних","\u002Fdatabases\u002Fsql\u002Fsample-database-setup","06.databases\u002F03.sql\u002F00.sample-database-setup",{"title":2677,"path":2678,"stem":2679},"DDL - Створення таблиць (CREATE TABLE)","\u002Fdatabases\u002Fsql\u002Fddl-create-table","06.databases\u002F03.sql\u002F01.ddl-create-table",{"title":2681,"path":2682,"stem":2683},"DDL - Зміна та видалення таблиць (ALTER, DROP)","\u002Fdatabases\u002Fsql\u002Fddl-alter-drop-table","06.databases\u002F03.sql\u002F02.ddl-alter-drop-table",{"title":2685,"path":2686,"stem":2687},"SELECT запити - Основи","\u002Fdatabases\u002Fsql\u002Fselect-queries-fundamentals","06.databases\u002F03.sql\u002F03.select-queries-fundamentals",{"title":2689,"path":2690,"stem":2691},"SELECT запити - Розширені можливості","\u002Fdatabases\u002Fsql\u002Fselect-queries-advanced","06.databases\u002F03.sql\u002F04.select-queries-advanced",{"title":2693,"path":2694,"stem":2695},"INSERT запити - Додавання даних","\u002Fdatabases\u002Fsql\u002Finsert-queries","06.databases\u002F03.sql\u002F05.insert-queries",{"title":2697,"path":2698,"stem":2699},"UPDATE та DELETE запити","\u002Fdatabases\u002Fsql\u002Fupdate-delete-queries","06.databases\u002F03.sql\u002F06.update-delete-queries",{"title":2701,"path":2702,"stem":2703},"Транзакції в SQL","\u002Fdatabases\u002Fsql\u002Ftransactions","06.databases\u002F03.sql\u002F07.transactions",{"title":2705,"icon":2610,"path":2706,"stem":2707,"children":2708,"page":59},"Multi Table Databases","\u002Fdatabases\u002Fmulti-table-databases","06.databases\u002F04.multi-table-databases",[2709,2713,2717,2721,2725,2729],{"title":2710,"path":2711,"stem":2712},"Зв'язки та нормалізація БД","\u002Fdatabases\u002Fmulti-table-databases\u002Frelationships-and-normalization","06.databases\u002F04.multi-table-databases\u002F00.relationships-and-normalization",{"title":2714,"path":2715,"stem":2716},"INNER JOIN - З'єднання таблиць","\u002Fdatabases\u002Fmulti-table-databases\u002Finner-join","06.databases\u002F04.multi-table-databases\u002F01.inner-join",{"title":2718,"path":2719,"stem":2720},"OUTER JOINs - LEFT, RIGHT, FULL","\u002Fdatabases\u002Fmulti-table-databases\u002Fouter-joins","06.databases\u002F04.multi-table-databases\u002F02.outer-joins",{"title":2722,"path":2723,"stem":2724},"CROSS та SELF JOINs","\u002Fdatabases\u002Fmulti-table-databases\u002Fcross-self-joins","06.databases\u002F04.multi-table-databases\u002F03.cross-self-joins",{"title":2726,"path":2727,"stem":2728},"Підзапити (Subqueries)","\u002Fdatabases\u002Fmulti-table-databases\u002Fsubqueries","06.databases\u002F04.multi-table-databases\u002F04.subqueries",{"title":2730,"path":2731,"stem":2732},"Агрегації з JOIN","\u002Fdatabases\u002Fmulti-table-databases\u002Faggregations-with-joins","06.databases\u002F04.multi-table-databases\u002F05.aggregations-with-joins",{"title":2734,"icon":2735,"path":2736,"stem":2737,"children":2738,"page":59},"Aggregate Functions","i-lucide-calculator","\u002Fdatabases\u002Faggregate-functions","06.databases\u002F05.aggregate-functions",[2739,2743,2747],{"title":2740,"path":2741,"stem":2742},"Функції агрегування в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fintroduction-aggregate-functions","06.databases\u002F05.aggregate-functions\u002F01.introduction-aggregate-functions",{"title":2744,"path":2745,"stem":2746},"Групування даних в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fgrouping-data","06.databases\u002F05.aggregate-functions\u002F02.grouping-data",{"title":2748,"path":2749,"stem":2750},"Підзапити з агрегатними функціями","\u002Fdatabases\u002Faggregate-functions\u002Fsubqueries-aggregates","06.databases\u002F05.aggregate-functions\u002F03.subqueries-aggregates",{"title":2752,"icon":2753,"path":2754,"stem":2755,"children":2756,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","\u002Fdatabases\u002Ftriggers-stored-procedures","06.databases\u002F07.triggers-stored-procedures",[2757,2761,2765,2769,2773,2777,2781],{"title":2758,"path":2759,"stem":2760},"DML-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fdml-triggers","06.databases\u002F07.triggers-stored-procedures\u002F01.dml-triggers",{"title":2762,"path":2763,"stem":2764},"DDL-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fddl-triggers","06.databases\u002F07.triggers-stored-procedures\u002F02.ddl-triggers",{"title":2766,"path":2767,"stem":2768},"Transact-SQL розширення","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransact-sql-extensions","06.databases\u002F07.triggers-stored-procedures\u002F03.transact-sql-extensions",{"title":2770,"path":2771,"stem":2772},"Транзакції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransactions","06.databases\u002F07.triggers-stored-procedures\u002F04.transactions",{"title":2774,"path":2775,"stem":2776},"Зберігаємі процедури","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fstored-procedures","06.databases\u002F07.triggers-stored-procedures\u002F05.stored-procedures",{"title":2778,"path":2779,"stem":2780},"Користувацькі функції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fuser-defined-functions","06.databases\u002F07.triggers-stored-procedures\u002F06.user-defined-functions",{"title":2782,"path":2783,"stem":2784},"Безпека баз даних","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fsecurity","06.databases\u002F07.triggers-stored-procedures\u002F08.security",{"title":2782,"icon":793,"path":2786,"stem":2787,"children":2788,"page":59},"\u002Fdatabases\u002Fsecurity","06.databases\u002F08.security",[2789,2793],{"title":2790,"path":2791,"stem":2792},"Вступ до безпеки баз даних","\u002Fdatabases\u002Fsecurity\u002Fintroduction","06.databases\u002F08.security\u002F01.introduction",{"title":2794,"path":2795,"stem":2796},"Системні представлення та метадані","\u002Fdatabases\u002Fsecurity\u002Fsystem-views","06.databases\u002F08.security\u002F02.system-views",{"title":2798,"icon":2799,"path":2800,"stem":2801,"children":2802,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","\u002Fdatabases\u002Fbackup-recovery","06.databases\u002F09.backup-recovery",[2803],{"title":2798,"path":2804,"stem":2805},"\u002Fdatabases\u002Fbackup-recovery\u002Fbackup-restore","06.databases\u002F09.backup-recovery\u002F01.backup-restore",{"title":2807,"icon":2808,"path":2809,"stem":2810,"children":2811,"page":59},"Повнотекстовий пошук","i-lucide-search","\u002Fdatabases\u002Ffull-text-search","06.databases\u002F10.full-text-search",[2812],{"title":2807,"path":2813,"stem":2814},"\u002Fdatabases\u002Ffull-text-search\u002Ffull-text-search","06.databases\u002F10.full-text-search\u002F01.full-text-search",{"title":2816,"icon":2817,"path":2818,"stem":2819,"children":2820,"page":59},"Tools","i-lucide-wrench","\u002Ftools","07.tools",[2821,2897],{"title":2822,"icon":2823,"path":2824,"stem":2825,"children":2826},"Docker","i-simple-icons-docker","\u002Ftools\u002Fdocker","07.tools\u002F01.docker\u002Findex",[2827,2829,2833,2837,2841,2845,2849,2853,2857,2861,2865,2869,2873,2877,2881,2885,2889,2893],{"title":2828,"path":2824,"stem":2825},"Docker: від нуля до production",{"title":2830,"path":2831,"stem":2832},"Контейнеризація — від проблеми до рішення","\u002Ftools\u002Fdocker\u002Fcontainerization-concept","07.tools\u002F01.docker\u002F01.containerization-concept",{"title":2834,"path":2835,"stem":2836},"Docker — що це і навіщо?","\u002Ftools\u002Fdocker\u002Fdocker-what-and-why","07.tools\u002F01.docker\u002F02.docker-what-and-why",{"title":2838,"path":2839,"stem":2840},"Архітектура Docker Engine","\u002Ftools\u002Fdocker\u002Fdocker-architecture","07.tools\u002F01.docker\u002F03.docker-architecture",{"title":2842,"path":2843,"stem":2844},"Встановлення Docker","\u002Ftools\u002Fdocker\u002Finstallation","07.tools\u002F01.docker\u002F04.installation",{"title":2846,"path":2847,"stem":2848},"Перший контейнер — docker run","\u002Ftools\u002Fdocker\u002Ffirst-container","07.tools\u002F01.docker\u002F05.first-container",{"title":2850,"path":2851,"stem":2852},"Життєвий цикл контейнера","\u002Ftools\u002Fdocker\u002Fcontainer-lifecycle","07.tools\u002F01.docker\u002F06.container-lifecycle",{"title":2854,"path":2855,"stem":2856},"Docker Images — фундаментальні концепції","\u002Ftools\u002Fdocker\u002Fdocker-images-fundamentals","07.tools\u002F01.docker\u002F07.docker-images-fundamentals",{"title":2858,"path":2859,"stem":2860},"Dockerfile — основи","\u002Ftools\u002Fdocker\u002Fdockerfile-basics","07.tools\u002F01.docker\u002F08.dockerfile-basics",{"title":2862,"path":2863,"stem":2864},"Dockerfile — просунуті техніки","\u002Ftools\u002Fdocker\u002Fdockerfile-advanced","07.tools\u002F01.docker\u002F09.dockerfile-advanced",{"title":2866,"path":2867,"stem":2868},"Build Context та кешування шарів","\u002Ftools\u002Fdocker\u002Fbuild-context-and-cache","07.tools\u002F01.docker\u002F10.build-context-and-cache",{"title":2870,"path":2871,"stem":2872},"Реєстри Docker-образів","\u002Ftools\u002Fdocker\u002Fimage-registries","07.tools\u002F01.docker\u002F11.image-registries",{"title":2874,"path":2875,"stem":2876},"Контейнеризація .NET додатків","\u002Ftools\u002Fdocker\u002Fdotnet-containerization","07.tools\u002F01.docker\u002F12.dotnet-containerization",{"title":2878,"path":2879,"stem":2880},"Томи та збереження даних","\u002Ftools\u002Fdocker\u002Fvolumes-and-data","07.tools\u002F01.docker\u002F13.volumes-and-data",{"title":2882,"path":2883,"stem":2884},"Основи мережі в Docker","\u002Ftools\u002Fdocker\u002Fnetworking-basics","07.tools\u002F01.docker\u002F14.networking-basics",{"title":2886,"path":2887,"stem":2888},"Змінні оточення та конфігурація","\u002Ftools\u002Fdocker\u002Fenvironment-and-configuration","07.tools\u002F01.docker\u002F15.environment-and-configuration",{"title":2890,"path":2891,"stem":2892},"Docker Compose — оркестрація контейнерів","\u002Ftools\u002Fdocker\u002Fdocker-compose-basics","07.tools\u002F01.docker\u002F16.docker-compose-basics",{"title":2894,"path":2895,"stem":2896},"Docker Compose — Multi-Service застосунки","\u002Ftools\u002Fdocker\u002Fcompose-multi-service","07.tools\u002F01.docker\u002F17.compose-multi-service",{"title":2898,"icon":2899,"path":2900,"stem":2901,"children":2902},"Kubernetes","simple-icons:kubernetes","\u002Ftools\u002Fkubernetes","07.tools\u002F02.kubernetes\u002Findex",[2903,2905,2909,2913,2917,2921,2925,2929,2933],{"title":2904,"path":2900,"stem":2901},"Kubernetes: від розробки до production",{"title":2906,"path":2907,"stem":2908},"Kubernetes — коли Docker Compose більше не вистачає","\u002Ftools\u002Fkubernetes\u002Fwhy-kubernetes","07.tools\u002F02.kubernetes\u002F01.why-kubernetes",{"title":2910,"path":2911,"stem":2912},"Архітектура Kubernetes — анатомія кластера","\u002Ftools\u002Fkubernetes\u002Fkubernetes-architecture","07.tools\u002F02.kubernetes\u002F02.kubernetes-architecture",{"title":2914,"path":2915,"stem":2916},"Локальне середовище — minikube, kind та k3s","\u002Ftools\u002Fkubernetes\u002Flocal-environment","07.tools\u002F02.kubernetes\u002F03.local-environment",{"title":2918,"path":2919,"stem":2920},"Pod — атомарна одиниця Kubernetes","\u002Ftools\u002Fkubernetes\u002Fpods-and-containers","07.tools\u002F02.kubernetes\u002F04.pods-and-containers",{"title":2922,"path":2923,"stem":2924},"Патерни використання Pod","\u002Ftools\u002Fkubernetes\u002Fpod-patterns","07.tools\u002F02.kubernetes\u002F05.pod-patterns",{"title":2926,"path":2927,"stem":2928},"Deployment — декларативне управління Pod","\u002Ftools\u002Fkubernetes\u002Fdeployment-basics","07.tools\u002F02.kubernetes\u002F06.deployment-basics",{"title":2930,"path":2931,"stem":2932},"Rolling Updates та управління життєвим циклом Deployment","\u002Ftools\u002Fkubernetes\u002Fdeployment-rolling-updates","07.tools\u002F02.kubernetes\u002F07.deployment-rolling-updates",{"title":2934,"path":2935,"stem":2936},"Service — мережева абстракція для Pod","\u002Ftools\u002Fkubernetes\u002Fservices-networking","07.tools\u002F02.kubernetes\u002F08.services-networking",{"title":2938,"icon":2939,"path":2940,"stem":2941,"children":2942,"page":59},"Software Engineering","i-lucide-code-2","\u002Fsoftware-engineering","09.software-engineering",[2943,2947,2951,2955,2959,2963,2967,2971,2975,2979,2983],{"title":2944,"path":2945,"stem":2946},"1. Аналіз предметної області. Експертні знання та складність","\u002Fsoftware-engineering\u002Fintro-subdomains","09.software-engineering\u002F01.intro-subdomains",{"title":2948,"path":2949,"stem":2950},"2. Обмежені контексти. Інтеграція обмежених контекстів","\u002Fsoftware-engineering\u002Fintegrating-limited-contexts","09.software-engineering\u002F02.integrating-limited-contexts",{"title":2952,"path":2953,"stem":2954},"3. Реалізація простої бізнес-логіки","\u002Fsoftware-engineering\u002Fsimple","09.software-engineering\u002F03.simple",{"title":2956,"path":2957,"stem":2958},"4. Опрацювання складної бізнес-логіки","\u002Fsoftware-engineering\u002Fcomplex-business-logic","09.software-engineering\u002F04.complex-business-logic",{"title":2960,"path":2961,"stem":2962},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","\u002Fsoftware-engineering\u002Fmodelling-the-time-factor","09.software-engineering\u002F05.modelling-the-time-factor",{"title":2964,"path":2965,"stem":2966},"6. Архітектурні патерни","\u002Fsoftware-engineering\u002Farchitectural-patterns","09.software-engineering\u002F06.architectural-patterns",{"title":2968,"path":2969,"stem":2970},"Паттерни взаємодії","\u002Fsoftware-engineering\u002Fpatterns-of-interaction","09.software-engineering\u002F07.patterns-of-interaction",{"title":2972,"path":2973,"stem":2974},"Евристика проєктування","\u002Fsoftware-engineering\u002Fdesign-heuristics","09.software-engineering\u002F08.design-heuristics",{"title":2976,"path":2977,"stem":2978},"Еволюція проєктних рішень","\u002Fsoftware-engineering\u002Fevolution-of-design-solutions","09.software-engineering\u002F09.evolution-of-design-solutions",{"title":2980,"path":2981,"stem":2982},"EventStorming","\u002Fsoftware-engineering\u002Feventstorming","09.software-engineering\u002F10.eventstorming",{"title":2984,"path":2985,"stem":2986},"DDD на практиці","\u002Fsoftware-engineering\u002Fddd-in-practice","09.software-engineering\u002F11.ddd-in-practice",{"title":2988,"icon":943,"path":2989,"stem":2990,"children":2991,"page":59},"DDD","\u002Fddd","10.ddd",[2992,2996,3000,3004,3008,3012,3016,3020,3024,3028,3032,3036,3040],{"title":2993,"path":2994,"stem":2995},"Аналіз предметної області","\u002Fddd\u002Fdomain-analysis","10.ddd\u002F01.domain-analysis",{"title":2997,"path":2998,"stem":2999},"Експертні знання про предметну область","\u002Fddd\u002Fdomain-expert-knowledge","10.ddd\u002F02.domain-expert-knowledge",{"title":3001,"path":3002,"stem":3003},"Як осмислити складність предметної області","\u002Fddd\u002Fmanaging-domain-complexity","10.ddd\u002F03.managing-domain-complexity",{"title":3005,"path":3006,"stem":3007},"Інтеграція обмежених контекстів","\u002Fddd\u002Fbounded-context-integration","10.ddd\u002F04.bounded-context-integration",{"title":3009,"path":3010,"stem":3011},"Реалізація простої бізнес-логіки","\u002Fddd\u002Fsimple-business-logic","10.ddd\u002F05.simple-business-logic",{"title":3013,"path":3014,"stem":3015},"Обробка складної бізнес-логіки","\u002Fddd\u002Fcomplex-business-logic","10.ddd\u002F06.complex-business-logic",{"title":3017,"path":3018,"stem":3019},"Моделювання фактора часу","\u002Fddd\u002Ftime-modeling","10.ddd\u002F07.time-modeling",{"title":3021,"path":3022,"stem":3023},"Глава 8. Архітектурні Патерни","\u002Fddd\u002Farchitectural-patterns","10.ddd\u002F08.architectural-patterns",{"title":3025,"path":3026,"stem":3027},"Глава 9. Патерни Взаємодії","\u002Fddd\u002Finteraction-patterns","10.ddd\u002F09.interaction-patterns",{"title":3029,"path":3030,"stem":3031},"Глава 10. Проектні Евристики","\u002Fddd\u002Fdesign-heuristics","10.ddd\u002F10.design-heuristics",{"title":3033,"path":3034,"stem":3035},"Глава 11. Еволюція Проектних Рішень","\u002Fddd\u002Fevolution-of-design-decisions","10.ddd\u002F11.evolution-of-design-decisions",{"title":3037,"path":3038,"stem":3039},"Глава 12. EventStorming","\u002Fddd\u002Fevent-storming","10.ddd\u002F12.event-storming",{"title":3041,"path":3042,"stem":3043},"Глава 13. DDD на Практиці","\u002Fddd\u002Fddd-in-practice","10.ddd\u002F13.ddd-in-practice",{"title":3045,"icon":3046,"path":3047,"stem":3048,"children":3049,"page":59},"Media Streaming","i-lucide-video","\u002Fmedia-streaming","11.media-streaming",[3050,3054,3058,3062,3066,3070,3074],{"title":3051,"path":3052,"stem":3053},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","\u002Fmedia-streaming\u002Fintroduction","11.media-streaming\u002F01.introduction",{"title":3055,"path":3056,"stem":3057},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","\u002Fmedia-streaming\u002Faudio-video-anatomy","11.media-streaming\u002F02.audio-video-anatomy",{"title":3059,"path":3060,"stem":3061},"03. The Gym: FFmpeg Deep Dive","\u002Fmedia-streaming\u002Fffmpeg-gym","11.media-streaming\u002F03.ffmpeg-gym",{"title":3063,"path":3064,"stem":3065},"04. HLS Protocol: HTTP Live Streaming у Деталях","\u002Fmedia-streaming\u002Fhls-protocol","11.media-streaming\u002F04.hls-protocol",{"title":3067,"path":3068,"stem":3069},"05. DASH Protocol: Відкритий Стандарт","\u002Fmedia-streaming\u002Fdash-protocol","11.media-streaming\u002F05.dash-protocol",{"title":3071,"path":3072,"stem":3073},"06. Масштабування: CDN та Adaptive Bitrate","\u002Fmedia-streaming\u002Fcdn-and-adaptive-bitrate","11.media-streaming\u002F06.cdn-and-adaptive-bitrate",{"title":3075,"path":3076,"stem":3077},"07. Війна із Затримкою (Latency)","\u002Fmedia-streaming\u002Frealtime-latency","11.media-streaming\u002F07.realtime-latency",{"title":3079,"icon":3080,"path":3081,"stem":3082,"children":3083,"page":59},"HTML & CSS","i-devicon-html5","\u002Fhtml-css","12.html-css",[3084,3088,3092,3096,3100,3104,3108,3112,3116,3120,3124,3128,3132,3136,3140,3144,3148,3152,3156,3160,3164,3168,3172,3176,3180,3184,3188,3192,3196,3200],{"title":3085,"path":3086,"stem":3087},"Вступ до HTML. Структура документа","\u002Fhtml-css\u002Fintro-html-structure","12.html-css\u002F01.intro-html-structure",{"title":3089,"path":3090,"stem":3091},"Форматування тексту в HTML","\u002Fhtml-css\u002Fhtml-text-formatting","12.html-css\u002F02.html-text-formatting",{"title":3093,"path":3094,"stem":3095},"Посилання та зображення в HTML","\u002Fhtml-css\u002Fhtml-links-images","12.html-css\u002F03.html-links-images",{"title":3097,"path":3098,"stem":3099},"Списки та таблиці в HTML","\u002Fhtml-css\u002Fhtml-lists-tables","12.html-css\u002F04.html-lists-tables",{"title":3101,"path":3102,"stem":3103},"Форми в HTML","\u002Fhtml-css\u002Fhtml-forms","12.html-css\u002F05.html-forms",{"title":3105,"path":3106,"stem":3107},"Семантичні елементи HTML5","\u002Fhtml-css\u002Fhtml-semantic-elements","12.html-css\u002F06.html-semantic-elements",{"title":3109,"path":3110,"stem":3111},"Мультимедіа та розширені елементи HTML","\u002Fhtml-css\u002Fhtml-multimedia-advanced","12.html-css\u002F07.html-multimedia-advanced",{"title":3113,"path":3114,"stem":3115},"Мікророзмітка та SEO в HTML","\u002Fhtml-css\u002Fhtml-microdata-seo","12.html-css\u002F08.html-microdata-seo",{"title":3117,"path":3118,"stem":3119},"Вступ до CSS. Селектори та специфічність","\u002Fhtml-css\u002Fcss-intro-selectors","12.html-css\u002F09.css-intro-selectors",{"title":3121,"path":3122,"stem":3123},"Блокова модель CSS. Відступи. Box Sizing","\u002Fhtml-css\u002Fcss-box-model","12.html-css\u002F10.css-box-model",{"title":3125,"path":3126,"stem":3127},"Розміри у CSS: повний довідник одиниць і ключових слів","\u002Fhtml-css\u002F10a.css-sizing","12.html-css\u002F10a.css-sizing",{"title":3129,"path":3130,"stem":3131},"Типографіка в CSS. Шрифти та текст","\u002Fhtml-css\u002Fcss-typography","12.html-css\u002F11.css-typography",{"title":3133,"path":3134,"stem":3135},"Кольори та фони в CSS","\u002Fhtml-css\u002Fcss-colors-backgrounds","12.html-css\u002F12.css-colors-backgrounds",{"title":3137,"path":3138,"stem":3139},"Тіні та фільтри в CSS","\u002Fhtml-css\u002F12b.css-shadows-filters","12.html-css\u002F12b.css-shadows-filters",{"title":3141,"path":3142,"stem":3143},"CSS Flexbox: Фундамент гнучких макетів","\u002Fhtml-css\u002Fcss-flexbox-fundamentals","12.html-css\u002F13.css-flexbox-fundamentals",{"title":3145,"path":3146,"stem":3147},"CSS Flexbox: Вирівнювання та Позиціонування","\u002Fhtml-css\u002Fcss-flexbox-alignment-sizing-and-patterns","12.html-css\u002F14.css-flexbox-alignment-sizing-and-patterns",{"title":3149,"path":3150,"stem":3151},"CSS Grid. Двовимірний макет. Частина 1","\u002Fhtml-css\u002Fcss-layout-grid","12.html-css\u002F15.css-layout-grid",{"title":3153,"path":3154,"stem":3155},"CSS Grid. Двовимірний макет. Частина 2","\u002Fhtml-css\u002Fcss-layout-grid-advanced","12.html-css\u002F16.css-layout-grid-advanced",{"title":3157,"path":3158,"stem":3159},"Позиціонування в CSS. Z-index. Stacking Context","\u002Fhtml-css\u002Fcss-positioning","12.html-css\u002F17.css-positioning",{"title":3161,"path":3162,"stem":3163},"CSS Анімації та Переходи","\u002Fhtml-css\u002Fcss-animations-transitions","12.html-css\u002F18.css-animations-transitions",{"title":3165,"path":3166,"stem":3167},"Адаптивний дизайн. Media Queries. Частина 1","\u002Fhtml-css\u002Fcss-responsive-media-queries","12.html-css\u002F19.css-responsive-media-queries",{"title":3169,"path":3170,"stem":3171},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","\u002Fhtml-css\u002Fcss-responsive-advanced","12.html-css\u002F20.css-responsive-advanced",{"title":3173,"path":3174,"stem":3175},"CSS Custom Properties. Методології. Сучасний CSS","\u002Fhtml-css\u002Fcss-variables-methodologies","12.html-css\u002F21.css-variables-methodologies",{"title":3177,"path":3178,"stem":3179},"Сучасний CSS 2023–2025: Нові можливості","\u002Fhtml-css\u002Fcss-modern-features","12.html-css\u002F22.css-modern-features",{"title":3181,"path":3182,"stem":3183},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","\u002Fhtml-css\u002F22a.css-nesting-modern-syntax","12.html-css\u002F22a.css-nesting-modern-syntax",{"title":3185,"path":3186,"stem":3187},"CSS для форм та інтерактивних станів","\u002Fhtml-css\u002Fcss-forms-interactive-states","12.html-css\u002F23.css-forms-interactive-states",{"title":3189,"path":3190,"stem":3191},"Доступність у CSS (CSS Accessibility)","\u002Fhtml-css\u002Fcss-accessibility","12.html-css\u002F24.css-accessibility",{"title":3193,"path":3194,"stem":3195},"CSS-функції та сучасні sizing primitives","\u002Fhtml-css\u002Fcss-functions-sizing","12.html-css\u002F25.css-functions-sizing",{"title":3197,"path":3198,"stem":3199},"Rendering Pipeline і CSS Performance","\u002Fhtml-css\u002Fcss-rendering-performance","12.html-css\u002F26.css-rendering-performance",{"title":3201,"path":3202,"stem":3203},"CSS Best Practices: типові ситуації та правильні рішення","\u002Fhtml-css\u002Fcss-best-practices","12.html-css\u002F27.css-best-practices",{"title":3205,"path":3206,"stem":3207,"children":3208,"page":59},"AWS","\u002Faws","13.aws",[3209,3213,3217,3221,3225,3229,3233,3237,3241,3245,3249,3253,3257,3261,3265,3269,3273,3277],{"title":3210,"path":3211,"stem":3212},"Реєстрація AWS акаунту та студентські програми","\u002Faws\u002Faccount-registration","13.aws\u002F00.account-registration",{"title":3214,"path":3215,"stem":3216},"Вступ до хмарних обчислень та AWS","\u002Faws\u002Fintroduction-to-cloud","13.aws\u002F01.introduction-to-cloud",{"title":3218,"path":3219,"stem":3220},"AWS IAM — Identity and Access Management","\u002Faws\u002Fiam","13.aws\u002F02.iam",{"title":3222,"path":3223,"stem":3224},"AWS IAM CLI — Довідник команд","\u002Faws\u002F02a.iam-doc","13.aws\u002F02a.iam-doc",{"title":3226,"path":3227,"stem":3228},"Docker та контейнеризація в AWS — ECR, ECS та Fargate","\u002Faws\u002Fdocker-ecs","13.aws\u002F03.docker-ecs",{"title":3230,"path":3231,"stem":3232},"AWS ECR \u002F ECS CLI — Довідник команд","\u002Faws\u002F03a.docker-ecs-doc","13.aws\u002F03a.docker-ecs-doc",{"title":3234,"path":3235,"stem":3236},"Amazon EC2 — Elastic Compute Cloud","\u002Faws\u002Fec2","13.aws\u002F04.ec2",{"title":3238,"path":3239,"stem":3240},"AWS EC2 CLI — Довідник команд","\u002Faws\u002F04a.ec2-doc","13.aws\u002F04a.ec2-doc",{"title":3242,"path":3243,"stem":3244},"Elastic Load Balancing та Auto Scaling","\u002Faws\u002Falb-asg","13.aws\u002F05.alb-asg",{"title":3246,"path":3247,"stem":3248},"Amazon S3 — Simple Storage Service","\u002Faws\u002Fs3","13.aws\u002F06.s3",{"title":3250,"path":3251,"stem":3252},"Amazon CloudFront — Content Delivery Network","\u002Faws\u002Fcloudfront","13.aws\u002F07.cloudfront",{"title":3254,"path":3255,"stem":3256},"Amazon RDS — Relational Database Service","\u002Faws\u002Frds","13.aws\u002F08.rds",{"title":3258,"path":3259,"stem":3260},"Amazon DynamoDB — NoSQL Database","\u002Faws\u002Fdynamodb","13.aws\u002F09.dynamodb",{"title":3262,"path":3263,"stem":3264},"AWS Lambda та Serverless Compute","\u002Faws\u002Flambda","13.aws\u002F10.lambda",{"title":3266,"path":3267,"stem":3268},"Amazon Bedrock - Foundation Models, RAG та Agents","\u002Faws\u002Fbedrock","13.aws\u002F22.bedrock",{"title":3270,"path":3271,"stem":3272},"Amazon Rekognition - Комп'ютерний зір","\u002Faws\u002Frekognition","13.aws\u002F23.rekognition",{"title":3274,"path":3275,"stem":3276},"Amazon Textract - Інтелектуальний аналіз документів","\u002Faws\u002Ftextract","13.aws\u002F24.textract",{"title":3278,"path":3279,"stem":3280},"Amazon Polly, Transcribe, Comprehend та Translate","\u002Faws\u002Faudio-nlp-services","13.aws\u002F25.audio-nlp-services",{"title":3282,"path":3283,"stem":3284,"children":3285,"page":59},"Tailwind","\u002Ftailwind","21.tailwind",[3286,3290,3294,3298,3302,3306,3310,3314,3318,3322,3326,3330],{"title":3287,"path":3288,"stem":3289},"Що таке Tailwind CSS і навіщо він потрібен","\u002Ftailwind\u002Ftailwind-intro-philosophy","21.tailwind\u002F01.tailwind-intro-philosophy",{"title":3291,"path":3292,"stem":3293},"Встановлення та налаштування Tailwind CSS v4","\u002Ftailwind\u002Ftailwind-installation-setup","21.tailwind\u002F02.tailwind-installation-setup",{"title":3295,"path":3296,"stem":3297},"Utility-класи: основи та система Tailwind","\u002Ftailwind\u002Ftailwind-utility-classes-core","21.tailwind\u002F03.tailwind-utility-classes-core",{"title":3299,"path":3300,"stem":3301},"Layout: Flexbox та Grid через Tailwind","\u002Ftailwind\u002Ftailwind-flexbox-grid","21.tailwind\u002F04.tailwind-flexbox-grid",{"title":3303,"path":3304,"stem":3305},"Кастомізація теми через @theme у Tailwind v4","\u002Ftailwind\u002Ftailwind-theme-customization","21.tailwind\u002F05.tailwind-theme-customization",{"title":3307,"path":3308,"stem":3309},"Варіанти: hover, focus, responsive, dark mode та нові v4","\u002Ftailwind\u002Ftailwind-variants-states","21.tailwind\u002F06.tailwind-variants-states",{"title":3311,"path":3312,"stem":3313},"Типографіка та система кольорів у Tailwind v4","\u002Ftailwind\u002Ftailwind-typography-colors","21.tailwind\u002F07.tailwind-typography-colors",{"title":3315,"path":3316,"stem":3317},"Компоненти та повторюваність: @apply, @utility та патерни","\u002Ftailwind\u002Ftailwind-components-patterns","21.tailwind\u002F08.tailwind-components-patterns",{"title":3319,"path":3320,"stem":3321},"Темна тема та система дизайн-токенів у Tailwind v4","\u002Ftailwind\u002Ftailwind-dark-mode-theming","21.tailwind\u002F09.tailwind-dark-mode-theming",{"title":3323,"path":3324,"stem":3325},"Довільні значення та контейнерні запити у Tailwind v4","\u002Ftailwind\u002Ftailwind-arbitrary-container-queries","21.tailwind\u002F10.tailwind-arbitrary-container-queries",{"title":3327,"path":3328,"stem":3329},"Анімації, трансформації та 3D у Tailwind v4","\u002Ftailwind\u002Ftailwind-animations-transforms","21.tailwind\u002F11.tailwind-animations-transforms",{"title":3331,"path":3332,"stem":3333},"Tailwind CLI, PostCSS та інтеграція з фреймворками","\u002Ftailwind\u002Ftailwind-cli-tooling","21.tailwind\u002F12.tailwind-cli-tooling",{"title":3335,"path":3336,"stem":3337},"Тестування компонентів діаграм","\u002Ftest-components","98.test-components",{"id":3339,"title":3258,"body":3340,"description":43223,"extension":43224,"links":43225,"meta":43226,"navigation":3440,"path":3259,"seo":43227,"stem":3260,"__hash__":43228},"docs\u002F13.aws\u002F09.dynamodb.md",{"type":3341,"value":3342,"toc":43115},"minimark",[3343,3347,3352,3356,3359,3367,3373,3395,3402,3719,3722,3726,3731,3736,3747,3758,3762,3771,3778,3983,3990,3994,4000,4095,4297,4302,4484,4487,4545,4547,4551,4562,4565,4569,4583,4588,4597,4614,4717,4725,4734,4846,4851,4893,4896,5097,5107,5112,5130,5135,5155,5159,5180,5187,5191,5198,5214,5331,5338,5348,5458,5466,5477,5614,5619,5659,5662,5814,5823,5920,5932,5938,6171,6175,6178,6282,6284,6288,6298,6302,6307,6615,6621,6960,6966,7404,7410,7641,7645,7654,7966,7975,8235,8455,8462,8466,8472,8976,8989,9689,9695,10427,10429,10433,10437,10450,10459,10502,10667,10671,10674,11158,11303,11839,11889,11893,13414,13524,13526,13530,13536,13547,13549,13552,13558,13591,13595,13628,13632,13638,13659,13663,13666,13670,13677,13699,13703,13777,13779,13782,13787,13810,13814,13845,13849,13854,13873,13877,13880,13883,13888,13902,13906,13982,13984,13988,14087,14090,14308,14310,14314,14330,14337,14349,14356,14500,14502,14748,14750,14754,14763,14766,14770,14773,14790,14809,14828,15003,15007,15010,15014,15021,15031,15037,15041,15051,15053,15057,15064,15112,15126,15130,15133,15241,15243,15247,16148,16152,16489,16671,16673,16677,16686,16690,16697,16700,16740,16924,16928,16934,16941,16945,16968,16972,16983,17003,17183,17187,17190,17194,17197,17234,17238,17241,17257,18137,18184,18188,18735,18737,18741,18744,18848,18850,18854,19026,19028,19032,19039,19043,19072,19076,19134,19283,19287,21334,21440,21442,21446,21457,21618,21620,21624,21639,21643,21646,21660,21663,21666,21670,21676,21679,21699,21703,21709,21727,21730,21748,21826,21828,21832,21839,21843,21876,21994,21998,22024,22026,22030,22044,22048,22062,22066,22069,22089,22091,22095,22189,22191,22195,22318,22333,22337,22340,22359,22361,22365,23915,24029,24033,24037,24052,24056,24094,24265,24269,24272,24345,24349,24356,24396,24400,25389,25391,25395,25407,25411,25414,25454,25460,25486,25501,25663,25667,25678,27403,27407,27411,27420,27424,27473,27588,27592,28780,28782,28786,28792,28796,28845,28988,28992,29974,29976,29980,29983,29987,29994,30000,30008,30014,30018,30032,30036,30041,30131,30138,30142,30149,30152,30154,30158,30161,30214,30290,30294,30413,30415,30419,30422,30426,30429,30474,30481,30488,30535,30553,30557,30563,30742,30773,30777,30787,30924,30928,30939,30977,30979,30983,30994,30998,31004,31071,31077,31082,31132,31136,31139,32044,32048,32056,32116,32119,32397,32399,32403,32415,32419,32422,32438,32442,32472,32476,32513,32517,32535,32539,32938,32942,32951,33129,33133,33139,33371,33373,33377,33385,33389,33395,33463,33467,33476,33515,33519,33526,33571,33575,33578,34088,34092,34098,34427,34431,34457,34461,34999,35001,35005,35008,35012,35023,35161,35179,35183,35191,35194,36020,36022,36026,36032,36036,36039,36077,36081,36932,36961,36963,36967,36970,37098,37100,37104,37122,37126,37135,37152,37155,37186,37189,37207,37209,37213,37227,37472,37477,37505,37507,37511,37524,37593,37598,37619,37621,37625,37628,37670,37675,37837,37839,37843,37854,37945,37949,37980,37996,37998,38002,38006,38016,38068,38072,38082,38142,38144,38148,38151,38192,38195,38218,38220,38224,38230,38240,38242,38246,38249,38705,38707,38711,38714,38752,39275,39277,39281,39294,40682,40684,40688,40694,41432,41436,41439,43058,43062,43065,43071,43077,43083,43089,43095,43101,43111],[3344,3345,3258],"h1",{"id":3346},"amazon-dynamodb-nosql-database",[3348,3349,3351],"h2",{"id":3350},"реляційна-парадигма-та-її-межі-навіщо-існує-dynamodb","Реляційна парадигма та її межі: навіщо існує DynamoDB",[3353,3354,3355],"p",{},"Протягом більш ніж чотирьох десятиліть реляційна модель баз даних домінувала у сфері зберігання структурованих даних. PostgreSQL, MySQL, SQL Server — ці системи побудовані на фундаменті, що залишається незмінним з часів Едгара Кодда: дані організовані у таблиці зі строго визначеною схемою, зв'язки між сутностями встановлюються через зовнішні ключі, а мова запитів SQL надає декларативний інтерфейс для маніпуляції даними. Для абсолютної більшості корпоративних застосунків ця модель є не просто достатньою — вона є оптимальною.",[3353,3357,3358],{},"Однак у 2000-х роках провідні інтернет-компанії зіткнулися зі сценарієм, де реляційна модель показала системні обмеження. Йдеться не про невелику деградацію продуктивності — йдеться про принципову неможливість масштабування до потрібних обсягів при збереженні прийнятних затримок. Проблема полягає у фундаментальній властивості реляційних систем: для гарантування ACID-властивостей (передусім Consistency та Isolation) вони використовують механізми блокувань, які за своєю природою є централізованими. Єдиний вузол або невеликий кластер може забезпечити сильну узгодженість, але горизонтальне масштабування на тисячі вузлів цю гарантію руйнує.",[3353,3360,3361,3362,3366],{},"Команда Amazon у 2004–2007 роках дослідила власні внутрішні сервіси та виявила закономірність: 70% операцій на їхніх production-системах мали форму \"прочитати або записати одну сутність за відомим ідентифікатором\", і лише 20% дійсно потребували можливостей JOIN та складних SQL-запитів. Це спостереження лягло в основу фундаментальної роботи ",[3363,3364,3365],"strong",{},"Dynamo: Amazon's Highly Available Key-Value Store"," (2007, Werner Vogels та ін.), яка описала архітектуру системи, що жертвує частиною семантики реляційної моделі заради лінійного горизонтального масштабування та гарантованих затримок.",[3353,3368,3369,3372],{},[3363,3370,3371],{},"Amazon DynamoDB"," — це хмарний керований NoSQL сервіс AWS, що є еволюцією оригінальної Dynamo-системи, публічно запущений у 2012 році. DynamoDB надає три гарантії, які в поєднанні недосяжні для будь-якої реляційної СУБД при масштабуванні:",[3374,3375,3376,3383,3389],"ol",{},[3377,3378,3379,3382],"li",{},[3363,3380,3381],{},"Продуктивність з однозначними мілісекундами"," — читання та запис будь-якого розміру таблиці виконуються з затримкою 1–10 ms (при правильному проектуванні)",[3377,3384,3385,3388],{},[3363,3386,3387],{},"Необмежений горизонтальний масштаб"," — одна таблиця DynamoDB здатна зберігати петабайти даних і обробляти мільйони запитів на секунду",[3377,3390,3391,3394],{},[3363,3392,3393],{},"Повністю керований сервіс"," — відсутність необхідності управляти серверами, patching, бекапами, реплікацією",[3396,3397,3398,3401],"note",{},[3363,3399,3400],{},"DynamoDB — це не заміна PostgreSQL."," Це інший інструмент для інших сценаріїв. У межах цього курсу ми розглянемо обидві системи: RDS PostgreSQL для транзакційних даних з комплексними відносинами, DynamoDB — для високонавантажених сценаріїв з передбачуваними патернами доступу. Вибір між ними є архітектурним рішенням, а не питанням переваг.",[3403,3404,3405],"plant-uml",{},[3406,3407,3412],"pre",{"className":3408,"code":3409,"language":3410,"meta":3411,"style":3411},"language-plantuml shiki shiki-themes light-plus dark-plus dark-plus","@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\nrectangle \"Реляційна модель (RDS PostgreSQL)\" as RDB #dbeafe {\n    note as RDB_NOTE\n      ✅ Складні JOIN між таблицями\n      ✅ Транзакції через кілька таблиць\n      ✅ Гнучкі ad-hoc запити (SQL)\n      ✅ Сильна узгодженість (ACID)\n      ❌ Горизонтальне масштабування складне\n      ❌ Латентність зростає з обсягом даних\n      ❌ Schema migrations при змінах\n    end note\n}\n\nrectangle \"NoSQL модель (DynamoDB)\" as NOSQL #d1fae5 {\n    note as NOSQL_NOTE\n      ✅ Необмежений горизонтальний масштаб\n      ✅ Гарантована низька латентність (~1–10ms)\n      ✅ Гнучка схема (schema-less)\n      ✅ Автоматична реплікація та HA\n      ❌ Не підтримує JOIN між таблицями\n      ❌ Обмежені можливості запитів\n      ❌ Потребує ретельного проектування ключів\n    end note\n}\n\nrectangle \"Коли обирати RDS\" as WHEN_RDB #eff6ff {\n    note as WHEN_RDB_NOTE\n      - Корпоративні системи з комплексними\n        зв'язками (ERP, CRM, облік)\n      - Фінансові транзакції між таблицями\n      - Аналітичні запити (GROUP BY, aggregate)\n      - Команда добре знає SQL\n    end note\n}\n\nrectangle \"Коли обирати DynamoDB\" as WHEN_NOSQL #f0fdf4 {\n    note as WHEN_NOSQL_NOTE\n      - Сесії користувачів, кешування\n      - Ігрові leaderboards\n      - IoT-дані (часові ряди)\n      - E-commerce (кошики, каталог товарів)\n      - Мільйони запитів\u002Fсек з \u003C10ms\n    end note\n}\n\nRDB -[hidden]right-> NOSQL\nWHEN_RDB -[hidden]right-> WHEN_NOSQL\n\n@enduml\n","plantuml","",[3413,3414,3415,3423,3429,3435,3442,3448,3454,3460,3466,3472,3478,3484,3490,3496,3502,3508,3513,3519,3525,3531,3537,3543,3549,3555,3561,3567,3572,3577,3582,3588,3594,3600,3606,3612,3618,3624,3629,3634,3639,3645,3651,3657,3663,3669,3675,3681,3686,3691,3696,3702,3708,3713],"code",{"__ignoreMap":3411},[3416,3417,3420],"span",{"class":3418,"line":3419},"line",1,[3416,3421,3422],{},"@startuml\n",[3416,3424,3426],{"class":3418,"line":3425},2,[3416,3427,3428],{},"skinparam style plain\n",[3416,3430,3432],{"class":3418,"line":3431},3,[3416,3433,3434],{},"skinparam backgroundColor #ffffff\n",[3416,3436,3438],{"class":3418,"line":3437},4,[3416,3439,3441],{"emptyLinePlaceholder":3440},true,"\n",[3416,3443,3445],{"class":3418,"line":3444},5,[3416,3446,3447],{},"rectangle \"Реляційна модель (RDS PostgreSQL)\" as RDB #dbeafe {\n",[3416,3449,3451],{"class":3418,"line":3450},6,[3416,3452,3453],{},"    note as RDB_NOTE\n",[3416,3455,3457],{"class":3418,"line":3456},7,[3416,3458,3459],{},"      ✅ Складні JOIN між таблицями\n",[3416,3461,3463],{"class":3418,"line":3462},8,[3416,3464,3465],{},"      ✅ Транзакції через кілька таблиць\n",[3416,3467,3469],{"class":3418,"line":3468},9,[3416,3470,3471],{},"      ✅ Гнучкі ad-hoc запити (SQL)\n",[3416,3473,3475],{"class":3418,"line":3474},10,[3416,3476,3477],{},"      ✅ Сильна узгодженість (ACID)\n",[3416,3479,3481],{"class":3418,"line":3480},11,[3416,3482,3483],{},"      ❌ Горизонтальне масштабування складне\n",[3416,3485,3487],{"class":3418,"line":3486},12,[3416,3488,3489],{},"      ❌ Латентність зростає з обсягом даних\n",[3416,3491,3493],{"class":3418,"line":3492},13,[3416,3494,3495],{},"      ❌ Schema migrations при змінах\n",[3416,3497,3499],{"class":3418,"line":3498},14,[3416,3500,3501],{},"    end note\n",[3416,3503,3505],{"class":3418,"line":3504},15,[3416,3506,3507],{},"}\n",[3416,3509,3511],{"class":3418,"line":3510},16,[3416,3512,3441],{"emptyLinePlaceholder":3440},[3416,3514,3516],{"class":3418,"line":3515},17,[3416,3517,3518],{},"rectangle \"NoSQL модель (DynamoDB)\" as NOSQL #d1fae5 {\n",[3416,3520,3522],{"class":3418,"line":3521},18,[3416,3523,3524],{},"    note as NOSQL_NOTE\n",[3416,3526,3528],{"class":3418,"line":3527},19,[3416,3529,3530],{},"      ✅ Необмежений горизонтальний масштаб\n",[3416,3532,3534],{"class":3418,"line":3533},20,[3416,3535,3536],{},"      ✅ Гарантована низька латентність (~1–10ms)\n",[3416,3538,3540],{"class":3418,"line":3539},21,[3416,3541,3542],{},"      ✅ Гнучка схема (schema-less)\n",[3416,3544,3546],{"class":3418,"line":3545},22,[3416,3547,3548],{},"      ✅ Автоматична реплікація та HA\n",[3416,3550,3552],{"class":3418,"line":3551},23,[3416,3553,3554],{},"      ❌ Не підтримує JOIN між таблицями\n",[3416,3556,3558],{"class":3418,"line":3557},24,[3416,3559,3560],{},"      ❌ Обмежені можливості запитів\n",[3416,3562,3564],{"class":3418,"line":3563},25,[3416,3565,3566],{},"      ❌ Потребує ретельного проектування ключів\n",[3416,3568,3570],{"class":3418,"line":3569},26,[3416,3571,3501],{},[3416,3573,3575],{"class":3418,"line":3574},27,[3416,3576,3507],{},[3416,3578,3580],{"class":3418,"line":3579},28,[3416,3581,3441],{"emptyLinePlaceholder":3440},[3416,3583,3585],{"class":3418,"line":3584},29,[3416,3586,3587],{},"rectangle \"Коли обирати RDS\" as WHEN_RDB #eff6ff {\n",[3416,3589,3591],{"class":3418,"line":3590},30,[3416,3592,3593],{},"    note as WHEN_RDB_NOTE\n",[3416,3595,3597],{"class":3418,"line":3596},31,[3416,3598,3599],{},"      - Корпоративні системи з комплексними\n",[3416,3601,3603],{"class":3418,"line":3602},32,[3416,3604,3605],{},"        зв'язками (ERP, CRM, облік)\n",[3416,3607,3609],{"class":3418,"line":3608},33,[3416,3610,3611],{},"      - Фінансові транзакції між таблицями\n",[3416,3613,3615],{"class":3418,"line":3614},34,[3416,3616,3617],{},"      - Аналітичні запити (GROUP BY, aggregate)\n",[3416,3619,3621],{"class":3418,"line":3620},35,[3416,3622,3623],{},"      - Команда добре знає SQL\n",[3416,3625,3627],{"class":3418,"line":3626},36,[3416,3628,3501],{},[3416,3630,3632],{"class":3418,"line":3631},37,[3416,3633,3507],{},[3416,3635,3637],{"class":3418,"line":3636},38,[3416,3638,3441],{"emptyLinePlaceholder":3440},[3416,3640,3642],{"class":3418,"line":3641},39,[3416,3643,3644],{},"rectangle \"Коли обирати DynamoDB\" as WHEN_NOSQL #f0fdf4 {\n",[3416,3646,3648],{"class":3418,"line":3647},40,[3416,3649,3650],{},"    note as WHEN_NOSQL_NOTE\n",[3416,3652,3654],{"class":3418,"line":3653},41,[3416,3655,3656],{},"      - Сесії користувачів, кешування\n",[3416,3658,3660],{"class":3418,"line":3659},42,[3416,3661,3662],{},"      - Ігрові leaderboards\n",[3416,3664,3666],{"class":3418,"line":3665},43,[3416,3667,3668],{},"      - IoT-дані (часові ряди)\n",[3416,3670,3672],{"class":3418,"line":3671},44,[3416,3673,3674],{},"      - E-commerce (кошики, каталог товарів)\n",[3416,3676,3678],{"class":3418,"line":3677},45,[3416,3679,3680],{},"      - Мільйони запитів\u002Fсек з \u003C10ms\n",[3416,3682,3684],{"class":3418,"line":3683},46,[3416,3685,3501],{},[3416,3687,3689],{"class":3418,"line":3688},47,[3416,3690,3507],{},[3416,3692,3694],{"class":3418,"line":3693},48,[3416,3695,3441],{"emptyLinePlaceholder":3440},[3416,3697,3699],{"class":3418,"line":3698},49,[3416,3700,3701],{},"RDB -[hidden]right-> NOSQL\n",[3416,3703,3705],{"class":3418,"line":3704},50,[3416,3706,3707],{},"WHEN_RDB -[hidden]right-> WHEN_NOSQL\n",[3416,3709,3711],{"class":3418,"line":3710},51,[3416,3712,3441],{"emptyLinePlaceholder":3440},[3416,3714,3716],{"class":3418,"line":3715},52,[3416,3717,3718],{},"@enduml\n",[3720,3721],"hr",{},[3348,3723,3725],{"id":3724},"модель-даних-dynamodb-таблиці-елементи-та-атрибути","Модель даних DynamoDB: таблиці, елементи та атрибути",[3727,3728,3730],"h3",{"id":3729},"таблиця-table","Таблиця (Table)",[3353,3732,3733,3735],{},[3363,3734,3730],{}," є найвищим рівнем організації даних у DynamoDB. На перший погляд, таблиця DynamoDB схожа на таблицю реляційної бази даних — вона має назву та містить записи. Проте між ними існує принципова різниця у семантиці.",[3353,3737,3738,3739,3742,3743,3746],{},"У реляційній моделі таблиця визначає ",[3363,3740,3741],{},"схему",": структуру кожного рядка з іменами стовпців та їхніми типами задають при CREATE TABLE, і всі рядки повинні відповідати цій схемі. DynamoDB, навпаки, є ",[3363,3744,3745],{},"schema-less"," на рівні атрибутів: єдине, що таблиця DynamoDB вимагає від кожного елемента — наявність атрибутів, що складають первинний ключ. Решта атрибутів кожного елемента може бути абсолютно довільною та різною від елемента до елемента.",[3353,3748,3749,3750,3753,3754,3757],{},"Таблиця DynamoDB є незалежним ресурсом — вона не \"належить\" схемі чи базі даних. Якщо в PostgreSQL ви маєте ",[3413,3751,3752],{},"database → schema → table",", то у DynamoDB ієрархія скорочується до ",[3413,3755,3756],{},"table",". Це означає, що таблиці DynamoDB не можуть бути об'єднані через JOIN навіть синтаксично — такого механізму не існує.",[3727,3759,3761],{"id":3760},"елемент-item","Елемент (Item)",[3353,3763,3764,3766,3767,3770],{},[3363,3765,3761],{}," — це одиниця даних у таблиці DynamoDB, аналог рядка (row) у реляційній базі даних. Кожен елемент унікально ідентифікується своїм первинним ключем та є колекцією атрибутів. Максимальний розмір одного елемента — ",[3363,3768,3769],{},"400 KB"," (разом з іменами атрибутів та значеннями).",[3353,3772,3773,3774,3777],{},"Відсутність фіксованої схеми надає DynamoDB надзвичайну гнучкість при еволюції моделі даних. Уявіть таблицю ",[3413,3775,3776],{},"Products",", де різні категорії товарів мають різний набір атрибутів:",[3406,3779,3783],{"className":3780,"code":3781,"language":3782,"meta":3411,"style":3411},"language-json shiki shiki-themes light-plus dark-plus dark-plus","\u002F\u002F Елемент 1: Книга\n{\n    \"ProductId\": \"book-001\",\n    \"Category\": \"Book\",\n    \"Title\": \"Clean Code\",\n    \"Author\": \"Robert C. Martin\",\n    \"ISBN\": \"978-0132350884\",\n    \"Pages\": 431,\n    \"Price\": 35.00\n}\n\n\u002F\u002F Елемент 2: Електроніка\n{\n    \"ProductId\": \"elec-002\",\n    \"Category\": \"Electronics\",\n    \"Title\": \"Sony WH-1000XM5\",\n    \"Brand\": \"Sony\",\n    \"WarrantyYears\": 2,\n    \"BatteryLifeHours\": 30,\n    \"Price\": 349.99\n}\n","json",[3413,3784,3785,3791,3797,3813,3825,3837,3849,3861,3874,3884,3888,3892,3897,3901,3912,3923,3934,3946,3958,3970,3979],{"__ignoreMap":3411},[3416,3786,3787],{"class":3418,"line":3419},[3416,3788,3790],{"class":3789},"spJ8K","\u002F\u002F Елемент 1: Книга\n",[3416,3792,3793],{"class":3418,"line":3425},[3416,3794,3796],{"class":3795},"sHH4Y","{\n",[3416,3798,3799,3803,3806,3810],{"class":3418,"line":3431},[3416,3800,3802],{"class":3801},"sLwNe","    \"ProductId\"",[3416,3804,3805],{"class":3795},": ",[3416,3807,3809],{"class":3808},"sbdoH","\"book-001\"",[3416,3811,3812],{"class":3795},",\n",[3416,3814,3815,3818,3820,3823],{"class":3418,"line":3437},[3416,3816,3817],{"class":3801},"    \"Category\"",[3416,3819,3805],{"class":3795},[3416,3821,3822],{"class":3808},"\"Book\"",[3416,3824,3812],{"class":3795},[3416,3826,3827,3830,3832,3835],{"class":3418,"line":3444},[3416,3828,3829],{"class":3801},"    \"Title\"",[3416,3831,3805],{"class":3795},[3416,3833,3834],{"class":3808},"\"Clean Code\"",[3416,3836,3812],{"class":3795},[3416,3838,3839,3842,3844,3847],{"class":3418,"line":3450},[3416,3840,3841],{"class":3801},"    \"Author\"",[3416,3843,3805],{"class":3795},[3416,3845,3846],{"class":3808},"\"Robert C. Martin\"",[3416,3848,3812],{"class":3795},[3416,3850,3851,3854,3856,3859],{"class":3418,"line":3456},[3416,3852,3853],{"class":3801},"    \"ISBN\"",[3416,3855,3805],{"class":3795},[3416,3857,3858],{"class":3808},"\"978-0132350884\"",[3416,3860,3812],{"class":3795},[3416,3862,3863,3866,3868,3872],{"class":3418,"line":3462},[3416,3864,3865],{"class":3801},"    \"Pages\"",[3416,3867,3805],{"class":3795},[3416,3869,3871],{"class":3870},"sJj4R","431",[3416,3873,3812],{"class":3795},[3416,3875,3876,3879,3881],{"class":3418,"line":3468},[3416,3877,3878],{"class":3801},"    \"Price\"",[3416,3880,3805],{"class":3795},[3416,3882,3883],{"class":3870},"35.00\n",[3416,3885,3886],{"class":3418,"line":3474},[3416,3887,3507],{"class":3795},[3416,3889,3890],{"class":3418,"line":3480},[3416,3891,3441],{"emptyLinePlaceholder":3440},[3416,3893,3894],{"class":3418,"line":3486},[3416,3895,3896],{"class":3789},"\u002F\u002F Елемент 2: Електроніка\n",[3416,3898,3899],{"class":3418,"line":3492},[3416,3900,3796],{"class":3795},[3416,3902,3903,3905,3907,3910],{"class":3418,"line":3498},[3416,3904,3802],{"class":3801},[3416,3906,3805],{"class":3795},[3416,3908,3909],{"class":3808},"\"elec-002\"",[3416,3911,3812],{"class":3795},[3416,3913,3914,3916,3918,3921],{"class":3418,"line":3504},[3416,3915,3817],{"class":3801},[3416,3917,3805],{"class":3795},[3416,3919,3920],{"class":3808},"\"Electronics\"",[3416,3922,3812],{"class":3795},[3416,3924,3925,3927,3929,3932],{"class":3418,"line":3510},[3416,3926,3829],{"class":3801},[3416,3928,3805],{"class":3795},[3416,3930,3931],{"class":3808},"\"Sony WH-1000XM5\"",[3416,3933,3812],{"class":3795},[3416,3935,3936,3939,3941,3944],{"class":3418,"line":3515},[3416,3937,3938],{"class":3801},"    \"Brand\"",[3416,3940,3805],{"class":3795},[3416,3942,3943],{"class":3808},"\"Sony\"",[3416,3945,3812],{"class":3795},[3416,3947,3948,3951,3953,3956],{"class":3418,"line":3521},[3416,3949,3950],{"class":3801},"    \"WarrantyYears\"",[3416,3952,3805],{"class":3795},[3416,3954,3955],{"class":3870},"2",[3416,3957,3812],{"class":3795},[3416,3959,3960,3963,3965,3968],{"class":3418,"line":3527},[3416,3961,3962],{"class":3801},"    \"BatteryLifeHours\"",[3416,3964,3805],{"class":3795},[3416,3966,3967],{"class":3870},"30",[3416,3969,3812],{"class":3795},[3416,3971,3972,3974,3976],{"class":3418,"line":3533},[3416,3973,3878],{"class":3801},[3416,3975,3805],{"class":3795},[3416,3977,3978],{"class":3870},"349.99\n",[3416,3980,3981],{"class":3418,"line":3539},[3416,3982,3507],{"class":3795},[3353,3984,3985,3986,3989],{},"Обидва елементи належать одній таблиці, але мають абсолютно різні набори атрибутів. У PostgreSQL для цього знадобилося б або успадкування таблиць, або поле типу ",[3413,3987,3988],{},"JSONB",", або окремі таблиці для кожної категорії.",[3727,3991,3993],{"id":3992},"атрибут-attribute-та-система-типів","Атрибут (Attribute) та система типів",[3353,3995,3996,3999],{},[3363,3997,3998],{},"Атрибут (Attribute)"," — це пара \"ім'я–значення\", що належить конкретному елементу. DynamoDB підтримує систему типів даних, яка суттєво відрізняється від SQL-типів:",[4001,4002,4003,4050,4066],"card-group",{},[4004,4005,4008,4018,4024,4030,4044],"card",{"icon":4006,"title":4007},"i-heroicons-tag","Скалярні типи (Scalar)",[3353,4009,4010,4013,4014,4017],{},[3363,4011,4012],{},"String (S)"," — рядок у кодуванні UTF-8. Порожній рядок (",[3413,4015,4016],{},"\"\"",") дозволений.",[3353,4019,4020,4023],{},[3363,4021,4022],{},"Number (N)"," — числове значення (ціле або дробове). Зберігається як рядок для збереження точності. Діапазон: до 38 значущих цифр.",[3353,4025,4026,4029],{},[3363,4027,4028],{},"Binary (B)"," — бінарні дані у форматі Base64. Використовується для зберігання зображень, стиснутих даних, криптографічних хешів.",[3353,4031,4032,4035,4036,4039,4040,4043],{},[3363,4033,4034],{},"Boolean (BOOL)"," — ",[3413,4037,4038],{},"true"," або ",[3413,4041,4042],{},"false",".",[3353,4045,4046,4049],{},[3363,4047,4048],{},"Null (NULL)"," — відсутність значення. Атрибут типу Null займає місце, але не має значення.",[4004,4051,4054,4060],{"icon":4052,"title":4053},"i-heroicons-document","Документні типи (Document)",[3353,4055,4056,4059],{},[3363,4057,4058],{},"Map (M)"," — довільна структура вигляду \"ключ–значення\", аналог JSON-об'єкта. Значення кожного ключа може бути будь-яким типом DynamoDB, включаючи вкладені Map.",[3353,4061,4062,4065],{},[3363,4063,4064],{},"List (L)"," — впорядкована колекція значень довільних типів. Аналог JSON-масиву. Елементи списку можуть бути різних типів.",[4004,4067,4070,4076,4082,4088],{"icon":4068,"title":4069},"i-heroicons-squares-2x2","Множинні типи (Set)",[3353,4071,4072,4075],{},[3363,4073,4074],{},"StringSet (SS)"," — невпорядкована колекція унікальних рядків.",[3353,4077,4078,4081],{},[3363,4079,4080],{},"NumberSet (NS)"," — невпорядкована колекція унікальних чисел.",[3353,4083,4084,4087],{},[3363,4085,4086],{},"BinarySet (BS)"," — невпорядкована колекція унікальних бінарних значень.",[3353,4089,4090,4094],{},[4091,4092,4093],"em",{},"Важливо:"," Set не може бути порожнім. Всі елементи Set мають бути одного типу.",[3403,4096,4097],{},[3406,4098,4100],{"className":3408,"code":4099,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\npackage \"DynamoDB Type System\" {\n    rectangle \"Scalar Types\" as SCALAR #fef3c7 {\n        note as S_NOTE\n          String (S):     \"London\"\n          Number (N):     42.5\n          Binary (B):     \u003Cbase64>\n          Boolean (BOOL): true\n          Null (NULL):    null\n        end note\n    }\n\n    rectangle \"Document Types\" as DOC #dbeafe {\n        note as D_NOTE\n          Map (M): {\n            \"city\": \"London\",\n            \"zip\": \"EC1A\"\n          }\n          List (L): [\n            \"one\", 2, true, {\"key\": \"val\"}\n          ]\n        end note\n    }\n\n    rectangle \"Set Types\" as SETS #d1fae5 {\n        note as SET_NOTE\n          StringSet (SS):\n            [\"red\", \"green\", \"blue\"]\n\n          NumberSet (NS):\n            [1, 2, 3, 5, 8, 13]\n\n          BinarySet (BS):\n            [\u003Cb64_1>, \u003Cb64_2>]\n        end note\n    }\n}\n\n@enduml\n",[3413,4101,4102,4106,4110,4114,4118,4123,4128,4133,4138,4143,4148,4153,4158,4163,4168,4172,4177,4182,4187,4192,4197,4202,4207,4212,4217,4221,4225,4229,4234,4239,4244,4249,4253,4258,4263,4267,4272,4277,4281,4285,4289,4293],{"__ignoreMap":3411},[3416,4103,4104],{"class":3418,"line":3419},[3416,4105,3422],{},[3416,4107,4108],{"class":3418,"line":3425},[3416,4109,3428],{},[3416,4111,4112],{"class":3418,"line":3431},[3416,4113,3434],{},[3416,4115,4116],{"class":3418,"line":3437},[3416,4117,3441],{"emptyLinePlaceholder":3440},[3416,4119,4120],{"class":3418,"line":3444},[3416,4121,4122],{},"package \"DynamoDB Type System\" {\n",[3416,4124,4125],{"class":3418,"line":3450},[3416,4126,4127],{},"    rectangle \"Scalar Types\" as SCALAR #fef3c7 {\n",[3416,4129,4130],{"class":3418,"line":3456},[3416,4131,4132],{},"        note as S_NOTE\n",[3416,4134,4135],{"class":3418,"line":3462},[3416,4136,4137],{},"          String (S):     \"London\"\n",[3416,4139,4140],{"class":3418,"line":3468},[3416,4141,4142],{},"          Number (N):     42.5\n",[3416,4144,4145],{"class":3418,"line":3474},[3416,4146,4147],{},"          Binary (B):     \u003Cbase64>\n",[3416,4149,4150],{"class":3418,"line":3480},[3416,4151,4152],{},"          Boolean (BOOL): true\n",[3416,4154,4155],{"class":3418,"line":3486},[3416,4156,4157],{},"          Null (NULL):    null\n",[3416,4159,4160],{"class":3418,"line":3492},[3416,4161,4162],{},"        end note\n",[3416,4164,4165],{"class":3418,"line":3498},[3416,4166,4167],{},"    }\n",[3416,4169,4170],{"class":3418,"line":3504},[3416,4171,3441],{"emptyLinePlaceholder":3440},[3416,4173,4174],{"class":3418,"line":3510},[3416,4175,4176],{},"    rectangle \"Document Types\" as DOC #dbeafe {\n",[3416,4178,4179],{"class":3418,"line":3515},[3416,4180,4181],{},"        note as D_NOTE\n",[3416,4183,4184],{"class":3418,"line":3521},[3416,4185,4186],{},"          Map (M): {\n",[3416,4188,4189],{"class":3418,"line":3527},[3416,4190,4191],{},"            \"city\": \"London\",\n",[3416,4193,4194],{"class":3418,"line":3533},[3416,4195,4196],{},"            \"zip\": \"EC1A\"\n",[3416,4198,4199],{"class":3418,"line":3539},[3416,4200,4201],{},"          }\n",[3416,4203,4204],{"class":3418,"line":3545},[3416,4205,4206],{},"          List (L): [\n",[3416,4208,4209],{"class":3418,"line":3551},[3416,4210,4211],{},"            \"one\", 2, true, {\"key\": \"val\"}\n",[3416,4213,4214],{"class":3418,"line":3557},[3416,4215,4216],{},"          ]\n",[3416,4218,4219],{"class":3418,"line":3563},[3416,4220,4162],{},[3416,4222,4223],{"class":3418,"line":3569},[3416,4224,4167],{},[3416,4226,4227],{"class":3418,"line":3574},[3416,4228,3441],{"emptyLinePlaceholder":3440},[3416,4230,4231],{"class":3418,"line":3579},[3416,4232,4233],{},"    rectangle \"Set Types\" as SETS #d1fae5 {\n",[3416,4235,4236],{"class":3418,"line":3584},[3416,4237,4238],{},"        note as SET_NOTE\n",[3416,4240,4241],{"class":3418,"line":3590},[3416,4242,4243],{},"          StringSet (SS):\n",[3416,4245,4246],{"class":3418,"line":3596},[3416,4247,4248],{},"            [\"red\", \"green\", \"blue\"]\n",[3416,4250,4251],{"class":3418,"line":3602},[3416,4252,3441],{"emptyLinePlaceholder":3440},[3416,4254,4255],{"class":3418,"line":3608},[3416,4256,4257],{},"          NumberSet (NS):\n",[3416,4259,4260],{"class":3418,"line":3614},[3416,4261,4262],{},"            [1, 2, 3, 5, 8, 13]\n",[3416,4264,4265],{"class":3418,"line":3620},[3416,4266,3441],{"emptyLinePlaceholder":3440},[3416,4268,4269],{"class":3418,"line":3626},[3416,4270,4271],{},"          BinarySet (BS):\n",[3416,4273,4274],{"class":3418,"line":3631},[3416,4275,4276],{},"            [\u003Cb64_1>, \u003Cb64_2>]\n",[3416,4278,4279],{"class":3418,"line":3636},[3416,4280,4162],{},[3416,4282,4283],{"class":3418,"line":3641},[3416,4284,4167],{},[3416,4286,4287],{"class":3418,"line":3647},[3416,4288,3507],{},[3416,4290,4291],{"class":3418,"line":3653},[3416,4292,3441],{"emptyLinePlaceholder":3440},[3416,4294,4295],{"class":3418,"line":3659},[3416,4296,3718],{},[3353,4298,4299],{},[3363,4300,4301],{},"Приклад елемента з вкладеними типами:",[3406,4303,4305],{"className":3780,"code":4304,"language":3782,"meta":3411,"style":3411},"{\n    \"UserId\": \"usr-123\",\n    \"Name\": \"Олена Петренко\",\n    \"Email\": \"elena@example.com\",\n    \"Age\": 28,\n    \"IsActive\": true,\n    \"Tags\": [\"developer\", \"aws-certified\", \"ukraine\"],\n    \"Address\": {\n        \"Country\": \"Ukraine\",\n        \"City\": \"Kyiv\",\n        \"ZipCode\": \"01001\"\n    },\n    \"Skills\": [\"C#\", \".NET\", \"DynamoDB\", \"PostgreSQL\"],\n    \"LastLoginAt\": \"2025-06-01T10:30:00Z\"\n}\n",[3413,4306,4307,4311,4323,4335,4347,4359,4371,4396,4404,4416,4428,4438,4443,4470,4480],{"__ignoreMap":3411},[3416,4308,4309],{"class":3418,"line":3419},[3416,4310,3796],{"class":3795},[3416,4312,4313,4316,4318,4321],{"class":3418,"line":3425},[3416,4314,4315],{"class":3801},"    \"UserId\"",[3416,4317,3805],{"class":3795},[3416,4319,4320],{"class":3808},"\"usr-123\"",[3416,4322,3812],{"class":3795},[3416,4324,4325,4328,4330,4333],{"class":3418,"line":3431},[3416,4326,4327],{"class":3801},"    \"Name\"",[3416,4329,3805],{"class":3795},[3416,4331,4332],{"class":3808},"\"Олена Петренко\"",[3416,4334,3812],{"class":3795},[3416,4336,4337,4340,4342,4345],{"class":3418,"line":3437},[3416,4338,4339],{"class":3801},"    \"Email\"",[3416,4341,3805],{"class":3795},[3416,4343,4344],{"class":3808},"\"elena@example.com\"",[3416,4346,3812],{"class":3795},[3416,4348,4349,4352,4354,4357],{"class":3418,"line":3444},[3416,4350,4351],{"class":3801},"    \"Age\"",[3416,4353,3805],{"class":3795},[3416,4355,4356],{"class":3870},"28",[3416,4358,3812],{"class":3795},[3416,4360,4361,4364,4366,4369],{"class":3418,"line":3450},[3416,4362,4363],{"class":3801},"    \"IsActive\"",[3416,4365,3805],{"class":3795},[3416,4367,4038],{"class":4368},"su1O8",[3416,4370,3812],{"class":3795},[3416,4372,4373,4376,4379,4382,4385,4388,4390,4393],{"class":3418,"line":3456},[3416,4374,4375],{"class":3801},"    \"Tags\"",[3416,4377,4378],{"class":3795},": [",[3416,4380,4381],{"class":3808},"\"developer\"",[3416,4383,4384],{"class":3795},", ",[3416,4386,4387],{"class":3808},"\"aws-certified\"",[3416,4389,4384],{"class":3795},[3416,4391,4392],{"class":3808},"\"ukraine\"",[3416,4394,4395],{"class":3795},"],\n",[3416,4397,4398,4401],{"class":3418,"line":3462},[3416,4399,4400],{"class":3801},"    \"Address\"",[3416,4402,4403],{"class":3795},": {\n",[3416,4405,4406,4409,4411,4414],{"class":3418,"line":3468},[3416,4407,4408],{"class":3801},"        \"Country\"",[3416,4410,3805],{"class":3795},[3416,4412,4413],{"class":3808},"\"Ukraine\"",[3416,4415,3812],{"class":3795},[3416,4417,4418,4421,4423,4426],{"class":3418,"line":3474},[3416,4419,4420],{"class":3801},"        \"City\"",[3416,4422,3805],{"class":3795},[3416,4424,4425],{"class":3808},"\"Kyiv\"",[3416,4427,3812],{"class":3795},[3416,4429,4430,4433,4435],{"class":3418,"line":3480},[3416,4431,4432],{"class":3801},"        \"ZipCode\"",[3416,4434,3805],{"class":3795},[3416,4436,4437],{"class":3808},"\"01001\"\n",[3416,4439,4440],{"class":3418,"line":3486},[3416,4441,4442],{"class":3795},"    },\n",[3416,4444,4445,4448,4450,4453,4455,4458,4460,4463,4465,4468],{"class":3418,"line":3492},[3416,4446,4447],{"class":3801},"    \"Skills\"",[3416,4449,4378],{"class":3795},[3416,4451,4452],{"class":3808},"\"C#\"",[3416,4454,4384],{"class":3795},[3416,4456,4457],{"class":3808},"\".NET\"",[3416,4459,4384],{"class":3795},[3416,4461,4462],{"class":3808},"\"DynamoDB\"",[3416,4464,4384],{"class":3795},[3416,4466,4467],{"class":3808},"\"PostgreSQL\"",[3416,4469,4395],{"class":3795},[3416,4471,4472,4475,4477],{"class":3418,"line":3498},[3416,4473,4474],{"class":3801},"    \"LastLoginAt\"",[3416,4476,3805],{"class":3795},[3416,4478,4479],{"class":3808},"\"2025-06-01T10:30:00Z\"\n",[3416,4481,4482],{"class":3418,"line":3504},[3416,4483,3507],{"class":3795},[3353,4485,4486],{},"У цьому прикладі:",[4488,4489,4490,4507,4514,4521,4529,4537],"ul",{},[3377,4491,4492,4384,4495,4384,4498,4384,4501,4504,4505],{},[3413,4493,4494],{},"UserId",[3413,4496,4497],{},"Name",[3413,4499,4500],{},"Email",[3413,4502,4503],{},"LastLoginAt"," — тип ",[3363,4506,4012],{},[3377,4508,4509,4504,4512],{},[3413,4510,4511],{},"Age",[3363,4513,4022],{},[3377,4515,4516,4504,4519],{},[3413,4517,4518],{},"IsActive",[3363,4520,4034],{},[3377,4522,4523,4504,4526,4528],{},[3413,4524,4525],{},"Tags",[3363,4527,4064],{}," зі String-елементами",[3377,4530,4531,4504,4534,4536],{},[3413,4532,4533],{},"Address",[3363,4535,4058],{}," з вкладеними String-атрибутами",[3377,4538,4539,4504,4542,4544],{},[3413,4540,4541],{},"Skills",[3363,4543,4074],{}," (множина, не може містити дублікати)",[3720,4546],{},[3348,4548,4550],{"id":4549},"первинний-ключ-primary-key-фундамент-dynamodb","Первинний ключ (Primary Key): фундамент DynamoDB",[3353,4552,4553,4554,4557,4558,4561],{},"Первинний ключ є найважливішим концептуальним елементом DynamoDB. На відміну від реляційних баз даних, де первинний ключ є лише засобом унікальної ідентифікації рядка, у DynamoDB первинний ключ виконує дві нерозривно пов'язані функції одночасно: ",[3363,4555,4556],{},"унікальну ідентифікацію"," елемента та ",[3363,4559,4560],{},"визначення фізичного розташування"," даних на серверах. Саме тому вибір первинного ключа є фундаментальним архітектурним рішенням, від якого залежить продуктивність системи при будь-якому масштабі.",[3353,4563,4564],{},"DynamoDB підтримує два типи первинного ключа.",[3727,4566,4568],{"id":4567},"partition-key-simple-primary-key","Partition Key (Simple Primary Key)",[3353,4570,4571,4574,4575,4578,4579,4582],{},[3363,4572,4573],{},"Partition Key"," (також відомий як Hash Key або PK) — це простий первинний ключ, що складається з одного атрибута. DynamoDB використовує значення Partition Key як вхідні дані для детермінованої ",[3363,4576,4577],{},"хеш-функції",", результат якої визначає, на якому ",[3363,4580,4581],{},"фізичному сервері (partition)"," зберігатиметься елемент.",[4584,4585,4587],"h4",{"id":4586},"візуалізація-simple-primary-key","Візуалізація Simple Primary Key",[4589,4590,4592,4593,4596],"h5",{"id":4591},"приклад-1-таблиця-users-профілі-користувачів","Приклад 1: Таблиця ",[3413,4594,4595],{},"Users"," (Профілі користувачів)",[3353,4598,4599,4600,4602,4603,4606,4607,4384,4609,4384,4611,4613],{},"У цій таблиці первинним ключем є ",[3413,4601,4494],{}," (тип ",[3413,4604,4605],{},"String","). Всі інші атрибути (",[3413,4608,4497],{},[3413,4610,4511],{},[3413,4612,4500],{},") є довільними та необов'язковими для схеми:",[3756,4615,4616,4656],{},[4617,4618,4619],"thead",{},[4620,4621,4622,4634,4641,4649],"tr",{},[4623,4624,4626,4627,4630],"th",{"align":4625},"left","UserId (PK) ",[4628,4629],"br",{},[4631,4632,4633],"sub",{},"тип: String (S)",[4623,4635,4636,4637,4639],{"align":4625},"Name ",[4628,4638],{},[4631,4640,4633],{},[4623,4642,4643,4644,4646],{"align":4625},"Age ",[4628,4645],{},[4631,4647,4648],{},"тип: Number (N)",[4623,4650,4651,4652,4654],{"align":4625},"Email ",[4628,4653],{},[4631,4655,4633],{},[4657,4658,4659,4679,4698],"tbody",{},[4620,4660,4661,4667,4670,4672],{},[4662,4663,4664],"td",{"align":4625},[3413,4665,4666],{},"usr-001",[4662,4668,4669],{"align":4625},"Олена",[4662,4671,4356],{"align":4625},[4662,4673,4674],{"align":4625},[4675,4676,4678],"a",{"href":4677},"mailto:elena@example.com","elena@example.com",[4620,4680,4681,4686,4689,4692],{},[4662,4682,4683],{"align":4625},[3413,4684,4685],{},"usr-002",[4662,4687,4688],{"align":4625},"Іван",[4662,4690,4691],{"align":4625},"32",[4662,4693,4694],{"align":4625},[4675,4695,4697],{"href":4696},"mailto:ivan@example.com","ivan@example.com",[4620,4699,4700,4705,4708,4711],{},[4662,4701,4702],{"align":4625},[3413,4703,4704],{},"usr-003",[4662,4706,4707],{"align":4625},"Марія",[4662,4709,4710],{"align":4625},"22",[4662,4712,4713],{"align":4625},[4675,4714,4716],{"href":4715},"mailto:maria@example.com","maria@example.com",[4589,4718,4720,4721,4724],{"id":4719},"приклад-2-таблиця-devices-метадані-iot-пристроїв","Приклад 2: Таблиця ",[3413,4722,4723],{},"Devices"," (Метадані IoT-пристроїв)",[3353,4726,4727,4728,4602,4731,4733],{},"У цьому сценарії первинним ключем є ",[3413,4729,4730],{},"DeviceId",[3413,4732,4605],{},"), який ідентифікує конкретний фізичний пристрій. Кожен пристрій має свій набір налаштувань та метаданих:",[3756,4735,4736,4776],{},[4617,4737,4738],{},[4620,4739,4740,4747,4754,4761,4768],{},[4623,4741,4742,4743,4745],{"align":4625},"DeviceId (PK) ",[4628,4744],{},[4631,4746,4633],{},[4623,4748,4749,4750,4752],{"align":4625},"DeviceType ",[4628,4751],{},[4631,4753,4633],{},[4623,4755,4756,4757,4759],{"align":4625},"FirmwareVersion ",[4628,4758],{},[4631,4760,4633],{},[4623,4762,4763,4764,4766],{"align":4625},"Status ",[4628,4765],{},[4631,4767,4633],{},[4623,4769,4770,4771,4773],{"align":4625},"Metadata ",[4628,4772],{},[4631,4774,4775],{},"тип: Map (M)",[4657,4777,4778,4801,4824],{},[4620,4779,4780,4785,4788,4793,4796],{},[4662,4781,4782],{"align":4625},[3413,4783,4784],{},"dev-sensor-091",[4662,4786,4787],{"align":4625},"Temperature",[4662,4789,4790],{"align":4625},[3413,4791,4792],{},"v2.4.1",[4662,4794,4795],{"align":4625},"ACTIVE",[4662,4797,4798],{"align":4625},[3413,4799,4800],{},"{\"Location\": \"ServerRoom-A\", \"IntervalSec\": 10}",[4620,4802,4803,4808,4811,4816,4819],{},[4662,4804,4805],{"align":4625},[3413,4806,4807],{},"dev-camera-104",[4662,4809,4810],{"align":4625},"IP-Camera",[4662,4812,4813],{"align":4625},[3413,4814,4815],{},"v1.0.8",[4662,4817,4818],{"align":4625},"OFFLINE",[4662,4820,4821],{"align":4625},[3413,4822,4823],{},"{\"Location\": \"MainEntrance\", \"Resolution\": \"4K\"}",[4620,4825,4826,4831,4834,4839,4841],{},[4662,4827,4828],{"align":4625},[3413,4829,4830],{},"dev-gate-002",[4662,4832,4833],{"align":4625},"SmartGate",[4662,4835,4836],{"align":4625},[3413,4837,4838],{},"v3.1.0",[4662,4840,4795],{"align":4625},[4662,4842,4843],{"align":4625},[3413,4844,4845],{},"{\"Location\": \"GateEast\"}",[3353,4847,4848],{},[3363,4849,4850],{},"Основні особливості роботи з простим ключем:",[4488,4852,4853,4865,4879],{},[3377,4854,4855,4858,4859,4861,4862,4864],{},[3363,4856,4857],{},"Унікальність:"," Кожен запис (елемент) у таблиці повинен мати унікальне значення ",[3413,4860,4494],{},". Запис елемента з наявним ",[3413,4863,4494],{}," перезапише старий елемент.",[3377,4866,4867,4870,4871,4874,4875,4878],{},[3363,4868,4869],{},"Швидкий доступ:"," Доступ до даних здійснюється виключно за точним значенням Partition Key (наприклад, ",[3413,4872,4873],{},"GetItem"," за ",[3413,4876,4877],{},"UserId = \"usr-001\"","). DynamoDB обчислює хеш від ключа та миттєво знаходить потрібну партицію.",[3377,4880,4881,4884,4885,4888,4889,4892],{},[3363,4882,4883],{},"Обмеження вибірок:"," Неможливо зробити запит (",[3413,4886,4887],{},"Query",") на кшталт \"показати всіх користувачів, які старші за 25 років\". Подібна операція без додаткових індексів вимагає сканування всієї таблиці (",[3413,4890,4891],{},"Scan","), що є дорогою операцією та створює велике навантаження.",[3353,4894,4895],{},"Нижче показано, як DynamoDB розподіляє ці дані на фізичному рівні:",[3403,4897,4898],{},[3406,4899,4901],{"className":3408,"code":4900,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Partition Key → фізичний розподіл даних\"\n\nrectangle \"Таблиця: Users\" as TBL #fef3c7\n\ntogether {\n    card \"Item\\nUserId: usr-001\\nName: Олена\" as I1 #bbf7d0\n    card \"Item\\nUserId: usr-002\\nName: Іван\" as I2 #bbf7d0\n    card \"Item\\nUserId: usr-003\\nName: Марія\" as I3 #bbf7d0\n}\n\nTBL --> I1\nTBL --> I2\nTBL --> I3\n\nrectangle \"Hash Function\\nhash(\\\"usr-001\\\") → 0x3A2F...\\nhash(\\\"usr-002\\\") → 0x8B1C...\\nhash(\\\"usr-003\\\") → 0x1D47...\" as HASH #e0e7ff\n\nI1 --> HASH\nI2 --> HASH\nI3 --> HASH\n\npackage \"Фізичні партиції\" as PARTITIONS {\n    node \"Partition A\\n[0x0000..0x5FFF]\" as PA #d1fae5\n    node \"Partition B\\n[0x6000..0xAFFF]\" as PB #d1fae5\n    node \"Partition C\\n[0xB000..0xFFFF]\" as PC #d1fae5\n}\n\nHASH --> PA : \"usr-001, usr-003\\n(хеш попав у діапазон A, C)\"\nHASH --> PB : \"usr-002\\n(хеш у діапазоні B)\"\n\nnote bottom of PA\n  Кожна партиція —\n  окремий SSD-диск\n  на окремому сервері AWS.\n  Максимум 10 GB даних\n  та 3000 RCU \u002F 1000 WCU.\nend note\n\n@enduml\n",[3413,4902,4903,4907,4911,4915,4919,4924,4928,4933,4937,4942,4947,4952,4957,4961,4965,4970,4975,4980,4984,4989,4993,4998,5003,5008,5012,5017,5022,5027,5032,5036,5040,5045,5050,5054,5059,5064,5069,5074,5079,5084,5089,5093],{"__ignoreMap":3411},[3416,4904,4905],{"class":3418,"line":3419},[3416,4906,3422],{},[3416,4908,4909],{"class":3418,"line":3425},[3416,4910,3428],{},[3416,4912,4913],{"class":3418,"line":3431},[3416,4914,3434],{},[3416,4916,4917],{"class":3418,"line":3437},[3416,4918,3441],{"emptyLinePlaceholder":3440},[3416,4920,4921],{"class":3418,"line":3444},[3416,4922,4923],{},"title \"Partition Key → фізичний розподіл даних\"\n",[3416,4925,4926],{"class":3418,"line":3450},[3416,4927,3441],{"emptyLinePlaceholder":3440},[3416,4929,4930],{"class":3418,"line":3456},[3416,4931,4932],{},"rectangle \"Таблиця: Users\" as TBL #fef3c7\n",[3416,4934,4935],{"class":3418,"line":3462},[3416,4936,3441],{"emptyLinePlaceholder":3440},[3416,4938,4939],{"class":3418,"line":3468},[3416,4940,4941],{},"together {\n",[3416,4943,4944],{"class":3418,"line":3474},[3416,4945,4946],{},"    card \"Item\\nUserId: usr-001\\nName: Олена\" as I1 #bbf7d0\n",[3416,4948,4949],{"class":3418,"line":3480},[3416,4950,4951],{},"    card \"Item\\nUserId: usr-002\\nName: Іван\" as I2 #bbf7d0\n",[3416,4953,4954],{"class":3418,"line":3486},[3416,4955,4956],{},"    card \"Item\\nUserId: usr-003\\nName: Марія\" as I3 #bbf7d0\n",[3416,4958,4959],{"class":3418,"line":3492},[3416,4960,3507],{},[3416,4962,4963],{"class":3418,"line":3498},[3416,4964,3441],{"emptyLinePlaceholder":3440},[3416,4966,4967],{"class":3418,"line":3504},[3416,4968,4969],{},"TBL --> I1\n",[3416,4971,4972],{"class":3418,"line":3510},[3416,4973,4974],{},"TBL --> I2\n",[3416,4976,4977],{"class":3418,"line":3515},[3416,4978,4979],{},"TBL --> I3\n",[3416,4981,4982],{"class":3418,"line":3521},[3416,4983,3441],{"emptyLinePlaceholder":3440},[3416,4985,4986],{"class":3418,"line":3527},[3416,4987,4988],{},"rectangle \"Hash Function\\nhash(\\\"usr-001\\\") → 0x3A2F...\\nhash(\\\"usr-002\\\") → 0x8B1C...\\nhash(\\\"usr-003\\\") → 0x1D47...\" as HASH #e0e7ff\n",[3416,4990,4991],{"class":3418,"line":3533},[3416,4992,3441],{"emptyLinePlaceholder":3440},[3416,4994,4995],{"class":3418,"line":3539},[3416,4996,4997],{},"I1 --> HASH\n",[3416,4999,5000],{"class":3418,"line":3545},[3416,5001,5002],{},"I2 --> HASH\n",[3416,5004,5005],{"class":3418,"line":3551},[3416,5006,5007],{},"I3 --> HASH\n",[3416,5009,5010],{"class":3418,"line":3557},[3416,5011,3441],{"emptyLinePlaceholder":3440},[3416,5013,5014],{"class":3418,"line":3563},[3416,5015,5016],{},"package \"Фізичні партиції\" as PARTITIONS {\n",[3416,5018,5019],{"class":3418,"line":3569},[3416,5020,5021],{},"    node \"Partition A\\n[0x0000..0x5FFF]\" as PA #d1fae5\n",[3416,5023,5024],{"class":3418,"line":3574},[3416,5025,5026],{},"    node \"Partition B\\n[0x6000..0xAFFF]\" as PB #d1fae5\n",[3416,5028,5029],{"class":3418,"line":3579},[3416,5030,5031],{},"    node \"Partition C\\n[0xB000..0xFFFF]\" as PC #d1fae5\n",[3416,5033,5034],{"class":3418,"line":3584},[3416,5035,3507],{},[3416,5037,5038],{"class":3418,"line":3590},[3416,5039,3441],{"emptyLinePlaceholder":3440},[3416,5041,5042],{"class":3418,"line":3596},[3416,5043,5044],{},"HASH --> PA : \"usr-001, usr-003\\n(хеш попав у діапазон A, C)\"\n",[3416,5046,5047],{"class":3418,"line":3602},[3416,5048,5049],{},"HASH --> PB : \"usr-002\\n(хеш у діапазоні B)\"\n",[3416,5051,5052],{"class":3418,"line":3608},[3416,5053,3441],{"emptyLinePlaceholder":3440},[3416,5055,5056],{"class":3418,"line":3614},[3416,5057,5058],{},"note bottom of PA\n",[3416,5060,5061],{"class":3418,"line":3620},[3416,5062,5063],{},"  Кожна партиція —\n",[3416,5065,5066],{"class":3418,"line":3626},[3416,5067,5068],{},"  окремий SSD-диск\n",[3416,5070,5071],{"class":3418,"line":3631},[3416,5072,5073],{},"  на окремому сервері AWS.\n",[3416,5075,5076],{"class":3418,"line":3636},[3416,5077,5078],{},"  Максимум 10 GB даних\n",[3416,5080,5081],{"class":3418,"line":3641},[3416,5082,5083],{},"  та 3000 RCU \u002F 1000 WCU.\n",[3416,5085,5086],{"class":3418,"line":3647},[3416,5087,5088],{},"end note\n",[3416,5090,5091],{"class":3418,"line":3653},[3416,5092,3441],{"emptyLinePlaceholder":3440},[3416,5094,5095],{"class":3418,"line":3659},[3416,5096,3718],{},[3353,5098,5099,5102,5103,5106],{},[3363,5100,5101],{},"Критична вимога до Partition Key: висока кардинальність."," Якщо всі або більшість елементів мають однакове значення Partition Key, всі вони потраплять на одну фізичну партицію. Ця ситуація називається ",[3363,5104,5105],{},"hot partition"," (гаряча партиція) і є найчастішою причиною деградації продуктивності у DynamoDB. Детально розглянемо це у розділі Best Practices.",[3353,5108,5109],{},[3363,5110,5111],{},"Приклади хороших Partition Key:",[4488,5113,5114,5119,5125],{},[3377,5115,5116,5118],{},[3413,5117,4494],{}," (UUID) — висока кардинальність, рівномірний розподіл",[3377,5120,5121,5124],{},[3413,5122,5123],{},"OrderId"," (UUID або timestamp-based) — унікальний для кожного запису",[3377,5126,5127,5129],{},[3413,5128,4730],{}," (для IoT) — кожен пристрій має унікальний ідентифікатор",[3353,5131,5132],{},[3363,5133,5134],{},"Приклади поганих Partition Key:",[4488,5136,5137,5143,5149],{},[3377,5138,5139,5142],{},[3413,5140,5141],{},"Country"," — лише ~200 унікальних значень, більшість запитів сконцентровано на одній-двох країнах",[3377,5144,5145,5148],{},[3413,5146,5147],{},"Status"," (\"active\", \"inactive\") — лише 2 значення, \"active\" буде hot partition",[3377,5150,5151,5154],{},[3413,5152,5153],{},"Date"," (тільки дата без часу) — всі записи за один день на одній партиції",[3727,5156,5158],{"id":5157},"composite-primary-key-partition-key-sort-key","Composite Primary Key: Partition Key + Sort Key",[3353,5160,5161,5164,5165,5167,5168,5171,5172,5175,5176,5179],{},[3363,5162,5163],{},"Composite Primary Key"," (або Range Key) складається з двох атрибутів: ",[3363,5166,4573],{}," та ",[3363,5169,5170],{},"Sort Key",". Ця комбінація надає DynamoDB принципово нові можливості для запитів. Partition Key визначає, на якій фізичній партиції зберігатиметься елемент, а Sort Key визначає ",[3363,5173,5174],{},"порядок зберігання"," елементів ",[4091,5177,5178],{},"всередині"," однієї партиції.",[3353,5181,5182,5183,5186],{},"Ключова відмінність від простого первинного ключа: при Composite Primary Key кілька елементів ",[3363,5184,5185],{},"можуть мати однакове значення Partition Key"," — це цілком допустимо і є основним патерном проектування. Унікальність елемента визначається парою (Partition Key, Sort Key).",[4584,5188,5190],{"id":5189},"візуалізація-composite-primary-key","Візуалізація Composite Primary Key",[4589,5192,4592,5194,5197],{"id":5193},"приклад-1-таблиця-userorders-замовлення-користувачів",[3413,5195,5196],{},"UserOrders"," (Замовлення користувачів)",[3353,5199,5200,5201,5203,5204,5207,5208,5210,5211,5213],{},"Тут ",[3413,5202,4494],{}," є Partition Key, а ",[3413,5205,5206],{},"OrderDate#OrderId"," — Sort Key. Обидва атрибути мають тип ",[3413,5209,4605],{},". Унікальність запису гарантується виключно комбінацією обох значень. Зверніть увагу, що замовлення для ",[3413,5212,4666],{}," відсортовані хронологічно:",[3756,5215,5216,5246],{},[4617,5217,5218],{},[4620,5219,5220,5226,5233,5240],{},[4623,5221,4626,5222,5224],{"align":4625},[4628,5223],{},[4631,5225,4633],{},[4623,5227,5228,5229,5231],{"align":4625},"OrderDate#OrderId (SK) ",[4628,5230],{},[4631,5232,4633],{},[4623,5234,5235,5236,5238],{"align":4625},"Amount ",[4628,5237],{},[4631,5239,4648],{},[4623,5241,4763,5242,5244],{"align":4625},[4628,5243],{},[4631,5245,4633],{},[4657,5247,5248,5265,5282,5299,5315],{},[4620,5249,5250,5254,5259,5262],{},[4662,5251,5252],{"align":4625},[3413,5253,4666],{},[4662,5255,5256],{"align":4625},[3413,5257,5258],{},"2025-01-15T10:00:00#ord-A",[4662,5260,5261],{"align":4625},"150.00",[4662,5263,5264],{"align":4625},"DELIVERED",[4620,5266,5267,5271,5276,5279],{},[4662,5268,5269],{"align":4625},[3413,5270,4666],{},[4662,5272,5273],{"align":4625},[3413,5274,5275],{},"2025-03-20T14:30:00#ord-B",[4662,5277,5278],{"align":4625},"89.99",[4662,5280,5281],{"align":4625},"SHIPPED",[4620,5283,5284,5288,5293,5296],{},[4662,5285,5286],{"align":4625},[3413,5287,4666],{},[4662,5289,5290],{"align":4625},[3413,5291,5292],{},"2025-06-01T09:15:00#ord-C",[4662,5294,5295],{"align":4625},"320.50",[4662,5297,5298],{"align":4625},"PENDING",[4620,5300,5301,5305,5310,5313],{},[4662,5302,5303],{"align":4625},[3413,5304,4685],{},[4662,5306,5307],{"align":4625},[3413,5308,5309],{},"2025-02-10T08:00:00#ord-D",[4662,5311,5312],{"align":4625},"45.00",[4662,5314,5264],{"align":4625},[4620,5316,5317,5321,5326,5329],{},[4662,5318,5319],{"align":4625},[3413,5320,4685],{},[4662,5322,5323],{"align":4625},[3413,5324,5325],{},"2025-05-05T16:45:00#ord-E",[4662,5327,5328],{"align":4625},"210.00",[4662,5330,5264],{"align":4625},[4589,5332,4720,5334,5337],{"id":5333},"приклад-2-таблиця-chatmessages-повідомлення-в-чатах",[3413,5335,5336],{},"ChatMessages"," (Повідомлення в чатах)",[3353,5339,5200,5340,5343,5344,5347],{},[3413,5341,5342],{},"ConversationId"," виступає як Partition Key, групуючи всі повідомлення конкретної розмови на одній партиції. ",[3413,5345,5346],{},"Timestamp#MessageId"," виступає як Sort Key, забезпечуючи хронологічний порядок та унікальність повідомлень (оскільки кілька повідомлень можуть бути відправлені в одну секунду):",[3756,5349,5350,5382],{},[4617,5351,5352],{},[4620,5353,5354,5361,5368,5375],{},[4623,5355,5356,5357,5359],{"align":4625},"ConversationId (PK) ",[4628,5358],{},[4631,5360,4633],{},[4623,5362,5363,5364,5366],{"align":4625},"Timestamp#MessageId (SK) ",[4628,5365],{},[4631,5367,4633],{},[4623,5369,5370,5371,5373],{"align":4625},"SenderId ",[4628,5372],{},[4631,5374,4633],{},[4623,5376,5377,5378,5380],{"align":4625},"MessageText ",[4628,5379],{},[4631,5381,4633],{},[4657,5383,5384,5403,5421,5439],{},[4620,5385,5386,5391,5396,5400],{},[4662,5387,5388],{"align":4625},[3413,5389,5390],{},"room-402",[4662,5392,5393],{"align":4625},[3413,5394,5395],{},"2025-06-03T10:00:15Z#msg-001",[4662,5397,5398],{"align":4625},[3413,5399,4666],{},[4662,5401,5402],{"align":4625},"Привіт всім!",[4620,5404,5405,5409,5414,5418],{},[4662,5406,5407],{"align":4625},[3413,5408,5390],{},[4662,5410,5411],{"align":4625},[3413,5412,5413],{},"2025-06-03T10:00:45Z#msg-002",[4662,5415,5416],{"align":4625},[3413,5417,4685],{},[4662,5419,5420],{"align":4625},"Привіт, Олено! Як справи?",[4620,5422,5423,5427,5432,5436],{},[4662,5424,5425],{"align":4625},[3413,5426,5390],{},[4662,5428,5429],{"align":4625},[3413,5430,5431],{},"2025-06-03T10:01:10Z#msg-003",[4662,5433,5434],{"align":4625},[3413,5435,4666],{},[4662,5437,5438],{"align":4625},"Все чудово, працюю над DynamoDB.",[4620,5440,5441,5446,5451,5455],{},[4662,5442,5443],{"align":4625},[3413,5444,5445],{},"room-511",[4662,5447,5448],{"align":4625},[3413,5449,5450],{},"2025-06-03T11:30:00Z#msg-004",[4662,5452,5453],{"align":4625},[3413,5454,4704],{},[4662,5456,5457],{"align":4625},"Коли почнемо зустріч?",[4589,5459,5461,5462,5465],{"id":5460},"приклад-3-таблиця-projecttasks-задачі-проектів-з-ієрархічним-sk","Приклад 3: Таблиця ",[3413,5463,5464],{},"ProjectTasks"," (Задачі проектів з ієрархічним SK)",[3353,5467,5468,5469,5472,5473,5476],{},"У великих системах Composite PK використовується для організації зв'язків типу \"один-до-багатьох\" та ієрархій. Розглянемо таблицю проектних задач, де Partition Key — це ",[3413,5470,5471],{},"ProjectId",", а Sort Key — це ",[3413,5474,5475],{},"Priority#TaskId",". Такий SK дозволяє не просто ідентифікувати задачу, але й сортувати задачі за пріоритетом у межах проекту:",[3756,5478,5479,5518],{},[4617,5480,5481],{},[4620,5482,5483,5490,5497,5504,5511],{},[4623,5484,5485,5486,5488],{"align":4625},"ProjectId (PK) ",[4628,5487],{},[4631,5489,4633],{},[4623,5491,5492,5493,5495],{"align":4625},"Priority#TaskId (SK) ",[4628,5494],{},[4631,5496,4633],{},[4623,5498,5499,5500,5502],{"align":4625},"TaskTitle ",[4628,5501],{},[4631,5503,4633],{},[4623,5505,5506,5507,5509],{"align":4625},"AssigneeId ",[4628,5508],{},[4631,5510,4633],{},[4623,5512,5513,5514,5516],{"align":4625},"DueDate ",[4628,5515],{},[4631,5517,4633],{},[4657,5519,5520,5544,5567,5590],{},[4620,5521,5522,5527,5532,5535,5539],{},[4662,5523,5524],{"align":4625},[3413,5525,5526],{},"proj-alpha",[4662,5528,5529],{"align":4625},[3413,5530,5531],{},"1-CRITICAL#task-102",[4662,5533,5534],{"align":4625},"Налаштувати AWS Credentials",[4662,5536,5537],{"align":4625},[3413,5538,4666],{},[4662,5540,5541],{"align":4625},[3413,5542,5543],{},"2025-06-05",[4620,5545,5546,5550,5555,5558,5562],{},[4662,5547,5548],{"align":4625},[3413,5549,5526],{},[4662,5551,5552],{"align":4625},[3413,5553,5554],{},"2-HIGH#task-105",[4662,5556,5557],{"align":4625},"Створити схему DynamoDB",[4662,5559,5560],{"align":4625},[3413,5561,4666],{},[4662,5563,5564],{"align":4625},[3413,5565,5566],{},"2025-06-08",[4620,5568,5569,5573,5578,5581,5585],{},[4662,5570,5571],{"align":4625},[3413,5572,5526],{},[4662,5574,5575],{"align":4625},[3413,5576,5577],{},"3-NORMAL#task-101",[4662,5579,5580],{"align":4625},"Написати README.md",[4662,5582,5583],{"align":4625},[3413,5584,4685],{},[4662,5586,5587],{"align":4625},[3413,5588,5589],{},"2025-06-12",[4620,5591,5592,5597,5602,5605,5609],{},[4662,5593,5594],{"align":4625},[3413,5595,5596],{},"proj-beta",[4662,5598,5599],{"align":4625},[3413,5600,5601],{},"1-CRITICAL#task-201",[4662,5603,5604],{"align":4625},"Виправити баг з авторизацією",[4662,5606,5607],{"align":4625},[3413,5608,4704],{},[4662,5610,5611],{"align":4625},[3413,5612,5613],{},"2025-06-04",[3353,5615,5616],{},[3363,5617,5618],{},"Основні особливості роботи з композитним ключем:",[4488,5620,5621,5630,5646],{},[3377,5622,5623,5626,5627,5629],{},[3363,5624,5625],{},"Групування та сортування:"," Записи з однаковим Partition Key (наприклад, ",[3413,5628,4666],{},") зберігаються на одній фізичній партиції та відсортовані за значенням Sort Key.",[3377,5631,5632,5635,5636,5638,5639,5641,5642,5645],{},[3363,5633,5634],{},"Ефективний діапазонний пошук:"," Завдяки сортуванню ви можете використовувати операцію ",[3413,5637,4887],{}," для вибірки всіх замовлень користувача ",[3413,5640,4666],{}," за певний період (наприклад, за допомогою оператора ",[3413,5643,5644],{},"BETWEEN"," для SK).",[3377,5647,5648,5651,5652,4039,5655,5658],{},[3363,5649,5650],{},"Складений Sort Key:"," Використання патерну ",[3413,5653,5654],{},"Date#Id",[3413,5656,5657],{},"Category#Status"," у Sort Key дозволяє будувати гнучкі та складні умови для пошуку в межах однієї партиції.",[3353,5660,5661],{},"Схема нижче демонструє, як це виглядає на фізичному та логічному рівнях:",[3403,5663,5664],{},[3406,5665,5667],{"className":3408,"code":5666,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Composite Primary Key: Partition Key + Sort Key\"\n\npackage \"Таблиця: UserOrders\" as TBL #fef3c7 {\n    rectangle \"Partition: UserId = \\\"usr-001\\\"\" as P1 #dbeafe {\n        card \"SK: \\\"2025-01-15T10:00:00\\\"\\nOrderId: ord-A\\nAmount: 150.00\" as I11 #bbf7d0\n        card \"SK: \\\"2025-03-20T14:30:00\\\"\\nOrderId: ord-B\\nAmount: 89.99\" as I12 #bbf7d0\n        card \"SK: \\\"2025-06-01T09:15:00\\\"\\nOrderId: ord-C\\nAmount: 320.50\" as I13 #bbf7d0\n\n        note right of I11\n          Всередині партиції елементи\n          зберігаються ВІДСОРТОВАНИМИ\n          за Sort Key (B-tree індекс).\n          Пошук по діапазону — O(log n)\n        end note\n    }\n\n    rectangle \"Partition: UserId = \\\"usr-002\\\"\" as P2 #dbeafe {\n        card \"SK: \\\"2025-02-10T08:00:00\\\"\\nOrderId: ord-D\\nAmount: 45.00\" as I21 #bbf7d0\n        card \"SK: \\\"2025-05-05T16:45:00\\\"\\nOrderId: ord-E\\nAmount: 210.00\" as I22 #bbf7d0\n    }\n}\n\nnote bottom of TBL\n  Query: UserId = \"usr-001\" AND OrderDate BETWEEN \"2025-01-01\" AND \"2025-04-01\"\n  → повертає: ord-A, ord-B (2 елементи з однієї партиції, без повного сканування)\nend note\n\n@enduml\n",[3413,5668,5669,5673,5677,5681,5685,5690,5694,5699,5704,5709,5714,5719,5723,5728,5733,5738,5743,5748,5752,5756,5760,5765,5770,5775,5779,5783,5787,5792,5797,5802,5806,5810],{"__ignoreMap":3411},[3416,5670,5671],{"class":3418,"line":3419},[3416,5672,3422],{},[3416,5674,5675],{"class":3418,"line":3425},[3416,5676,3428],{},[3416,5678,5679],{"class":3418,"line":3431},[3416,5680,3434],{},[3416,5682,5683],{"class":3418,"line":3437},[3416,5684,3441],{"emptyLinePlaceholder":3440},[3416,5686,5687],{"class":3418,"line":3444},[3416,5688,5689],{},"title \"Composite Primary Key: Partition Key + Sort Key\"\n",[3416,5691,5692],{"class":3418,"line":3450},[3416,5693,3441],{"emptyLinePlaceholder":3440},[3416,5695,5696],{"class":3418,"line":3456},[3416,5697,5698],{},"package \"Таблиця: UserOrders\" as TBL #fef3c7 {\n",[3416,5700,5701],{"class":3418,"line":3462},[3416,5702,5703],{},"    rectangle \"Partition: UserId = \\\"usr-001\\\"\" as P1 #dbeafe {\n",[3416,5705,5706],{"class":3418,"line":3468},[3416,5707,5708],{},"        card \"SK: \\\"2025-01-15T10:00:00\\\"\\nOrderId: ord-A\\nAmount: 150.00\" as I11 #bbf7d0\n",[3416,5710,5711],{"class":3418,"line":3474},[3416,5712,5713],{},"        card \"SK: \\\"2025-03-20T14:30:00\\\"\\nOrderId: ord-B\\nAmount: 89.99\" as I12 #bbf7d0\n",[3416,5715,5716],{"class":3418,"line":3480},[3416,5717,5718],{},"        card \"SK: \\\"2025-06-01T09:15:00\\\"\\nOrderId: ord-C\\nAmount: 320.50\" as I13 #bbf7d0\n",[3416,5720,5721],{"class":3418,"line":3486},[3416,5722,3441],{"emptyLinePlaceholder":3440},[3416,5724,5725],{"class":3418,"line":3492},[3416,5726,5727],{},"        note right of I11\n",[3416,5729,5730],{"class":3418,"line":3498},[3416,5731,5732],{},"          Всередині партиції елементи\n",[3416,5734,5735],{"class":3418,"line":3504},[3416,5736,5737],{},"          зберігаються ВІДСОРТОВАНИМИ\n",[3416,5739,5740],{"class":3418,"line":3510},[3416,5741,5742],{},"          за Sort Key (B-tree індекс).\n",[3416,5744,5745],{"class":3418,"line":3515},[3416,5746,5747],{},"          Пошук по діапазону — O(log n)\n",[3416,5749,5750],{"class":3418,"line":3521},[3416,5751,4162],{},[3416,5753,5754],{"class":3418,"line":3527},[3416,5755,4167],{},[3416,5757,5758],{"class":3418,"line":3533},[3416,5759,3441],{"emptyLinePlaceholder":3440},[3416,5761,5762],{"class":3418,"line":3539},[3416,5763,5764],{},"    rectangle \"Partition: UserId = \\\"usr-002\\\"\" as P2 #dbeafe {\n",[3416,5766,5767],{"class":3418,"line":3545},[3416,5768,5769],{},"        card \"SK: \\\"2025-02-10T08:00:00\\\"\\nOrderId: ord-D\\nAmount: 45.00\" as I21 #bbf7d0\n",[3416,5771,5772],{"class":3418,"line":3551},[3416,5773,5774],{},"        card \"SK: \\\"2025-05-05T16:45:00\\\"\\nOrderId: ord-E\\nAmount: 210.00\" as I22 #bbf7d0\n",[3416,5776,5777],{"class":3418,"line":3557},[3416,5778,4167],{},[3416,5780,5781],{"class":3418,"line":3563},[3416,5782,3507],{},[3416,5784,5785],{"class":3418,"line":3569},[3416,5786,3441],{"emptyLinePlaceholder":3440},[3416,5788,5789],{"class":3418,"line":3574},[3416,5790,5791],{},"note bottom of TBL\n",[3416,5793,5794],{"class":3418,"line":3579},[3416,5795,5796],{},"  Query: UserId = \"usr-001\" AND OrderDate BETWEEN \"2025-01-01\" AND \"2025-04-01\"\n",[3416,5798,5799],{"class":3418,"line":3584},[3416,5800,5801],{},"  → повертає: ord-A, ord-B (2 елементи з однієї партиції, без повного сканування)\n",[3416,5803,5804],{"class":3418,"line":3590},[3416,5805,5088],{},[3416,5807,5808],{"class":3418,"line":3596},[3416,5809,3441],{"emptyLinePlaceholder":3440},[3416,5811,5812],{"class":3418,"line":3602},[3416,5813,3718],{},[3353,5815,5816,5819,5820,5822],{},[3363,5817,5818],{},"Можливості запитів із Sort Key."," Наявність Sort Key відкриває можливість ефективних ",[3363,5821,4887],{},"-операцій із умовою на значення Sort Key. DynamoDB підтримує такі оператори для Sort Key у межах однієї партиції:",[3756,5824,5825,5838],{},[4617,5826,5827],{},[4620,5828,5829,5832,5835],{},[4623,5830,5831],{},"Оператор",[4623,5833,5834],{},"Значення",[4623,5836,5837],{},"Приклад",[4657,5839,5840,5855,5873,5891,5905],{},[4620,5841,5842,5847,5850],{},[4662,5843,5844],{},[3413,5845,5846],{},"=",[4662,5848,5849],{},"Точне значення",[4662,5851,5852],{},[3413,5853,5854],{},"OrderDate = \"2025-06-01T10:00:00\"",[4620,5856,5857,5865,5868],{},[4662,5858,5859,4384,5862],{},[3413,5860,5861],{},"\u003C",[3413,5863,5864],{},"\u003C=",[4662,5866,5867],{},"Менше або рівне",[4662,5869,5870],{},[3413,5871,5872],{},"Score \u003C= 100",[4620,5874,5875,5883,5886],{},[4662,5876,5877,4384,5880],{},[3413,5878,5879],{},">",[3413,5881,5882],{},">=",[4662,5884,5885],{},"Більше або рівне",[4662,5887,5888],{},[3413,5889,5890],{},"CreatedAt >= \"2025-01-01\"",[4620,5892,5893,5897,5900],{},[4662,5894,5895],{},[3413,5896,5644],{},[4662,5898,5899],{},"Включний діапазон",[4662,5901,5902],{},[3413,5903,5904],{},"Score BETWEEN 50 AND 100",[4620,5906,5907,5912,5915],{},[4662,5908,5909],{},[3413,5910,5911],{},"begins_with",[4662,5913,5914],{},"Починається з префіксу",[4662,5916,5917],{},[3413,5918,5919],{},"OrderId begins_with \"2025-06\"",[3396,5921,5922,5924,5925,5927,5928,5931],{},[3363,5923,4093],{}," оператор ",[3413,5926,5911],{}," та всі порівняльні оператори для Sort Key працюють тільки всередині однієї партиції. Неможливо знайти всі елементи з Sort Key, що \"починається з X\" ",[3363,5929,5930],{},"по всій таблиці"," без сканування. Для таких запитів необхідні Global Secondary Index (розглянемо у наступному розділі).",[3353,5933,5934,5937],{},[3363,5935,5936],{},"Паттерни проектування з Composite Primary Key."," Розуміння цього патерну є ключовим для ефективного використання DynamoDB. Partition Key групує пов'язані елементи в одну партицію, Sort Key впорядковує їх для ефективного пошуку:",[3403,5939,5940],{},[3406,5941,5943],{"className":3408,"code":5942,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Патерни Composite Primary Key у реальних доменах\"\n\npackage \"Приклад 1: Замовлення користувача\" as EX1 #fef3c7 {\n    note as N1\n      PK: UserId | SK: OrderDate#OrderId\n      ─────────────────────────────────────\n      usr-001 | 2025-01-15#ord-A → Order A\n      usr-001 | 2025-03-20#ord-B → Order B\n      usr-001 | 2025-06-01#ord-C → Order C\n      usr-002 | 2025-02-10#ord-D → Order D\n      ─────────────────────────────────────\n      Query: \"всі замовлення usr-001 за Q1 2025\"\n      → PK=\"usr-001\", SK BETWEEN \"2025-01\" AND \"2025-04\"\n    end note\n}\n\npackage \"Приклад 2: Повідомлення чату\" as EX2 #dbeafe {\n    note as N2\n      PK: ConversationId | SK: Timestamp#MessageId\n      ─────────────────────────────────────────────\n      conv-001 | 2025-06-01T10:00#msg-1 → \"Привіт!\"\n      conv-001 | 2025-06-01T10:01#msg-2 → \"Як справи?\"\n      conv-001 | 2025-06-01T10:02#msg-3 → \"Чудово!\"\n      conv-002 | 2025-06-01T11:00#msg-4 → \"Зустріч?\"\n      ─────────────────────────────────────────────\n      Query: \"останні 20 повідомлень конversation-001\"\n      → PK=\"conv-001\", SK DESC, LIMIT 20\n    end note\n}\n\npackage \"Приклад 3: IoT-дані сенсора\" as EX3 #d1fae5 {\n    note as N3\n      PK: DeviceId | SK: Timestamp\n      ─────────────────────────────────────\n      sensor-A | 2025-06-01T00:00:00 → 23.5°C\n      sensor-A | 2025-06-01T00:05:00 → 23.7°C\n      sensor-A | 2025-06-01T00:10:00 → 24.1°C\n      sensor-B | 2025-06-01T00:00:00 → 18.2°C\n      ─────────────────────────────────────\n      Query: \"показання sensor-A за останню годину\"\n      → PK=\"sensor-A\", SK >= \"2025-06-01T09:00:00\"\n    end note\n}\n\n@enduml\n",[3413,5944,5945,5949,5953,5957,5961,5966,5970,5975,5980,5985,5990,5995,6000,6005,6010,6014,6019,6024,6028,6032,6036,6041,6046,6051,6056,6061,6066,6071,6076,6080,6085,6090,6094,6098,6102,6107,6112,6117,6121,6126,6131,6136,6141,6145,6150,6155,6159,6163,6167],{"__ignoreMap":3411},[3416,5946,5947],{"class":3418,"line":3419},[3416,5948,3422],{},[3416,5950,5951],{"class":3418,"line":3425},[3416,5952,3428],{},[3416,5954,5955],{"class":3418,"line":3431},[3416,5956,3434],{},[3416,5958,5959],{"class":3418,"line":3437},[3416,5960,3441],{"emptyLinePlaceholder":3440},[3416,5962,5963],{"class":3418,"line":3444},[3416,5964,5965],{},"title \"Патерни Composite Primary Key у реальних доменах\"\n",[3416,5967,5968],{"class":3418,"line":3450},[3416,5969,3441],{"emptyLinePlaceholder":3440},[3416,5971,5972],{"class":3418,"line":3456},[3416,5973,5974],{},"package \"Приклад 1: Замовлення користувача\" as EX1 #fef3c7 {\n",[3416,5976,5977],{"class":3418,"line":3462},[3416,5978,5979],{},"    note as N1\n",[3416,5981,5982],{"class":3418,"line":3468},[3416,5983,5984],{},"      PK: UserId | SK: OrderDate#OrderId\n",[3416,5986,5987],{"class":3418,"line":3474},[3416,5988,5989],{},"      ─────────────────────────────────────\n",[3416,5991,5992],{"class":3418,"line":3480},[3416,5993,5994],{},"      usr-001 | 2025-01-15#ord-A → Order A\n",[3416,5996,5997],{"class":3418,"line":3486},[3416,5998,5999],{},"      usr-001 | 2025-03-20#ord-B → Order B\n",[3416,6001,6002],{"class":3418,"line":3492},[3416,6003,6004],{},"      usr-001 | 2025-06-01#ord-C → Order C\n",[3416,6006,6007],{"class":3418,"line":3498},[3416,6008,6009],{},"      usr-002 | 2025-02-10#ord-D → Order D\n",[3416,6011,6012],{"class":3418,"line":3504},[3416,6013,5989],{},[3416,6015,6016],{"class":3418,"line":3510},[3416,6017,6018],{},"      Query: \"всі замовлення usr-001 за Q1 2025\"\n",[3416,6020,6021],{"class":3418,"line":3515},[3416,6022,6023],{},"      → PK=\"usr-001\", SK BETWEEN \"2025-01\" AND \"2025-04\"\n",[3416,6025,6026],{"class":3418,"line":3521},[3416,6027,3501],{},[3416,6029,6030],{"class":3418,"line":3527},[3416,6031,3507],{},[3416,6033,6034],{"class":3418,"line":3533},[3416,6035,3441],{"emptyLinePlaceholder":3440},[3416,6037,6038],{"class":3418,"line":3539},[3416,6039,6040],{},"package \"Приклад 2: Повідомлення чату\" as EX2 #dbeafe {\n",[3416,6042,6043],{"class":3418,"line":3545},[3416,6044,6045],{},"    note as N2\n",[3416,6047,6048],{"class":3418,"line":3551},[3416,6049,6050],{},"      PK: ConversationId | SK: Timestamp#MessageId\n",[3416,6052,6053],{"class":3418,"line":3557},[3416,6054,6055],{},"      ─────────────────────────────────────────────\n",[3416,6057,6058],{"class":3418,"line":3563},[3416,6059,6060],{},"      conv-001 | 2025-06-01T10:00#msg-1 → \"Привіт!\"\n",[3416,6062,6063],{"class":3418,"line":3569},[3416,6064,6065],{},"      conv-001 | 2025-06-01T10:01#msg-2 → \"Як справи?\"\n",[3416,6067,6068],{"class":3418,"line":3574},[3416,6069,6070],{},"      conv-001 | 2025-06-01T10:02#msg-3 → \"Чудово!\"\n",[3416,6072,6073],{"class":3418,"line":3579},[3416,6074,6075],{},"      conv-002 | 2025-06-01T11:00#msg-4 → \"Зустріч?\"\n",[3416,6077,6078],{"class":3418,"line":3584},[3416,6079,6055],{},[3416,6081,6082],{"class":3418,"line":3590},[3416,6083,6084],{},"      Query: \"останні 20 повідомлень конversation-001\"\n",[3416,6086,6087],{"class":3418,"line":3596},[3416,6088,6089],{},"      → PK=\"conv-001\", SK DESC, LIMIT 20\n",[3416,6091,6092],{"class":3418,"line":3602},[3416,6093,3501],{},[3416,6095,6096],{"class":3418,"line":3608},[3416,6097,3507],{},[3416,6099,6100],{"class":3418,"line":3614},[3416,6101,3441],{"emptyLinePlaceholder":3440},[3416,6103,6104],{"class":3418,"line":3620},[3416,6105,6106],{},"package \"Приклад 3: IoT-дані сенсора\" as EX3 #d1fae5 {\n",[3416,6108,6109],{"class":3418,"line":3626},[3416,6110,6111],{},"    note as N3\n",[3416,6113,6114],{"class":3418,"line":3631},[3416,6115,6116],{},"      PK: DeviceId | SK: Timestamp\n",[3416,6118,6119],{"class":3418,"line":3636},[3416,6120,5989],{},[3416,6122,6123],{"class":3418,"line":3641},[3416,6124,6125],{},"      sensor-A | 2025-06-01T00:00:00 → 23.5°C\n",[3416,6127,6128],{"class":3418,"line":3647},[3416,6129,6130],{},"      sensor-A | 2025-06-01T00:05:00 → 23.7°C\n",[3416,6132,6133],{"class":3418,"line":3653},[3416,6134,6135],{},"      sensor-A | 2025-06-01T00:10:00 → 24.1°C\n",[3416,6137,6138],{"class":3418,"line":3659},[3416,6139,6140],{},"      sensor-B | 2025-06-01T00:00:00 → 18.2°C\n",[3416,6142,6143],{"class":3418,"line":3665},[3416,6144,5989],{},[3416,6146,6147],{"class":3418,"line":3671},[3416,6148,6149],{},"      Query: \"показання sensor-A за останню годину\"\n",[3416,6151,6152],{"class":3418,"line":3677},[3416,6153,6154],{},"      → PK=\"sensor-A\", SK >= \"2025-06-01T09:00:00\"\n",[3416,6156,6157],{"class":3418,"line":3683},[3416,6158,3501],{},[3416,6160,6161],{"class":3418,"line":3688},[3416,6162,3507],{},[3416,6164,6165],{"class":3418,"line":3693},[3416,6166,3441],{"emptyLinePlaceholder":3440},[3416,6168,6169],{"class":3418,"line":3698},[3416,6170,3718],{},[3727,6172,6174],{"id":6173},"порівняльна-таблиця-первинних-ключів","Порівняльна таблиця первинних ключів",[3353,6176,6177],{},"Для швидкого вибору типу первинного ключа скористайтеся порівняльною таблицею:",[3756,6179,6180,6193],{},[4617,6181,6182],{},[4620,6183,6184,6187,6190],{},[4623,6185,6186],{"align":4625},"Характеристика",[4623,6188,6189],{"align":4625},"Simple Primary Key (Partition Key)",[4623,6191,6192],{"align":4625},"Composite Primary Key (PK + Sort Key)",[4657,6194,6195,6208,6221,6234,6247,6269],{},[4620,6196,6197,6202,6205],{},[4662,6198,6199],{"align":4625},[3363,6200,6201],{},"Склад ключа",[4662,6203,6204],{"align":4625},"Лише один атрибут: Partition Key (PK)",[4662,6206,6207],{"align":4625},"Два атрибути: Partition Key (PK) + Sort Key (SK)",[4620,6209,6210,6215,6218],{},[4662,6211,6212],{"align":4625},[3363,6213,6214],{},"Унікальність",[4662,6216,6217],{"align":4625},"Гарантується на рівні Partition Key",[4662,6219,6220],{"align":4625},"Гарантується комбінацією (Partition Key, Sort Key)",[4620,6222,6223,6228,6231],{},[4662,6224,6225],{"align":4625},[3363,6226,6227],{},"Зберігання даних",[4662,6229,6230],{"align":4625},"Кожен запис може мати свій унікальний PK",[4662,6232,6233],{"align":4625},"Кілька записів можуть мати однаковий PK (групуються разом)",[4620,6235,6236,6241,6244],{},[4662,6237,6238],{"align":4625},[3363,6239,6240],{},"Сортування",[4662,6242,6243],{"align":4625},"Дані не впорядковані",[4662,6245,6246],{"align":4625},"Дані відсортовані за значенням SK в межах одного PK",[4620,6248,6249,6254,6260],{},[4662,6250,6251],{"align":4625},[3363,6252,6253],{},"Доступні запити",[4662,6255,6256,6257,6259],{"align":4625},"Лише за точним значенням PK (",[3413,6258,4873],{},")",[4662,6261,6262,6263,4384,6265,4384,6267,6259],{"align":4625},"За точним PK + фільтрація по SK (",[3413,6264,4887],{},[3413,6266,5644],{},[3413,6268,5911],{},[4620,6270,6271,6276,6279],{},[4662,6272,6273],{"align":4625},[3363,6274,6275],{},"Типові сценарії",[4662,6277,6278],{"align":4625},"Таблиці сесій, кеш, конфігурації користувача",[4662,6280,6281],{"align":4625},"Історія замовлень, чат-повідомлення, логування IoT-пристроїв",[3720,6283],{},[3348,6285,6287],{"id":6286},"операції-читання-і-запису-базовий-api","Операції читання і запису: базовий API",[3353,6289,6290,6291,6294,6295,4043],{},"Розуміння базових операцій DynamoDB є необхідною передумовою для обговорення продуктивності та проектування схем. DynamoDB надає чіткий поділ між операціями для ",[3363,6292,6293],{},"одного елемента"," та операціями для ",[3363,6296,6297],{},"множини елементів",[3727,6299,6301],{"id":6300},"операції-з-одним-елементом","Операції з одним елементом",[3353,6303,6304,6306],{},[3363,6305,4873],{}," — найшвидша операція в DynamoDB. Отримує рівно один елемент за його повним первинним ключем (Partition Key + Sort Key, якщо є). GetItem завжди звертається до конкретної партиції — жодного сканування, жодних індексів, гарантований час O(1).",[6308,6309,6310,6370,6538],"tabs",{},[6311,6312,6314],"tabs-item",{"label":6313},"AWS CLI (bash)",[3406,6315,6319],{"className":6316,"code":6317,"language":6318,"meta":3411,"style":3411},"language-bash shiki shiki-themes light-plus dark-plus dark-plus","# Отримання сесії за композитним ключем\naws dynamodb get-item \\\n    --table-name UserSessions \\\n    --key '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}' \\\n    --region eu-central-1\n","bash",[3413,6320,6321,6326,6342,6352,6362],{"__ignoreMap":3411},[3416,6322,6323],{"class":3418,"line":3419},[3416,6324,6325],{"class":3789},"# Отримання сесії за композитним ключем\n",[3416,6327,6328,6332,6335,6338],{"class":3418,"line":3425},[3416,6329,6331],{"class":6330},"s8Opu","aws",[3416,6333,6334],{"class":3808}," dynamodb",[3416,6336,6337],{"class":3808}," get-item",[3416,6339,6341],{"class":6340},"sjcCO"," \\\n",[3416,6343,6344,6347,6350],{"class":3418,"line":3431},[3416,6345,6346],{"class":4368},"    --table-name",[3416,6348,6349],{"class":3808}," UserSessions",[3416,6351,6341],{"class":6340},[3416,6353,6354,6357,6360],{"class":3418,"line":3437},[3416,6355,6356],{"class":4368},"    --key",[3416,6358,6359],{"class":3808}," '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}'",[3416,6361,6341],{"class":6340},[3416,6363,6364,6367],{"class":3418,"line":3444},[3416,6365,6366],{"class":4368},"    --region",[3416,6368,6369],{"class":3808}," eu-central-1\n",[6311,6371,6373],{"label":6372},".NET SDK (C#)",[3406,6374,6378],{"className":6375,"code":6376,"language":6377,"meta":3411,"style":3411},"language-csharp shiki shiki-themes light-plus dark-plus dark-plus","var client = new AmazonDynamoDBClient();\nvar response = await client.GetItemAsync(new GetItemRequest\n{\n    TableName = \"UserSessions\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } }\n    }\n});\n","csharp",[3413,6379,6380,6402,6429,6433,6445,6470,6475,6504,6529,6533],{"__ignoreMap":3411},[3416,6381,6382,6385,6389,6392,6395,6399],{"class":3418,"line":3419},[3416,6383,6384],{"class":4368},"var",[3416,6386,6388],{"class":6387},"siwwj"," client",[3416,6390,6391],{"class":3795}," = ",[3416,6393,6394],{"class":4368},"new",[3416,6396,6398],{"class":6397},"sN1BT"," AmazonDynamoDBClient",[3416,6400,6401],{"class":3795},"();\n",[3416,6403,6404,6406,6409,6411,6414,6416,6418,6421,6424,6426],{"class":3418,"line":3425},[3416,6405,6384],{"class":4368},[3416,6407,6408],{"class":6387}," response",[3416,6410,6391],{"class":3795},[3416,6412,6413],{"class":4368},"await",[3416,6415,6388],{"class":6387},[3416,6417,4043],{"class":3795},[3416,6419,6420],{"class":6330},"GetItemAsync",[3416,6422,6423],{"class":3795},"(",[3416,6425,6394],{"class":4368},[3416,6427,6428],{"class":6397}," GetItemRequest\n",[3416,6430,6431],{"class":3418,"line":3431},[3416,6432,3796],{"class":3795},[3416,6434,6435,6438,6440,6443],{"class":3418,"line":3437},[3416,6436,6437],{"class":6387},"    TableName",[3416,6439,6391],{"class":3795},[3416,6441,6442],{"class":3808},"\"UserSessions\"",[3416,6444,3812],{"class":3795},[3416,6446,6447,6450,6452,6454,6457,6459,6462,6464,6467],{"class":3418,"line":3444},[3416,6448,6449],{"class":6387},"    Key",[3416,6451,6391],{"class":3795},[3416,6453,6394],{"class":4368},[3416,6455,6456],{"class":6397}," Dictionary",[3416,6458,5861],{"class":3795},[3416,6460,6461],{"class":4368},"string",[3416,6463,4384],{"class":3795},[3416,6465,6466],{"class":6397},"AttributeValue",[3416,6468,6469],{"class":3795},">\n",[3416,6471,6472],{"class":3418,"line":3450},[3416,6473,6474],{"class":3795},"    {\n",[3416,6476,6477,6480,6483,6485,6487,6490,6493,6496,6498,6501],{"class":3418,"line":3456},[3416,6478,6479],{"class":3795},"        { ",[3416,6481,6482],{"class":3808},"\"UserId\"",[3416,6484,4384],{"class":3795},[3416,6486,6394],{"class":4368},[3416,6488,6489],{"class":6397}," AttributeValue",[3416,6491,6492],{"class":3795}," { ",[3416,6494,6495],{"class":6387},"S",[3416,6497,6391],{"class":3795},[3416,6499,6500],{"class":3808},"\"usr-001\"",[3416,6502,6503],{"class":3795}," } },\n",[3416,6505,6506,6508,6511,6513,6515,6517,6519,6521,6523,6526],{"class":3418,"line":3462},[3416,6507,6479],{"class":3795},[3416,6509,6510],{"class":3808},"\"SessionId\"",[3416,6512,4384],{"class":3795},[3416,6514,6394],{"class":4368},[3416,6516,6489],{"class":6397},[3416,6518,6492],{"class":3795},[3416,6520,6495],{"class":6387},[3416,6522,6391],{"class":3795},[3416,6524,6525],{"class":3808},"\"sess-a1b2c3d4\"",[3416,6527,6528],{"class":3795}," } }\n",[3416,6530,6531],{"class":3418,"line":3468},[3416,6532,4167],{"class":3795},[3416,6534,6535],{"class":3418,"line":3474},[3416,6536,6537],{"class":3795},"});\n",[6311,6539,6541],{"label":6540},"PowerShell",[3406,6542,6546],{"className":6543,"code":6544,"language":6545,"meta":3411,"style":3411},"language-powershell shiki shiki-themes light-plus dark-plus dark-plus","# Отримання сесії за композитним ключем\n$key = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n}\nGet-DDBItem -TableName UserSessions -Key $key -Region eu-central-1\n","powershell",[3413,6547,6548,6552,6564,6581,6595,6599],{"__ignoreMap":3411},[3416,6549,6550],{"class":3418,"line":3419},[3416,6551,6325],{"class":3789},[3416,6553,6554,6557,6559,6562],{"class":3418,"line":3425},[3416,6555,6556],{"class":6387},"$key",[3416,6558,6391],{"class":3795},[3416,6560,6561],{"class":4368},"@",[3416,6563,3796],{"class":3795},[3416,6565,6566,6569,6572,6575,6578],{"class":3418,"line":3431},[3416,6567,6568],{"class":6387},"    UserId",[3416,6570,6571],{"class":3795},"    = ",[3416,6573,6574],{"class":6330},"New-DDBEntry",[3416,6576,6577],{"class":3795}," -S ",[3416,6579,6580],{"class":3808},"'usr-001'\n",[3416,6582,6583,6586,6588,6590,6592],{"class":3418,"line":3437},[3416,6584,6585],{"class":6387},"    SessionId",[3416,6587,6391],{"class":3795},[3416,6589,6574],{"class":6330},[3416,6591,6577],{"class":3795},[3416,6593,6594],{"class":3808},"'sess-a1b2c3d4'\n",[3416,6596,6597],{"class":3418,"line":3444},[3416,6598,3507],{"class":3795},[3416,6600,6601,6604,6607,6609,6612],{"class":3418,"line":3450},[3416,6602,6603],{"class":6330},"Get-DDBItem",[3416,6605,6606],{"class":3795}," -TableName UserSessions -Key ",[3416,6608,6556],{"class":6387},[3416,6610,6611],{"class":3795}," -Region eu-central-",[3416,6613,6614],{"class":3870},"1\n",[3353,6616,6617,6620],{},[3363,6618,6619],{},"PutItem"," — записує або повністю замінює елемент за вказаним первинним ключем. Якщо елемент із таким ключем вже існує — він буде повністю замінений. Підтримує умовні записи (Condition Expression).",[6308,6622,6623,6695,6865],{},[6311,6624,6625],{"label":6313},[3406,6626,6628],{"className":6316,"code":6627,"language":6318,"meta":3411,"style":3411},"# Запис нової сесії (якщо вже існує — буде повністю перезаписано)\naws dynamodb put-item \\\n    --table-name UserSessions \\\n    --item '{\n        \"UserId\":    {\"S\": \"usr-001\"},\n        \"SessionId\": {\"S\": \"sess-a1b2c3d4\"},\n        \"CreatedAt\": {\"S\": \"2025-06-01T10:00:00Z\"},\n        \"IsActive\":  {\"BOOL\": true}\n    }' \\\n    --region eu-central-1\n",[3413,6629,6630,6635,6646,6654,6662,6667,6672,6677,6682,6689],{"__ignoreMap":3411},[3416,6631,6632],{"class":3418,"line":3419},[3416,6633,6634],{"class":3789},"# Запис нової сесії (якщо вже існує — буде повністю перезаписано)\n",[3416,6636,6637,6639,6641,6644],{"class":3418,"line":3425},[3416,6638,6331],{"class":6330},[3416,6640,6334],{"class":3808},[3416,6642,6643],{"class":3808}," put-item",[3416,6645,6341],{"class":6340},[3416,6647,6648,6650,6652],{"class":3418,"line":3431},[3416,6649,6346],{"class":4368},[3416,6651,6349],{"class":3808},[3416,6653,6341],{"class":6340},[3416,6655,6656,6659],{"class":3418,"line":3437},[3416,6657,6658],{"class":4368},"    --item",[3416,6660,6661],{"class":3808}," '{\n",[3416,6663,6664],{"class":3418,"line":3444},[3416,6665,6666],{"class":3808},"        \"UserId\":    {\"S\": \"usr-001\"},\n",[3416,6668,6669],{"class":3418,"line":3450},[3416,6670,6671],{"class":3808},"        \"SessionId\": {\"S\": \"sess-a1b2c3d4\"},\n",[3416,6673,6674],{"class":3418,"line":3456},[3416,6675,6676],{"class":3808},"        \"CreatedAt\": {\"S\": \"2025-06-01T10:00:00Z\"},\n",[3416,6678,6679],{"class":3418,"line":3462},[3416,6680,6681],{"class":3808},"        \"IsActive\":  {\"BOOL\": true}\n",[3416,6683,6684,6687],{"class":3418,"line":3468},[3416,6685,6686],{"class":3808},"    }'",[3416,6688,6341],{"class":6340},[3416,6690,6691,6693],{"class":3418,"line":3474},[3416,6692,6366],{"class":4368},[3416,6694,6369],{"class":3808},[6311,6696,6697],{"label":6372},[3406,6698,6700],{"className":6375,"code":6699,"language":6377,"meta":3411,"style":3411},"var response = await client.PutItemAsync(new PutItemRequest\n{\n    TableName = \"UserSessions\",\n    Item = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } },\n        { \"CreatedAt\", new AttributeValue { S = \"2025-06-01T10:00:00Z\" } },\n        { \"IsActive\", new AttributeValue { BOOL = true } }\n    }\n});\n",[3413,6701,6702,6726,6730,6740,6761,6765,6787,6809,6833,6857,6861],{"__ignoreMap":3411},[3416,6703,6704,6706,6708,6710,6712,6714,6716,6719,6721,6723],{"class":3418,"line":3419},[3416,6705,6384],{"class":4368},[3416,6707,6408],{"class":6387},[3416,6709,6391],{"class":3795},[3416,6711,6413],{"class":4368},[3416,6713,6388],{"class":6387},[3416,6715,4043],{"class":3795},[3416,6717,6718],{"class":6330},"PutItemAsync",[3416,6720,6423],{"class":3795},[3416,6722,6394],{"class":4368},[3416,6724,6725],{"class":6397}," PutItemRequest\n",[3416,6727,6728],{"class":3418,"line":3425},[3416,6729,3796],{"class":3795},[3416,6731,6732,6734,6736,6738],{"class":3418,"line":3431},[3416,6733,6437],{"class":6387},[3416,6735,6391],{"class":3795},[3416,6737,6442],{"class":3808},[3416,6739,3812],{"class":3795},[3416,6741,6742,6745,6747,6749,6751,6753,6755,6757,6759],{"class":3418,"line":3437},[3416,6743,6744],{"class":6387},"    Item",[3416,6746,6391],{"class":3795},[3416,6748,6394],{"class":4368},[3416,6750,6456],{"class":6397},[3416,6752,5861],{"class":3795},[3416,6754,6461],{"class":4368},[3416,6756,4384],{"class":3795},[3416,6758,6466],{"class":6397},[3416,6760,6469],{"class":3795},[3416,6762,6763],{"class":3418,"line":3444},[3416,6764,6474],{"class":3795},[3416,6766,6767,6769,6771,6773,6775,6777,6779,6781,6783,6785],{"class":3418,"line":3450},[3416,6768,6479],{"class":3795},[3416,6770,6482],{"class":3808},[3416,6772,4384],{"class":3795},[3416,6774,6394],{"class":4368},[3416,6776,6489],{"class":6397},[3416,6778,6492],{"class":3795},[3416,6780,6495],{"class":6387},[3416,6782,6391],{"class":3795},[3416,6784,6500],{"class":3808},[3416,6786,6503],{"class":3795},[3416,6788,6789,6791,6793,6795,6797,6799,6801,6803,6805,6807],{"class":3418,"line":3456},[3416,6790,6479],{"class":3795},[3416,6792,6510],{"class":3808},[3416,6794,4384],{"class":3795},[3416,6796,6394],{"class":4368},[3416,6798,6489],{"class":6397},[3416,6800,6492],{"class":3795},[3416,6802,6495],{"class":6387},[3416,6804,6391],{"class":3795},[3416,6806,6525],{"class":3808},[3416,6808,6503],{"class":3795},[3416,6810,6811,6813,6816,6818,6820,6822,6824,6826,6828,6831],{"class":3418,"line":3462},[3416,6812,6479],{"class":3795},[3416,6814,6815],{"class":3808},"\"CreatedAt\"",[3416,6817,4384],{"class":3795},[3416,6819,6394],{"class":4368},[3416,6821,6489],{"class":6397},[3416,6823,6492],{"class":3795},[3416,6825,6495],{"class":6387},[3416,6827,6391],{"class":3795},[3416,6829,6830],{"class":3808},"\"2025-06-01T10:00:00Z\"",[3416,6832,6503],{"class":3795},[3416,6834,6835,6837,6840,6842,6844,6846,6848,6851,6853,6855],{"class":3418,"line":3468},[3416,6836,6479],{"class":3795},[3416,6838,6839],{"class":3808},"\"IsActive\"",[3416,6841,4384],{"class":3795},[3416,6843,6394],{"class":4368},[3416,6845,6489],{"class":6397},[3416,6847,6492],{"class":3795},[3416,6849,6850],{"class":6387},"BOOL",[3416,6852,6391],{"class":3795},[3416,6854,4038],{"class":4368},[3416,6856,6528],{"class":3795},[3416,6858,6859],{"class":3418,"line":3474},[3416,6860,4167],{"class":3795},[3416,6862,6863],{"class":3418,"line":3480},[3416,6864,6537],{"class":3795},[6311,6866,6867],{"label":6540},[3406,6868,6870],{"className":6543,"code":6869,"language":6545,"meta":3411,"style":3411},"# Запис нової сесії (або повний перезапис наявної)\n$item = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n    CreatedAt = New-DDBEntry -S '2025-06-01T10:00:00Z'\n    IsActive  = New-DDBEntry -BOOL $true\n}\nSet-DDBItem -TableName UserSessions -Item $item -Region eu-central-1\n",[3413,6871,6872,6877,6888,6900,6912,6926,6942,6946],{"__ignoreMap":3411},[3416,6873,6874],{"class":3418,"line":3419},[3416,6875,6876],{"class":3789},"# Запис нової сесії (або повний перезапис наявної)\n",[3416,6878,6879,6882,6884,6886],{"class":3418,"line":3425},[3416,6880,6881],{"class":6387},"$item",[3416,6883,6391],{"class":3795},[3416,6885,6561],{"class":4368},[3416,6887,3796],{"class":3795},[3416,6889,6890,6892,6894,6896,6898],{"class":3418,"line":3431},[3416,6891,6568],{"class":6387},[3416,6893,6571],{"class":3795},[3416,6895,6574],{"class":6330},[3416,6897,6577],{"class":3795},[3416,6899,6580],{"class":3808},[3416,6901,6902,6904,6906,6908,6910],{"class":3418,"line":3437},[3416,6903,6585],{"class":6387},[3416,6905,6391],{"class":3795},[3416,6907,6574],{"class":6330},[3416,6909,6577],{"class":3795},[3416,6911,6594],{"class":3808},[3416,6913,6914,6917,6919,6921,6923],{"class":3418,"line":3444},[3416,6915,6916],{"class":6387},"    CreatedAt",[3416,6918,6391],{"class":3795},[3416,6920,6574],{"class":6330},[3416,6922,6577],{"class":3795},[3416,6924,6925],{"class":3808},"'2025-06-01T10:00:00Z'\n",[3416,6927,6928,6931,6934,6936,6939],{"class":3418,"line":3450},[3416,6929,6930],{"class":6387},"    IsActive",[3416,6932,6933],{"class":3795},"  = ",[3416,6935,6574],{"class":6330},[3416,6937,6938],{"class":3795}," -BOOL ",[3416,6940,6941],{"class":4368},"$true\n",[3416,6943,6944],{"class":3418,"line":3456},[3416,6945,3507],{"class":3795},[3416,6947,6948,6951,6954,6956,6958],{"class":3418,"line":3462},[3416,6949,6950],{"class":6330},"Set-DDBItem",[3416,6952,6953],{"class":3795}," -TableName UserSessions -Item ",[3416,6955,6881],{"class":6387},[3416,6957,6611],{"class":3795},[3416,6959,6614],{"class":3870},[3353,6961,6962,6965],{},[3363,6963,6964],{},"UpdateItem"," — оновлює конкретні атрибути існуючого елемента, не торкаючись інших. Є атомарним: або всі зміни застосовуються, або жодна. Підтримує атомарні лічильники (Atomic Counter).",[6308,6967,6968,7046,7255],{},[6311,6969,6970],{"label":6313},[3406,6971,6973],{"className":6316,"code":6972,"language":6318,"meta":3411,"style":3411},"# Атомарне оновлення статусу та часу активності сесії\naws dynamodb update-item \\\n    --table-name UserSessions \\\n    --key '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}' \\\n    --update-expression \"SET IsActive = :false, LastActivity = :now\" \\\n    --expression-attribute-values '{\n        \":false\": {\"BOOL\": false},\n        \":now\":   {\"S\": \"2025-06-01T12:00:00Z\"}\n    }' \\\n    --region eu-central-1\n",[3413,6974,6975,6980,6991,6999,7007,7017,7024,7029,7034,7040],{"__ignoreMap":3411},[3416,6976,6977],{"class":3418,"line":3419},[3416,6978,6979],{"class":3789},"# Атомарне оновлення статусу та часу активності сесії\n",[3416,6981,6982,6984,6986,6989],{"class":3418,"line":3425},[3416,6983,6331],{"class":6330},[3416,6985,6334],{"class":3808},[3416,6987,6988],{"class":3808}," update-item",[3416,6990,6341],{"class":6340},[3416,6992,6993,6995,6997],{"class":3418,"line":3431},[3416,6994,6346],{"class":4368},[3416,6996,6349],{"class":3808},[3416,6998,6341],{"class":6340},[3416,7000,7001,7003,7005],{"class":3418,"line":3437},[3416,7002,6356],{"class":4368},[3416,7004,6359],{"class":3808},[3416,7006,6341],{"class":6340},[3416,7008,7009,7012,7015],{"class":3418,"line":3444},[3416,7010,7011],{"class":4368},"    --update-expression",[3416,7013,7014],{"class":3808}," \"SET IsActive = :false, LastActivity = :now\"",[3416,7016,6341],{"class":6340},[3416,7018,7019,7022],{"class":3418,"line":3450},[3416,7020,7021],{"class":4368},"    --expression-attribute-values",[3416,7023,6661],{"class":3808},[3416,7025,7026],{"class":3418,"line":3456},[3416,7027,7028],{"class":3808},"        \":false\": {\"BOOL\": false},\n",[3416,7030,7031],{"class":3418,"line":3462},[3416,7032,7033],{"class":3808},"        \":now\":   {\"S\": \"2025-06-01T12:00:00Z\"}\n",[3416,7035,7036,7038],{"class":3418,"line":3468},[3416,7037,6686],{"class":3808},[3416,7039,6341],{"class":6340},[3416,7041,7042,7044],{"class":3418,"line":3474},[3416,7043,6366],{"class":4368},[3416,7045,6369],{"class":3808},[6311,7047,7048],{"label":6372},[3406,7049,7051],{"className":6375,"code":7050,"language":6377,"meta":3411,"style":3411},"var response = await client.UpdateItemAsync(new UpdateItemRequest\n{\n    TableName = \"UserSessions\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } }\n    },\n    UpdateExpression = \"SET IsActive = :false, LastActivity = :now\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":false\", new AttributeValue { BOOL = false } },\n        { \":now\", new AttributeValue { S = \"2025-06-01T12:00:00Z\" } }\n    }\n});\n",[3413,7052,7053,7077,7081,7091,7111,7115,7137,7159,7163,7175,7196,7200,7223,7247,7251],{"__ignoreMap":3411},[3416,7054,7055,7057,7059,7061,7063,7065,7067,7070,7072,7074],{"class":3418,"line":3419},[3416,7056,6384],{"class":4368},[3416,7058,6408],{"class":6387},[3416,7060,6391],{"class":3795},[3416,7062,6413],{"class":4368},[3416,7064,6388],{"class":6387},[3416,7066,4043],{"class":3795},[3416,7068,7069],{"class":6330},"UpdateItemAsync",[3416,7071,6423],{"class":3795},[3416,7073,6394],{"class":4368},[3416,7075,7076],{"class":6397}," UpdateItemRequest\n",[3416,7078,7079],{"class":3418,"line":3425},[3416,7080,3796],{"class":3795},[3416,7082,7083,7085,7087,7089],{"class":3418,"line":3431},[3416,7084,6437],{"class":6387},[3416,7086,6391],{"class":3795},[3416,7088,6442],{"class":3808},[3416,7090,3812],{"class":3795},[3416,7092,7093,7095,7097,7099,7101,7103,7105,7107,7109],{"class":3418,"line":3437},[3416,7094,6449],{"class":6387},[3416,7096,6391],{"class":3795},[3416,7098,6394],{"class":4368},[3416,7100,6456],{"class":6397},[3416,7102,5861],{"class":3795},[3416,7104,6461],{"class":4368},[3416,7106,4384],{"class":3795},[3416,7108,6466],{"class":6397},[3416,7110,6469],{"class":3795},[3416,7112,7113],{"class":3418,"line":3444},[3416,7114,6474],{"class":3795},[3416,7116,7117,7119,7121,7123,7125,7127,7129,7131,7133,7135],{"class":3418,"line":3450},[3416,7118,6479],{"class":3795},[3416,7120,6482],{"class":3808},[3416,7122,4384],{"class":3795},[3416,7124,6394],{"class":4368},[3416,7126,6489],{"class":6397},[3416,7128,6492],{"class":3795},[3416,7130,6495],{"class":6387},[3416,7132,6391],{"class":3795},[3416,7134,6500],{"class":3808},[3416,7136,6503],{"class":3795},[3416,7138,7139,7141,7143,7145,7147,7149,7151,7153,7155,7157],{"class":3418,"line":3456},[3416,7140,6479],{"class":3795},[3416,7142,6510],{"class":3808},[3416,7144,4384],{"class":3795},[3416,7146,6394],{"class":4368},[3416,7148,6489],{"class":6397},[3416,7150,6492],{"class":3795},[3416,7152,6495],{"class":6387},[3416,7154,6391],{"class":3795},[3416,7156,6525],{"class":3808},[3416,7158,6528],{"class":3795},[3416,7160,7161],{"class":3418,"line":3462},[3416,7162,4442],{"class":3795},[3416,7164,7165,7168,7170,7173],{"class":3418,"line":3468},[3416,7166,7167],{"class":6387},"    UpdateExpression",[3416,7169,6391],{"class":3795},[3416,7171,7172],{"class":3808},"\"SET IsActive = :false, LastActivity = :now\"",[3416,7174,3812],{"class":3795},[3416,7176,7177,7180,7182,7184,7186,7188,7190,7192,7194],{"class":3418,"line":3474},[3416,7178,7179],{"class":6387},"    ExpressionAttributeValues",[3416,7181,6391],{"class":3795},[3416,7183,6394],{"class":4368},[3416,7185,6456],{"class":6397},[3416,7187,5861],{"class":3795},[3416,7189,6461],{"class":4368},[3416,7191,4384],{"class":3795},[3416,7193,6466],{"class":6397},[3416,7195,6469],{"class":3795},[3416,7197,7198],{"class":3418,"line":3480},[3416,7199,6474],{"class":3795},[3416,7201,7202,7204,7207,7209,7211,7213,7215,7217,7219,7221],{"class":3418,"line":3486},[3416,7203,6479],{"class":3795},[3416,7205,7206],{"class":3808},"\":false\"",[3416,7208,4384],{"class":3795},[3416,7210,6394],{"class":4368},[3416,7212,6489],{"class":6397},[3416,7214,6492],{"class":3795},[3416,7216,6850],{"class":6387},[3416,7218,6391],{"class":3795},[3416,7220,4042],{"class":4368},[3416,7222,6503],{"class":3795},[3416,7224,7225,7227,7230,7232,7234,7236,7238,7240,7242,7245],{"class":3418,"line":3492},[3416,7226,6479],{"class":3795},[3416,7228,7229],{"class":3808},"\":now\"",[3416,7231,4384],{"class":3795},[3416,7233,6394],{"class":4368},[3416,7235,6489],{"class":6397},[3416,7237,6492],{"class":3795},[3416,7239,6495],{"class":6387},[3416,7241,6391],{"class":3795},[3416,7243,7244],{"class":3808},"\"2025-06-01T12:00:00Z\"",[3416,7246,6528],{"class":3795},[3416,7248,7249],{"class":3418,"line":3498},[3416,7250,4167],{"class":3795},[3416,7252,7253],{"class":3418,"line":3504},[3416,7254,6537],{"class":3795},[6311,7256,7257],{"label":6540},[3406,7258,7260],{"className":6543,"code":7259,"language":6545,"meta":3411,"style":3411},"# Атомарне оновлення статусу та часу активності\n$updateRequest = [Amazon.DynamoDBv2.Model.UpdateItemRequest]@{\n    TableName = 'UserSessions'\n    Key = @{\n        UserId    = New-DDBEntry -S 'usr-001'\n        SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n    }\n    UpdateExpression = 'SET IsActive = :false, LastActivity = :now'\n    ExpressionAttributeValues = @{\n        ':false' = New-DDBEntry -BOOL $false\n        ':now'   = New-DDBEntry -S '2025-06-01T12:00:00Z'\n    }\n}\nUpdate-DDBItem -UpdateItemRequest $updateRequest -Region eu-central-1\n",[3413,7261,7262,7267,7285,7294,7304,7317,7330,7334,7343,7353,7367,7382,7386,7390],{"__ignoreMap":3411},[3416,7263,7264],{"class":3418,"line":3419},[3416,7265,7266],{"class":3789},"# Атомарне оновлення статусу та часу активності\n",[3416,7268,7269,7272,7275,7278,7281,7283],{"class":3418,"line":3425},[3416,7270,7271],{"class":6387},"$updateRequest",[3416,7273,7274],{"class":3795}," = [",[3416,7276,7277],{"class":4368},"Amazon.DynamoDBv2.Model.UpdateItemRequest",[3416,7279,7280],{"class":3795},"]",[3416,7282,6561],{"class":4368},[3416,7284,3796],{"class":3795},[3416,7286,7287,7289,7291],{"class":3418,"line":3431},[3416,7288,6437],{"class":6387},[3416,7290,6391],{"class":3795},[3416,7292,7293],{"class":3808},"'UserSessions'\n",[3416,7295,7296,7298,7300,7302],{"class":3418,"line":3437},[3416,7297,6449],{"class":6387},[3416,7299,6391],{"class":3795},[3416,7301,6561],{"class":4368},[3416,7303,3796],{"class":3795},[3416,7305,7306,7309,7311,7313,7315],{"class":3418,"line":3444},[3416,7307,7308],{"class":6387},"        UserId",[3416,7310,6571],{"class":3795},[3416,7312,6574],{"class":6330},[3416,7314,6577],{"class":3795},[3416,7316,6580],{"class":3808},[3416,7318,7319,7322,7324,7326,7328],{"class":3418,"line":3450},[3416,7320,7321],{"class":6387},"        SessionId",[3416,7323,6391],{"class":3795},[3416,7325,6574],{"class":6330},[3416,7327,6577],{"class":3795},[3416,7329,6594],{"class":3808},[3416,7331,7332],{"class":3418,"line":3456},[3416,7333,4167],{"class":3795},[3416,7335,7336,7338,7340],{"class":3418,"line":3462},[3416,7337,7167],{"class":6387},[3416,7339,6391],{"class":3795},[3416,7341,7342],{"class":3808},"'SET IsActive = :false, LastActivity = :now'\n",[3416,7344,7345,7347,7349,7351],{"class":3418,"line":3468},[3416,7346,7179],{"class":6387},[3416,7348,6391],{"class":3795},[3416,7350,6561],{"class":4368},[3416,7352,3796],{"class":3795},[3416,7354,7355,7358,7360,7362,7364],{"class":3418,"line":3474},[3416,7356,7357],{"class":3808},"        ':false'",[3416,7359,6391],{"class":3795},[3416,7361,6574],{"class":6330},[3416,7363,6938],{"class":3795},[3416,7365,7366],{"class":4368},"$false\n",[3416,7368,7369,7372,7375,7377,7379],{"class":3418,"line":3480},[3416,7370,7371],{"class":3808},"        ':now'",[3416,7373,7374],{"class":3795},"   = ",[3416,7376,6574],{"class":6330},[3416,7378,6577],{"class":3795},[3416,7380,7381],{"class":3808},"'2025-06-01T12:00:00Z'\n",[3416,7383,7384],{"class":3418,"line":3486},[3416,7385,4167],{"class":3795},[3416,7387,7388],{"class":3418,"line":3492},[3416,7389,3507],{"class":3795},[3416,7391,7392,7395,7398,7400,7402],{"class":3418,"line":3498},[3416,7393,7394],{"class":6330},"Update-DDBItem",[3416,7396,7397],{"class":3795}," -UpdateItemRequest ",[3416,7399,7271],{"class":6387},[3416,7401,6611],{"class":3795},[3416,7403,6614],{"class":3870},[3353,7405,7406,7409],{},[3363,7407,7408],{},"DeleteItem"," — видаляє елемент за первинним ключем. Підтримує умовне видалення.",[6308,7411,7412,7457,7578],{},[6311,7413,7414],{"label":6313},[3406,7415,7417],{"className":6316,"code":7416,"language":6318,"meta":3411,"style":3411},"# Видалення сесії за її первинним ключем\naws dynamodb delete-item \\\n    --table-name UserSessions \\\n    --key '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}' \\\n    --region eu-central-1\n",[3413,7418,7419,7424,7435,7443,7451],{"__ignoreMap":3411},[3416,7420,7421],{"class":3418,"line":3419},[3416,7422,7423],{"class":3789},"# Видалення сесії за її первинним ключем\n",[3416,7425,7426,7428,7430,7433],{"class":3418,"line":3425},[3416,7427,6331],{"class":6330},[3416,7429,6334],{"class":3808},[3416,7431,7432],{"class":3808}," delete-item",[3416,7434,6341],{"class":6340},[3416,7436,7437,7439,7441],{"class":3418,"line":3431},[3416,7438,6346],{"class":4368},[3416,7440,6349],{"class":3808},[3416,7442,6341],{"class":6340},[3416,7444,7445,7447,7449],{"class":3418,"line":3437},[3416,7446,6356],{"class":4368},[3416,7448,6359],{"class":3808},[3416,7450,6341],{"class":6340},[3416,7452,7453,7455],{"class":3418,"line":3444},[3416,7454,6366],{"class":4368},[3416,7456,6369],{"class":3808},[6311,7458,7459],{"label":6372},[3406,7460,7462],{"className":6375,"code":7461,"language":6377,"meta":3411,"style":3411},"var response = await client.DeleteItemAsync(new DeleteItemRequest\n{\n    TableName = \"UserSessions\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } }\n    }\n});\n",[3413,7463,7464,7488,7492,7502,7522,7526,7548,7570,7574],{"__ignoreMap":3411},[3416,7465,7466,7468,7470,7472,7474,7476,7478,7481,7483,7485],{"class":3418,"line":3419},[3416,7467,6384],{"class":4368},[3416,7469,6408],{"class":6387},[3416,7471,6391],{"class":3795},[3416,7473,6413],{"class":4368},[3416,7475,6388],{"class":6387},[3416,7477,4043],{"class":3795},[3416,7479,7480],{"class":6330},"DeleteItemAsync",[3416,7482,6423],{"class":3795},[3416,7484,6394],{"class":4368},[3416,7486,7487],{"class":6397}," DeleteItemRequest\n",[3416,7489,7490],{"class":3418,"line":3425},[3416,7491,3796],{"class":3795},[3416,7493,7494,7496,7498,7500],{"class":3418,"line":3431},[3416,7495,6437],{"class":6387},[3416,7497,6391],{"class":3795},[3416,7499,6442],{"class":3808},[3416,7501,3812],{"class":3795},[3416,7503,7504,7506,7508,7510,7512,7514,7516,7518,7520],{"class":3418,"line":3437},[3416,7505,6449],{"class":6387},[3416,7507,6391],{"class":3795},[3416,7509,6394],{"class":4368},[3416,7511,6456],{"class":6397},[3416,7513,5861],{"class":3795},[3416,7515,6461],{"class":4368},[3416,7517,4384],{"class":3795},[3416,7519,6466],{"class":6397},[3416,7521,6469],{"class":3795},[3416,7523,7524],{"class":3418,"line":3444},[3416,7525,6474],{"class":3795},[3416,7527,7528,7530,7532,7534,7536,7538,7540,7542,7544,7546],{"class":3418,"line":3450},[3416,7529,6479],{"class":3795},[3416,7531,6482],{"class":3808},[3416,7533,4384],{"class":3795},[3416,7535,6394],{"class":4368},[3416,7537,6489],{"class":6397},[3416,7539,6492],{"class":3795},[3416,7541,6495],{"class":6387},[3416,7543,6391],{"class":3795},[3416,7545,6500],{"class":3808},[3416,7547,6503],{"class":3795},[3416,7549,7550,7552,7554,7556,7558,7560,7562,7564,7566,7568],{"class":3418,"line":3456},[3416,7551,6479],{"class":3795},[3416,7553,6510],{"class":3808},[3416,7555,4384],{"class":3795},[3416,7557,6394],{"class":4368},[3416,7559,6489],{"class":6397},[3416,7561,6492],{"class":3795},[3416,7563,6495],{"class":6387},[3416,7565,6391],{"class":3795},[3416,7567,6525],{"class":3808},[3416,7569,6528],{"class":3795},[3416,7571,7572],{"class":3418,"line":3462},[3416,7573,4167],{"class":3795},[3416,7575,7576],{"class":3418,"line":3468},[3416,7577,6537],{"class":3795},[6311,7579,7580],{"label":6540},[3406,7581,7583],{"className":6543,"code":7582,"language":6545,"meta":3411,"style":3411},"# Видалення сесії за первинним ключем\n$key = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n}\nRemove-DDBItem -TableName UserSessions -Key $key -Region eu-central-1\n",[3413,7584,7585,7590,7600,7612,7624,7628],{"__ignoreMap":3411},[3416,7586,7587],{"class":3418,"line":3419},[3416,7588,7589],{"class":3789},"# Видалення сесії за первинним ключем\n",[3416,7591,7592,7594,7596,7598],{"class":3418,"line":3425},[3416,7593,6556],{"class":6387},[3416,7595,6391],{"class":3795},[3416,7597,6561],{"class":4368},[3416,7599,3796],{"class":3795},[3416,7601,7602,7604,7606,7608,7610],{"class":3418,"line":3431},[3416,7603,6568],{"class":6387},[3416,7605,6571],{"class":3795},[3416,7607,6574],{"class":6330},[3416,7609,6577],{"class":3795},[3416,7611,6580],{"class":3808},[3416,7613,7614,7616,7618,7620,7622],{"class":3418,"line":3437},[3416,7615,6585],{"class":6387},[3416,7617,6391],{"class":3795},[3416,7619,6574],{"class":6330},[3416,7621,6577],{"class":3795},[3416,7623,6594],{"class":3808},[3416,7625,7626],{"class":3418,"line":3444},[3416,7627,3507],{"class":3795},[3416,7629,7630,7633,7635,7637,7639],{"class":3418,"line":3450},[3416,7631,7632],{"class":6330},"Remove-DDBItem",[3416,7634,6606],{"class":3795},[3416,7636,6556],{"class":6387},[3416,7638,6611],{"class":3795},[3416,7640,6614],{"class":3870},[3727,7642,7644],{"id":7643},"операції-з-множиною-елементів","Операції з множиною елементів",[3353,7646,7647,7649,7650,7653],{},[3363,7648,4887],{}," — отримує один або кілька елементів, що відповідають заданому Partition Key та (необов'язково) умові на Sort Key. Query виконується ",[3363,7651,7652],{},"виключно всередині однієї партиції"," — це забезпечує ефективність. Query — це основна операція запиту у правильно спроектованій таблиці DynamoDB.",[6308,7655,7656,7725,7861],{},[6311,7657,7658],{"label":6313},[3406,7659,7661],{"className":6316,"code":7660,"language":6318,"meta":3411,"style":3411},"# Пошук сесій користувача, які починаються з певного префіксу\naws dynamodb query \\\n    --table-name UserSessions \\\n    --key-condition-expression \"UserId = :uid AND SessionId begins_with(:sessPrefix)\" \\\n    --expression-attribute-values '{\n        \":uid\":        {\"S\": \"usr-001\"},\n        \":sessPrefix\": {\"S\": \"sess-a\"}\n    }' \\\n    --region eu-central-1\n",[3413,7662,7663,7668,7679,7687,7697,7703,7708,7713,7719],{"__ignoreMap":3411},[3416,7664,7665],{"class":3418,"line":3419},[3416,7666,7667],{"class":3789},"# Пошук сесій користувача, які починаються з певного префіксу\n",[3416,7669,7670,7672,7674,7677],{"class":3418,"line":3425},[3416,7671,6331],{"class":6330},[3416,7673,6334],{"class":3808},[3416,7675,7676],{"class":3808}," query",[3416,7678,6341],{"class":6340},[3416,7680,7681,7683,7685],{"class":3418,"line":3431},[3416,7682,6346],{"class":4368},[3416,7684,6349],{"class":3808},[3416,7686,6341],{"class":6340},[3416,7688,7689,7692,7695],{"class":3418,"line":3437},[3416,7690,7691],{"class":4368},"    --key-condition-expression",[3416,7693,7694],{"class":3808}," \"UserId = :uid AND SessionId begins_with(:sessPrefix)\"",[3416,7696,6341],{"class":6340},[3416,7698,7699,7701],{"class":3418,"line":3444},[3416,7700,7021],{"class":4368},[3416,7702,6661],{"class":3808},[3416,7704,7705],{"class":3418,"line":3450},[3416,7706,7707],{"class":3808},"        \":uid\":        {\"S\": \"usr-001\"},\n",[3416,7709,7710],{"class":3418,"line":3456},[3416,7711,7712],{"class":3808},"        \":sessPrefix\": {\"S\": \"sess-a\"}\n",[3416,7714,7715,7717],{"class":3418,"line":3462},[3416,7716,6686],{"class":3808},[3416,7718,6341],{"class":6340},[3416,7720,7721,7723],{"class":3418,"line":3468},[3416,7722,6366],{"class":4368},[3416,7724,6369],{"class":3808},[6311,7726,7727],{"label":6372},[3406,7728,7730],{"className":6375,"code":7729,"language":6377,"meta":3411,"style":3411},"var response = await client.QueryAsync(new QueryRequest\n{\n    TableName = \"UserSessions\",\n    KeyConditionExpression = \"UserId = :uid AND SessionId begins_with(:sessPrefix)\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":uid\", new AttributeValue { S = \"usr-001\" } },\n        { \":sessPrefix\", new AttributeValue { S = \"sess-a\" } }\n    }\n});\n",[3413,7731,7732,7756,7760,7770,7782,7802,7806,7829,7853,7857],{"__ignoreMap":3411},[3416,7733,7734,7736,7738,7740,7742,7744,7746,7749,7751,7753],{"class":3418,"line":3419},[3416,7735,6384],{"class":4368},[3416,7737,6408],{"class":6387},[3416,7739,6391],{"class":3795},[3416,7741,6413],{"class":4368},[3416,7743,6388],{"class":6387},[3416,7745,4043],{"class":3795},[3416,7747,7748],{"class":6330},"QueryAsync",[3416,7750,6423],{"class":3795},[3416,7752,6394],{"class":4368},[3416,7754,7755],{"class":6397}," QueryRequest\n",[3416,7757,7758],{"class":3418,"line":3425},[3416,7759,3796],{"class":3795},[3416,7761,7762,7764,7766,7768],{"class":3418,"line":3431},[3416,7763,6437],{"class":6387},[3416,7765,6391],{"class":3795},[3416,7767,6442],{"class":3808},[3416,7769,3812],{"class":3795},[3416,7771,7772,7775,7777,7780],{"class":3418,"line":3437},[3416,7773,7774],{"class":6387},"    KeyConditionExpression",[3416,7776,6391],{"class":3795},[3416,7778,7779],{"class":3808},"\"UserId = :uid AND SessionId begins_with(:sessPrefix)\"",[3416,7781,3812],{"class":3795},[3416,7783,7784,7786,7788,7790,7792,7794,7796,7798,7800],{"class":3418,"line":3444},[3416,7785,7179],{"class":6387},[3416,7787,6391],{"class":3795},[3416,7789,6394],{"class":4368},[3416,7791,6456],{"class":6397},[3416,7793,5861],{"class":3795},[3416,7795,6461],{"class":4368},[3416,7797,4384],{"class":3795},[3416,7799,6466],{"class":6397},[3416,7801,6469],{"class":3795},[3416,7803,7804],{"class":3418,"line":3450},[3416,7805,6474],{"class":3795},[3416,7807,7808,7810,7813,7815,7817,7819,7821,7823,7825,7827],{"class":3418,"line":3456},[3416,7809,6479],{"class":3795},[3416,7811,7812],{"class":3808},"\":uid\"",[3416,7814,4384],{"class":3795},[3416,7816,6394],{"class":4368},[3416,7818,6489],{"class":6397},[3416,7820,6492],{"class":3795},[3416,7822,6495],{"class":6387},[3416,7824,6391],{"class":3795},[3416,7826,6500],{"class":3808},[3416,7828,6503],{"class":3795},[3416,7830,7831,7833,7836,7838,7840,7842,7844,7846,7848,7851],{"class":3418,"line":3462},[3416,7832,6479],{"class":3795},[3416,7834,7835],{"class":3808},"\":sessPrefix\"",[3416,7837,4384],{"class":3795},[3416,7839,6394],{"class":4368},[3416,7841,6489],{"class":6397},[3416,7843,6492],{"class":3795},[3416,7845,6495],{"class":6387},[3416,7847,6391],{"class":3795},[3416,7849,7850],{"class":3808},"\"sess-a\"",[3416,7852,6528],{"class":3795},[3416,7854,7855],{"class":3418,"line":3468},[3416,7856,4167],{"class":3795},[3416,7858,7859],{"class":3418,"line":3474},[3416,7860,6537],{"class":3795},[6311,7862,7863],{"label":6540},[3406,7864,7866],{"className":6543,"code":7865,"language":6545,"meta":3411,"style":3411},"# Пошук сесій за Partition Key та префіксом Sort Key\n$queryRequest = [Amazon.DynamoDBv2.Model.QueryRequest]@{\n    TableName = 'UserSessions'\n    KeyConditionExpression = 'UserId = :uid AND SessionId begins_with(:sessPrefix)'\n    ExpressionAttributeValues = @{\n        ':uid'        = New-DDBEntry -S 'usr-001'\n        ':sessPrefix' = New-DDBEntry -S 'sess-a'\n    }\n}\nInvoke-DDBQuery -QueryRequest $queryRequest -Region eu-central-1\n",[3413,7867,7868,7873,7889,7897,7906,7916,7930,7944,7948,7952],{"__ignoreMap":3411},[3416,7869,7870],{"class":3418,"line":3419},[3416,7871,7872],{"class":3789},"# Пошук сесій за Partition Key та префіксом Sort Key\n",[3416,7874,7875,7878,7880,7883,7885,7887],{"class":3418,"line":3425},[3416,7876,7877],{"class":6387},"$queryRequest",[3416,7879,7274],{"class":3795},[3416,7881,7882],{"class":4368},"Amazon.DynamoDBv2.Model.QueryRequest",[3416,7884,7280],{"class":3795},[3416,7886,6561],{"class":4368},[3416,7888,3796],{"class":3795},[3416,7890,7891,7893,7895],{"class":3418,"line":3431},[3416,7892,6437],{"class":6387},[3416,7894,6391],{"class":3795},[3416,7896,7293],{"class":3808},[3416,7898,7899,7901,7903],{"class":3418,"line":3437},[3416,7900,7774],{"class":6387},[3416,7902,6391],{"class":3795},[3416,7904,7905],{"class":3808},"'UserId = :uid AND SessionId begins_with(:sessPrefix)'\n",[3416,7907,7908,7910,7912,7914],{"class":3418,"line":3444},[3416,7909,7179],{"class":6387},[3416,7911,6391],{"class":3795},[3416,7913,6561],{"class":4368},[3416,7915,3796],{"class":3795},[3416,7917,7918,7921,7924,7926,7928],{"class":3418,"line":3450},[3416,7919,7920],{"class":3808},"        ':uid'",[3416,7922,7923],{"class":3795},"        = ",[3416,7925,6574],{"class":6330},[3416,7927,6577],{"class":3795},[3416,7929,6580],{"class":3808},[3416,7931,7932,7935,7937,7939,7941],{"class":3418,"line":3456},[3416,7933,7934],{"class":3808},"        ':sessPrefix'",[3416,7936,6391],{"class":3795},[3416,7938,6574],{"class":6330},[3416,7940,6577],{"class":3795},[3416,7942,7943],{"class":3808},"'sess-a'\n",[3416,7945,7946],{"class":3418,"line":3462},[3416,7947,4167],{"class":3795},[3416,7949,7950],{"class":3418,"line":3468},[3416,7951,3507],{"class":3795},[3416,7953,7954,7957,7960,7962,7964],{"class":3418,"line":3474},[3416,7955,7956],{"class":6330},"Invoke-DDBQuery",[3416,7958,7959],{"class":3795}," -QueryRequest ",[3416,7961,7877],{"class":6387},[3416,7963,6611],{"class":3795},[3416,7965,6614],{"class":3870},[3353,7967,7968,7970,7971,7974],{},[3363,7969,4891],{}," — проходить по ",[3363,7972,7973],{},"всіх"," елементах таблиці або індексу. Scan є дорогою операцією: він читає кожен елемент, споживає одиниці пропускної здатності для кожного прочитаного елемента, навіть якщо результат фільтрується. Scan використовується виключно для адміністративних задач або однократного аналізу даних.",[6308,7976,7977,8033,8145],{},[6311,7978,7979],{"label":6313},[3406,7980,7982],{"className":6316,"code":7981,"language":6318,"meta":3411,"style":3411},"# Сканування всієї таблиці для пошуку активних сесій (неефективно!)\naws dynamodb scan \\\n    --table-name UserSessions \\\n    --filter-expression \"IsActive = :true\" \\\n    --expression-attribute-values '{\":true\": {\"BOOL\": true}}' \\\n    --region eu-central-1\n",[3413,7983,7984,7989,8000,8008,8018,8027],{"__ignoreMap":3411},[3416,7985,7986],{"class":3418,"line":3419},[3416,7987,7988],{"class":3789},"# Сканування всієї таблиці для пошуку активних сесій (неефективно!)\n",[3416,7990,7991,7993,7995,7998],{"class":3418,"line":3425},[3416,7992,6331],{"class":6330},[3416,7994,6334],{"class":3808},[3416,7996,7997],{"class":3808}," scan",[3416,7999,6341],{"class":6340},[3416,8001,8002,8004,8006],{"class":3418,"line":3431},[3416,8003,6346],{"class":4368},[3416,8005,6349],{"class":3808},[3416,8007,6341],{"class":6340},[3416,8009,8010,8013,8016],{"class":3418,"line":3437},[3416,8011,8012],{"class":4368},"    --filter-expression",[3416,8014,8015],{"class":3808}," \"IsActive = :true\"",[3416,8017,6341],{"class":6340},[3416,8019,8020,8022,8025],{"class":3418,"line":3444},[3416,8021,7021],{"class":4368},[3416,8023,8024],{"class":3808}," '{\":true\": {\"BOOL\": true}}'",[3416,8026,6341],{"class":6340},[3416,8028,8029,8031],{"class":3418,"line":3450},[3416,8030,6366],{"class":4368},[3416,8032,6369],{"class":3808},[6311,8034,8035],{"label":6372},[3406,8036,8038],{"className":6375,"code":8037,"language":6377,"meta":3411,"style":3411},"var response = await client.ScanAsync(new ScanRequest\n{\n    TableName = \"UserSessions\",\n    FilterExpression = \"IsActive = :true\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":true\", new AttributeValue { BOOL = true } }\n    }\n});\n",[3413,8039,8040,8064,8068,8078,8090,8110,8114,8137,8141],{"__ignoreMap":3411},[3416,8041,8042,8044,8046,8048,8050,8052,8054,8057,8059,8061],{"class":3418,"line":3419},[3416,8043,6384],{"class":4368},[3416,8045,6408],{"class":6387},[3416,8047,6391],{"class":3795},[3416,8049,6413],{"class":4368},[3416,8051,6388],{"class":6387},[3416,8053,4043],{"class":3795},[3416,8055,8056],{"class":6330},"ScanAsync",[3416,8058,6423],{"class":3795},[3416,8060,6394],{"class":4368},[3416,8062,8063],{"class":6397}," ScanRequest\n",[3416,8065,8066],{"class":3418,"line":3425},[3416,8067,3796],{"class":3795},[3416,8069,8070,8072,8074,8076],{"class":3418,"line":3431},[3416,8071,6437],{"class":6387},[3416,8073,6391],{"class":3795},[3416,8075,6442],{"class":3808},[3416,8077,3812],{"class":3795},[3416,8079,8080,8083,8085,8088],{"class":3418,"line":3437},[3416,8081,8082],{"class":6387},"    FilterExpression",[3416,8084,6391],{"class":3795},[3416,8086,8087],{"class":3808},"\"IsActive = :true\"",[3416,8089,3812],{"class":3795},[3416,8091,8092,8094,8096,8098,8100,8102,8104,8106,8108],{"class":3418,"line":3444},[3416,8093,7179],{"class":6387},[3416,8095,6391],{"class":3795},[3416,8097,6394],{"class":4368},[3416,8099,6456],{"class":6397},[3416,8101,5861],{"class":3795},[3416,8103,6461],{"class":4368},[3416,8105,4384],{"class":3795},[3416,8107,6466],{"class":6397},[3416,8109,6469],{"class":3795},[3416,8111,8112],{"class":3418,"line":3450},[3416,8113,6474],{"class":3795},[3416,8115,8116,8118,8121,8123,8125,8127,8129,8131,8133,8135],{"class":3418,"line":3456},[3416,8117,6479],{"class":3795},[3416,8119,8120],{"class":3808},"\":true\"",[3416,8122,4384],{"class":3795},[3416,8124,6394],{"class":4368},[3416,8126,6489],{"class":6397},[3416,8128,6492],{"class":3795},[3416,8130,6850],{"class":6387},[3416,8132,6391],{"class":3795},[3416,8134,4038],{"class":4368},[3416,8136,6528],{"class":3795},[3416,8138,8139],{"class":3418,"line":3462},[3416,8140,4167],{"class":3795},[3416,8142,8143],{"class":3418,"line":3468},[3416,8144,6537],{"class":3795},[6311,8146,8147],{"label":6540},[3406,8148,8150],{"className":6543,"code":8149,"language":6545,"meta":3411,"style":3411},"# Сканування всієї таблиці з фільтрацією\n$scanRequest = [Amazon.DynamoDBv2.Model.ScanRequest]@{\n    TableName = 'UserSessions'\n    FilterExpression = 'IsActive = :true'\n    ExpressionAttributeValues = @{\n        ':true' = New-DDBEntry -BOOL $true\n    }\n}\nInvoke-DDBScan -ScanRequest $scanRequest -Region eu-central-1\n",[3413,8151,8152,8157,8173,8181,8190,8200,8213,8217,8221],{"__ignoreMap":3411},[3416,8153,8154],{"class":3418,"line":3419},[3416,8155,8156],{"class":3789},"# Сканування всієї таблиці з фільтрацією\n",[3416,8158,8159,8162,8164,8167,8169,8171],{"class":3418,"line":3425},[3416,8160,8161],{"class":6387},"$scanRequest",[3416,8163,7274],{"class":3795},[3416,8165,8166],{"class":4368},"Amazon.DynamoDBv2.Model.ScanRequest",[3416,8168,7280],{"class":3795},[3416,8170,6561],{"class":4368},[3416,8172,3796],{"class":3795},[3416,8174,8175,8177,8179],{"class":3418,"line":3431},[3416,8176,6437],{"class":6387},[3416,8178,6391],{"class":3795},[3416,8180,7293],{"class":3808},[3416,8182,8183,8185,8187],{"class":3418,"line":3437},[3416,8184,8082],{"class":6387},[3416,8186,6391],{"class":3795},[3416,8188,8189],{"class":3808},"'IsActive = :true'\n",[3416,8191,8192,8194,8196,8198],{"class":3418,"line":3444},[3416,8193,7179],{"class":6387},[3416,8195,6391],{"class":3795},[3416,8197,6561],{"class":4368},[3416,8199,3796],{"class":3795},[3416,8201,8202,8205,8207,8209,8211],{"class":3418,"line":3450},[3416,8203,8204],{"class":3808},"        ':true'",[3416,8206,6391],{"class":3795},[3416,8208,6574],{"class":6330},[3416,8210,6938],{"class":3795},[3416,8212,6941],{"class":4368},[3416,8214,8215],{"class":3418,"line":3456},[3416,8216,4167],{"class":3795},[3416,8218,8219],{"class":3418,"line":3462},[3416,8220,3507],{"class":3795},[3416,8222,8223,8226,8229,8231,8233],{"class":3418,"line":3468},[3416,8224,8225],{"class":6330},"Invoke-DDBScan",[3416,8227,8228],{"class":3795}," -ScanRequest ",[3416,8230,8161],{"class":6387},[3416,8232,6611],{"class":3795},[3416,8234,6614],{"class":3870},[3403,8236,8237],{},[3406,8238,8240],{"className":3408,"code":8239,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Query vs Scan: різниця у підході\"\n\npackage \"Таблиця: Orders (10 мільйонів елементів)\" as TBL {\n    together {\n        node \"Partition: usr-001\\n5 замовлень\" as P1 #bbf7d0\n        node \"Partition: usr-002\\n3 замовлення\" as P2 #bbf7d0\n        node \"Partition: usr-003\\n8 замовлень\" as P3 #bbf7d0\n        node \"... ще 2 млн партицій ...\" as PDOTS #e5e7eb\n    }\n}\n\nactor \"Client\" as C\n\nrectangle \"Query\\nPK = 'usr-001'\" as Q #d1fae5\nrectangle \"Scan\\n(filter: Amount > 100)\" as S #fee2e2\n\nC --> Q\nC --> S\n\nQ --> P1 : \"1 звернення\\nдо 1 партиції\\n~1ms, 5 RCU\"\nS --> P1 : \"читає ВСЕ\\n\"\nS --> P2 : \"читає ВСЕ\\n\"\nS --> P3 : \"читає ВСЕ\\n\"\nS --> PDOTS : \"читає ВСЕ...\"\n\nnote right of S #fee2e2\n  Scan читає 10 млн елементів!\n  Час: секунди–хвилини.\n  Споживає: 10 млн RCU.\n  В production: заборонено\n  для operational queries.\nend note\n\nnote right of Q #d1fae5\n  Query читає 5 елементів\n  в 1 партиції.\n  Час: ~1ms.\n  Споживає: 5 RCU (або 0.5 RCU\n  при Eventually Consistent).\nend note\n\n@enduml\n",[3413,8241,8242,8246,8250,8254,8258,8263,8267,8272,8277,8282,8287,8292,8297,8301,8305,8309,8314,8318,8323,8328,8332,8337,8342,8346,8351,8356,8361,8366,8371,8375,8380,8385,8390,8395,8400,8405,8409,8413,8418,8423,8428,8433,8438,8443,8447,8451],{"__ignoreMap":3411},[3416,8243,8244],{"class":3418,"line":3419},[3416,8245,3422],{},[3416,8247,8248],{"class":3418,"line":3425},[3416,8249,3428],{},[3416,8251,8252],{"class":3418,"line":3431},[3416,8253,3434],{},[3416,8255,8256],{"class":3418,"line":3437},[3416,8257,3441],{"emptyLinePlaceholder":3440},[3416,8259,8260],{"class":3418,"line":3444},[3416,8261,8262],{},"title \"Query vs Scan: різниця у підході\"\n",[3416,8264,8265],{"class":3418,"line":3450},[3416,8266,3441],{"emptyLinePlaceholder":3440},[3416,8268,8269],{"class":3418,"line":3456},[3416,8270,8271],{},"package \"Таблиця: Orders (10 мільйонів елементів)\" as TBL {\n",[3416,8273,8274],{"class":3418,"line":3462},[3416,8275,8276],{},"    together {\n",[3416,8278,8279],{"class":3418,"line":3468},[3416,8280,8281],{},"        node \"Partition: usr-001\\n5 замовлень\" as P1 #bbf7d0\n",[3416,8283,8284],{"class":3418,"line":3474},[3416,8285,8286],{},"        node \"Partition: usr-002\\n3 замовлення\" as P2 #bbf7d0\n",[3416,8288,8289],{"class":3418,"line":3480},[3416,8290,8291],{},"        node \"Partition: usr-003\\n8 замовлень\" as P3 #bbf7d0\n",[3416,8293,8294],{"class":3418,"line":3486},[3416,8295,8296],{},"        node \"... ще 2 млн партицій ...\" as PDOTS #e5e7eb\n",[3416,8298,8299],{"class":3418,"line":3492},[3416,8300,4167],{},[3416,8302,8303],{"class":3418,"line":3498},[3416,8304,3507],{},[3416,8306,8307],{"class":3418,"line":3504},[3416,8308,3441],{"emptyLinePlaceholder":3440},[3416,8310,8311],{"class":3418,"line":3510},[3416,8312,8313],{},"actor \"Client\" as C\n",[3416,8315,8316],{"class":3418,"line":3515},[3416,8317,3441],{"emptyLinePlaceholder":3440},[3416,8319,8320],{"class":3418,"line":3521},[3416,8321,8322],{},"rectangle \"Query\\nPK = 'usr-001'\" as Q #d1fae5\n",[3416,8324,8325],{"class":3418,"line":3527},[3416,8326,8327],{},"rectangle \"Scan\\n(filter: Amount > 100)\" as S #fee2e2\n",[3416,8329,8330],{"class":3418,"line":3533},[3416,8331,3441],{"emptyLinePlaceholder":3440},[3416,8333,8334],{"class":3418,"line":3539},[3416,8335,8336],{},"C --> Q\n",[3416,8338,8339],{"class":3418,"line":3545},[3416,8340,8341],{},"C --> S\n",[3416,8343,8344],{"class":3418,"line":3551},[3416,8345,3441],{"emptyLinePlaceholder":3440},[3416,8347,8348],{"class":3418,"line":3557},[3416,8349,8350],{},"Q --> P1 : \"1 звернення\\nдо 1 партиції\\n~1ms, 5 RCU\"\n",[3416,8352,8353],{"class":3418,"line":3563},[3416,8354,8355],{},"S --> P1 : \"читає ВСЕ\\n\"\n",[3416,8357,8358],{"class":3418,"line":3569},[3416,8359,8360],{},"S --> P2 : \"читає ВСЕ\\n\"\n",[3416,8362,8363],{"class":3418,"line":3574},[3416,8364,8365],{},"S --> P3 : \"читає ВСЕ\\n\"\n",[3416,8367,8368],{"class":3418,"line":3579},[3416,8369,8370],{},"S --> PDOTS : \"читає ВСЕ...\"\n",[3416,8372,8373],{"class":3418,"line":3584},[3416,8374,3441],{"emptyLinePlaceholder":3440},[3416,8376,8377],{"class":3418,"line":3590},[3416,8378,8379],{},"note right of S #fee2e2\n",[3416,8381,8382],{"class":3418,"line":3596},[3416,8383,8384],{},"  Scan читає 10 млн елементів!\n",[3416,8386,8387],{"class":3418,"line":3602},[3416,8388,8389],{},"  Час: секунди–хвилини.\n",[3416,8391,8392],{"class":3418,"line":3608},[3416,8393,8394],{},"  Споживає: 10 млн RCU.\n",[3416,8396,8397],{"class":3418,"line":3614},[3416,8398,8399],{},"  В production: заборонено\n",[3416,8401,8402],{"class":3418,"line":3620},[3416,8403,8404],{},"  для operational queries.\n",[3416,8406,8407],{"class":3418,"line":3626},[3416,8408,5088],{},[3416,8410,8411],{"class":3418,"line":3631},[3416,8412,3441],{"emptyLinePlaceholder":3440},[3416,8414,8415],{"class":3418,"line":3636},[3416,8416,8417],{},"note right of Q #d1fae5\n",[3416,8419,8420],{"class":3418,"line":3641},[3416,8421,8422],{},"  Query читає 5 елементів\n",[3416,8424,8425],{"class":3418,"line":3647},[3416,8426,8427],{},"  в 1 партиції.\n",[3416,8429,8430],{"class":3418,"line":3653},[3416,8431,8432],{},"  Час: ~1ms.\n",[3416,8434,8435],{"class":3418,"line":3659},[3416,8436,8437],{},"  Споживає: 5 RCU (або 0.5 RCU\n",[3416,8439,8440],{"class":3418,"line":3665},[3416,8441,8442],{},"  при Eventually Consistent).\n",[3416,8444,8445],{"class":3418,"line":3671},[3416,8446,5088],{},[3416,8448,8449],{"class":3418,"line":3677},[3416,8450,3441],{"emptyLinePlaceholder":3440},[3416,8452,8453],{"class":3418,"line":3683},[3416,8454,3718],{},[8456,8457,8458,8461],"tip",{},[3363,8459,8460],{},"Правило DynamoDB-архітектора:"," якщо ваш застосунок виконує Scan для операційних запитів (тих, що відбуваються у real-time під час роботи користувача) — таблиця спроектована неправильно. Scan є прийнятним лише для одноразових адміністративних операцій (наприклад, міграція даних) або аналітики поза виробничим контуром.",[3727,8463,8465],{"id":8464},"batch-операції-та-транзакції","Batch-операції та транзакції",[3353,8467,8468,8471],{},[3363,8469,8470],{},"BatchGetItem"," — дозволяє отримати до 100 елементів з однієї або кількох таблиць за один API-виклик. Внутрішньо DynamoDB паралелізує читання, тому час виконання близький до часу читання одного елемента.",[6308,8473,8474,8546,8828],{},[6311,8475,8476],{"label":6313},[3406,8477,8479],{"className":6316,"code":8478,"language":6318,"meta":3411,"style":3411},"# Пакетне отримання кількох сесій за один запит\naws dynamodb batch-get-item \\\n    --request-items '{\n        \"UserSessions\": {\n            \"Keys\": [\n                {\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2\"}},\n                {\"UserId\": {\"S\": \"usr-002\"}, \"SessionId\": {\"S\": \"sess-c3d4\"}}\n            ]\n        }\n    }' \\\n    --region eu-central-1\n",[3413,8480,8481,8486,8497,8504,8509,8514,8519,8524,8529,8534,8540],{"__ignoreMap":3411},[3416,8482,8483],{"class":3418,"line":3419},[3416,8484,8485],{"class":3789},"# Пакетне отримання кількох сесій за один запит\n",[3416,8487,8488,8490,8492,8495],{"class":3418,"line":3425},[3416,8489,6331],{"class":6330},[3416,8491,6334],{"class":3808},[3416,8493,8494],{"class":3808}," batch-get-item",[3416,8496,6341],{"class":6340},[3416,8498,8499,8502],{"class":3418,"line":3431},[3416,8500,8501],{"class":4368},"    --request-items",[3416,8503,6661],{"class":3808},[3416,8505,8506],{"class":3418,"line":3437},[3416,8507,8508],{"class":3808},"        \"UserSessions\": {\n",[3416,8510,8511],{"class":3418,"line":3444},[3416,8512,8513],{"class":3808},"            \"Keys\": [\n",[3416,8515,8516],{"class":3418,"line":3450},[3416,8517,8518],{"class":3808},"                {\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2\"}},\n",[3416,8520,8521],{"class":3418,"line":3456},[3416,8522,8523],{"class":3808},"                {\"UserId\": {\"S\": \"usr-002\"}, \"SessionId\": {\"S\": \"sess-c3d4\"}}\n",[3416,8525,8526],{"class":3418,"line":3462},[3416,8527,8528],{"class":3808},"            ]\n",[3416,8530,8531],{"class":3418,"line":3468},[3416,8532,8533],{"class":3808},"        }\n",[3416,8535,8536,8538],{"class":3418,"line":3474},[3416,8537,6686],{"class":3808},[3416,8539,6341],{"class":6340},[3416,8541,8542,8544],{"class":3418,"line":3480},[3416,8543,6366],{"class":4368},[3416,8545,6369],{"class":3808},[6311,8547,8548],{"label":6372},[3406,8549,8551],{"className":6375,"code":8550,"language":6377,"meta":3411,"style":3411},"var response = await client.BatchGetItemAsync(new BatchGetItemRequest\n{\n    RequestItems = new Dictionary\u003Cstring, KeysAndAttributes>\n    {\n        {\n            \"UserSessions\", new KeysAndAttributes\n            {\n                Keys = new List\u003CDictionary\u003Cstring, AttributeValue>>\n                {\n                    new Dictionary\u003Cstring, AttributeValue>\n                    {\n                        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n                        { \"SessionId\", new AttributeValue { S = \"sess-a1b2\" } }\n                    },\n                    new Dictionary\u003Cstring, AttributeValue>\n                    {\n                        { \"UserId\", new AttributeValue { S = \"usr-002\" } },\n                        { \"SessionId\", new AttributeValue { S = \"sess-c3d4\" } }\n                    }\n                }\n            }\n        }\n    }\n});\n",[3413,8552,8553,8577,8581,8603,8607,8612,8624,8629,8657,8662,8679,8684,8707,8730,8735,8751,8755,8778,8801,8806,8811,8816,8820,8824],{"__ignoreMap":3411},[3416,8554,8555,8557,8559,8561,8563,8565,8567,8570,8572,8574],{"class":3418,"line":3419},[3416,8556,6384],{"class":4368},[3416,8558,6408],{"class":6387},[3416,8560,6391],{"class":3795},[3416,8562,6413],{"class":4368},[3416,8564,6388],{"class":6387},[3416,8566,4043],{"class":3795},[3416,8568,8569],{"class":6330},"BatchGetItemAsync",[3416,8571,6423],{"class":3795},[3416,8573,6394],{"class":4368},[3416,8575,8576],{"class":6397}," BatchGetItemRequest\n",[3416,8578,8579],{"class":3418,"line":3425},[3416,8580,3796],{"class":3795},[3416,8582,8583,8586,8588,8590,8592,8594,8596,8598,8601],{"class":3418,"line":3431},[3416,8584,8585],{"class":6387},"    RequestItems",[3416,8587,6391],{"class":3795},[3416,8589,6394],{"class":4368},[3416,8591,6456],{"class":6397},[3416,8593,5861],{"class":3795},[3416,8595,6461],{"class":4368},[3416,8597,4384],{"class":3795},[3416,8599,8600],{"class":6397},"KeysAndAttributes",[3416,8602,6469],{"class":3795},[3416,8604,8605],{"class":3418,"line":3437},[3416,8606,6474],{"class":3795},[3416,8608,8609],{"class":3418,"line":3444},[3416,8610,8611],{"class":3795},"        {\n",[3416,8613,8614,8617,8619,8621],{"class":3418,"line":3450},[3416,8615,8616],{"class":3808},"            \"UserSessions\"",[3416,8618,4384],{"class":3795},[3416,8620,6394],{"class":4368},[3416,8622,8623],{"class":6397}," KeysAndAttributes\n",[3416,8625,8626],{"class":3418,"line":3456},[3416,8627,8628],{"class":3795},"            {\n",[3416,8630,8631,8634,8636,8638,8641,8643,8646,8648,8650,8652,8654],{"class":3418,"line":3462},[3416,8632,8633],{"class":6387},"                Keys",[3416,8635,6391],{"class":3795},[3416,8637,6394],{"class":4368},[3416,8639,8640],{"class":6397}," List",[3416,8642,5861],{"class":3795},[3416,8644,8645],{"class":6397},"Dictionary",[3416,8647,5861],{"class":3795},[3416,8649,6461],{"class":4368},[3416,8651,4384],{"class":3795},[3416,8653,6466],{"class":6397},[3416,8655,8656],{"class":3795},">>\n",[3416,8658,8659],{"class":3418,"line":3468},[3416,8660,8661],{"class":3795},"                {\n",[3416,8663,8664,8667,8669,8671,8673,8675,8677],{"class":3418,"line":3474},[3416,8665,8666],{"class":4368},"                    new",[3416,8668,6456],{"class":6397},[3416,8670,5861],{"class":3795},[3416,8672,6461],{"class":4368},[3416,8674,4384],{"class":3795},[3416,8676,6466],{"class":6397},[3416,8678,6469],{"class":3795},[3416,8680,8681],{"class":3418,"line":3480},[3416,8682,8683],{"class":3795},"                    {\n",[3416,8685,8686,8689,8691,8693,8695,8697,8699,8701,8703,8705],{"class":3418,"line":3486},[3416,8687,8688],{"class":3795},"                        { ",[3416,8690,6482],{"class":3808},[3416,8692,4384],{"class":3795},[3416,8694,6394],{"class":4368},[3416,8696,6489],{"class":6397},[3416,8698,6492],{"class":3795},[3416,8700,6495],{"class":6387},[3416,8702,6391],{"class":3795},[3416,8704,6500],{"class":3808},[3416,8706,6503],{"class":3795},[3416,8708,8709,8711,8713,8715,8717,8719,8721,8723,8725,8728],{"class":3418,"line":3492},[3416,8710,8688],{"class":3795},[3416,8712,6510],{"class":3808},[3416,8714,4384],{"class":3795},[3416,8716,6394],{"class":4368},[3416,8718,6489],{"class":6397},[3416,8720,6492],{"class":3795},[3416,8722,6495],{"class":6387},[3416,8724,6391],{"class":3795},[3416,8726,8727],{"class":3808},"\"sess-a1b2\"",[3416,8729,6528],{"class":3795},[3416,8731,8732],{"class":3418,"line":3498},[3416,8733,8734],{"class":3795},"                    },\n",[3416,8736,8737,8739,8741,8743,8745,8747,8749],{"class":3418,"line":3504},[3416,8738,8666],{"class":4368},[3416,8740,6456],{"class":6397},[3416,8742,5861],{"class":3795},[3416,8744,6461],{"class":4368},[3416,8746,4384],{"class":3795},[3416,8748,6466],{"class":6397},[3416,8750,6469],{"class":3795},[3416,8752,8753],{"class":3418,"line":3510},[3416,8754,8683],{"class":3795},[3416,8756,8757,8759,8761,8763,8765,8767,8769,8771,8773,8776],{"class":3418,"line":3515},[3416,8758,8688],{"class":3795},[3416,8760,6482],{"class":3808},[3416,8762,4384],{"class":3795},[3416,8764,6394],{"class":4368},[3416,8766,6489],{"class":6397},[3416,8768,6492],{"class":3795},[3416,8770,6495],{"class":6387},[3416,8772,6391],{"class":3795},[3416,8774,8775],{"class":3808},"\"usr-002\"",[3416,8777,6503],{"class":3795},[3416,8779,8780,8782,8784,8786,8788,8790,8792,8794,8796,8799],{"class":3418,"line":3521},[3416,8781,8688],{"class":3795},[3416,8783,6510],{"class":3808},[3416,8785,4384],{"class":3795},[3416,8787,6394],{"class":4368},[3416,8789,6489],{"class":6397},[3416,8791,6492],{"class":3795},[3416,8793,6495],{"class":6387},[3416,8795,6391],{"class":3795},[3416,8797,8798],{"class":3808},"\"sess-c3d4\"",[3416,8800,6528],{"class":3795},[3416,8802,8803],{"class":3418,"line":3527},[3416,8804,8805],{"class":3795},"                    }\n",[3416,8807,8808],{"class":3418,"line":3533},[3416,8809,8810],{"class":3795},"                }\n",[3416,8812,8813],{"class":3418,"line":3539},[3416,8814,8815],{"class":3795},"            }\n",[3416,8817,8818],{"class":3418,"line":3545},[3416,8819,8533],{"class":3795},[3416,8821,8822],{"class":3418,"line":3551},[3416,8823,4167],{"class":3795},[3416,8825,8826],{"class":3418,"line":3557},[3416,8827,6537],{"class":3795},[6311,8829,8830],{"label":6540},[3406,8831,8833],{"className":6543,"code":8832,"language":6545,"meta":3411,"style":3411},"# Пакетне отримання кількох елементів за один запит\n$requestItems = @{\n    'UserSessions' = [Amazon.DynamoDBv2.Model.KeysAndAttributes]@{\n        Keys = @(\n            @{ UserId = New-DDBEntry -S 'usr-001'; SessionId = New-DDBEntry -S 'sess-a1b2' },\n            @{ UserId = New-DDBEntry -S 'usr-002'; SessionId = New-DDBEntry -S 'sess-c3d4' }\n        )\n    }\n}\nGet-DDBItemBatch -RequestItems $requestItems -Region eu-central-1\n",[3413,8834,8835,8840,8851,8867,8879,8916,8949,8954,8958,8962],{"__ignoreMap":3411},[3416,8836,8837],{"class":3418,"line":3419},[3416,8838,8839],{"class":3789},"# Пакетне отримання кількох елементів за один запит\n",[3416,8841,8842,8845,8847,8849],{"class":3418,"line":3425},[3416,8843,8844],{"class":6387},"$requestItems",[3416,8846,6391],{"class":3795},[3416,8848,6561],{"class":4368},[3416,8850,3796],{"class":3795},[3416,8852,8853,8856,8858,8861,8863,8865],{"class":3418,"line":3431},[3416,8854,8855],{"class":3808},"    'UserSessions'",[3416,8857,7274],{"class":3795},[3416,8859,8860],{"class":4368},"Amazon.DynamoDBv2.Model.KeysAndAttributes",[3416,8862,7280],{"class":3795},[3416,8864,6561],{"class":4368},[3416,8866,3796],{"class":3795},[3416,8868,8869,8872,8874,8876],{"class":3418,"line":3437},[3416,8870,8871],{"class":6387},"        Keys",[3416,8873,6391],{"class":3795},[3416,8875,6561],{"class":4368},[3416,8877,8878],{"class":3795},"(\n",[3416,8880,8881,8884,8887,8889,8891,8893,8895,8898,8901,8904,8906,8908,8910,8913],{"class":3418,"line":3444},[3416,8882,8883],{"class":4368},"            @",[3416,8885,8886],{"class":3795},"{ ",[3416,8888,4494],{"class":6387},[3416,8890,6391],{"class":3795},[3416,8892,6574],{"class":6330},[3416,8894,6577],{"class":3795},[3416,8896,8897],{"class":3808},"'usr-001'",[3416,8899,8900],{"class":3795},"; ",[3416,8902,8903],{"class":6387},"SessionId",[3416,8905,6391],{"class":3795},[3416,8907,6574],{"class":6330},[3416,8909,6577],{"class":3795},[3416,8911,8912],{"class":3808},"'sess-a1b2'",[3416,8914,8915],{"class":3795}," },\n",[3416,8917,8918,8920,8922,8924,8926,8928,8930,8933,8935,8937,8939,8941,8943,8946],{"class":3418,"line":3450},[3416,8919,8883],{"class":4368},[3416,8921,8886],{"class":3795},[3416,8923,4494],{"class":6387},[3416,8925,6391],{"class":3795},[3416,8927,6574],{"class":6330},[3416,8929,6577],{"class":3795},[3416,8931,8932],{"class":3808},"'usr-002'",[3416,8934,8900],{"class":3795},[3416,8936,8903],{"class":6387},[3416,8938,6391],{"class":3795},[3416,8940,6574],{"class":6330},[3416,8942,6577],{"class":3795},[3416,8944,8945],{"class":3808},"'sess-c3d4'",[3416,8947,8948],{"class":3795}," }\n",[3416,8950,8951],{"class":3418,"line":3456},[3416,8952,8953],{"class":3795},"        )\n",[3416,8955,8956],{"class":3418,"line":3462},[3416,8957,4167],{"class":3795},[3416,8959,8960],{"class":3418,"line":3468},[3416,8961,3507],{"class":3795},[3416,8963,8964,8967,8970,8972,8974],{"class":3418,"line":3474},[3416,8965,8966],{"class":6330},"Get-DDBItemBatch",[3416,8968,8969],{"class":3795}," -RequestItems ",[3416,8971,8844],{"class":6387},[3416,8973,6611],{"class":3795},[3416,8975,6614],{"class":3870},[3353,8977,8978,8981,8982,8985,8986,4043],{},[3363,8979,8980],{},"BatchWriteItem"," — дозволяє записати або видалити до 25 елементів за один виклик. Операції у BatchWriteItem ",[3363,8983,8984],{},"не є атомарними"," — можливий частковий успіх (деякі елементи записані, деякі — ні). Елементи, що не вдалося обробити, повертаються у полі ",[3413,8987,8988],{},"UnprocessedItems",[6308,8990,8991,9120,9469],{},[6311,8992,8993],{"label":6313},[3406,8994,8996],{"className":6316,"code":8995,"language":6318,"meta":3411,"style":3411},"# Пакетний запис та видалення сесій (до 25 операцій)\naws dynamodb batch-write-item \\\n    --request-items '{\n        \"UserSessions\": [\n            {\n                \"PutRequest\": {\n                    \"Item\": {\n                        \"UserId\": {\"S\": \"usr-001\"},\n                        \"SessionId\": {\"S\": \"sess-e5f6\"},\n                        \"IsActive\": {\"BOOL\": true}\n                    }\n                }\n            },\n            {\n                \"DeleteRequest\": {\n                    \"Key\": {\n                        \"UserId\": {\"S\": \"usr-002\"},\n                        \"SessionId\": {\"S\": \"sess-old\"}\n                    }\n                }\n            }\n        ]\n    }' \\\n    --region eu-central-1\n",[3413,8997,8998,9003,9014,9020,9025,9029,9034,9039,9044,9049,9054,9058,9062,9067,9071,9076,9081,9086,9091,9095,9099,9103,9108,9114],{"__ignoreMap":3411},[3416,8999,9000],{"class":3418,"line":3419},[3416,9001,9002],{"class":3789},"# Пакетний запис та видалення сесій (до 25 операцій)\n",[3416,9004,9005,9007,9009,9012],{"class":3418,"line":3425},[3416,9006,6331],{"class":6330},[3416,9008,6334],{"class":3808},[3416,9010,9011],{"class":3808}," batch-write-item",[3416,9013,6341],{"class":6340},[3416,9015,9016,9018],{"class":3418,"line":3431},[3416,9017,8501],{"class":4368},[3416,9019,6661],{"class":3808},[3416,9021,9022],{"class":3418,"line":3437},[3416,9023,9024],{"class":3808},"        \"UserSessions\": [\n",[3416,9026,9027],{"class":3418,"line":3444},[3416,9028,8628],{"class":3808},[3416,9030,9031],{"class":3418,"line":3450},[3416,9032,9033],{"class":3808},"                \"PutRequest\": {\n",[3416,9035,9036],{"class":3418,"line":3456},[3416,9037,9038],{"class":3808},"                    \"Item\": {\n",[3416,9040,9041],{"class":3418,"line":3462},[3416,9042,9043],{"class":3808},"                        \"UserId\": {\"S\": \"usr-001\"},\n",[3416,9045,9046],{"class":3418,"line":3468},[3416,9047,9048],{"class":3808},"                        \"SessionId\": {\"S\": \"sess-e5f6\"},\n",[3416,9050,9051],{"class":3418,"line":3474},[3416,9052,9053],{"class":3808},"                        \"IsActive\": {\"BOOL\": true}\n",[3416,9055,9056],{"class":3418,"line":3480},[3416,9057,8805],{"class":3808},[3416,9059,9060],{"class":3418,"line":3486},[3416,9061,8810],{"class":3808},[3416,9063,9064],{"class":3418,"line":3492},[3416,9065,9066],{"class":3808},"            },\n",[3416,9068,9069],{"class":3418,"line":3498},[3416,9070,8628],{"class":3808},[3416,9072,9073],{"class":3418,"line":3504},[3416,9074,9075],{"class":3808},"                \"DeleteRequest\": {\n",[3416,9077,9078],{"class":3418,"line":3510},[3416,9079,9080],{"class":3808},"                    \"Key\": {\n",[3416,9082,9083],{"class":3418,"line":3515},[3416,9084,9085],{"class":3808},"                        \"UserId\": {\"S\": \"usr-002\"},\n",[3416,9087,9088],{"class":3418,"line":3521},[3416,9089,9090],{"class":3808},"                        \"SessionId\": {\"S\": \"sess-old\"}\n",[3416,9092,9093],{"class":3418,"line":3527},[3416,9094,8805],{"class":3808},[3416,9096,9097],{"class":3418,"line":3533},[3416,9098,8810],{"class":3808},[3416,9100,9101],{"class":3418,"line":3539},[3416,9102,8815],{"class":3808},[3416,9104,9105],{"class":3418,"line":3545},[3416,9106,9107],{"class":3808},"        ]\n",[3416,9109,9110,9112],{"class":3418,"line":3551},[3416,9111,6686],{"class":3808},[3416,9113,6341],{"class":6340},[3416,9115,9116,9118],{"class":3418,"line":3557},[3416,9117,6366],{"class":4368},[3416,9119,6369],{"class":3808},[6311,9121,9122],{"label":6372},[3406,9123,9125],{"className":6375,"code":9124,"language":6377,"meta":3411,"style":3411},"var response = await client.BatchWriteItemAsync(new BatchWriteItemRequest\n{\n    RequestItems = new Dictionary\u003Cstring, List\u003CWriteRequest>>\n    {\n        {\n            \"UserSessions\", new List\u003CWriteRequest>\n            {\n                new WriteRequest\n                {\n                    PutRequest = new PutRequest\n                    {\n                        Item = new Dictionary\u003Cstring, AttributeValue>\n                        {\n                            { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n                            { \"SessionId\", new AttributeValue { S = \"sess-e5f6\" } },\n                            { \"IsActive\", new AttributeValue { BOOL = true } }\n                        }\n                    }\n                },\n                new WriteRequest\n                {\n                    DeleteRequest = new DeleteRequest\n                    {\n                        Key = new Dictionary\u003Cstring, AttributeValue>\n                        {\n                            { \"UserId\", new AttributeValue { S = \"usr-002\" } },\n                            { \"SessionId\", new AttributeValue { S = \"sess-old\" } }\n                        }\n                    }\n                }\n            }\n        }\n    }\n});\n",[3413,9126,9127,9151,9155,9181,9185,9189,9205,9209,9217,9221,9233,9237,9258,9263,9286,9309,9331,9336,9340,9345,9351,9355,9367,9371,9392,9396,9418,9441,9445,9449,9453,9457,9461,9465],{"__ignoreMap":3411},[3416,9128,9129,9131,9133,9135,9137,9139,9141,9144,9146,9148],{"class":3418,"line":3419},[3416,9130,6384],{"class":4368},[3416,9132,6408],{"class":6387},[3416,9134,6391],{"class":3795},[3416,9136,6413],{"class":4368},[3416,9138,6388],{"class":6387},[3416,9140,4043],{"class":3795},[3416,9142,9143],{"class":6330},"BatchWriteItemAsync",[3416,9145,6423],{"class":3795},[3416,9147,6394],{"class":4368},[3416,9149,9150],{"class":6397}," BatchWriteItemRequest\n",[3416,9152,9153],{"class":3418,"line":3425},[3416,9154,3796],{"class":3795},[3416,9156,9157,9159,9161,9163,9165,9167,9169,9171,9174,9176,9179],{"class":3418,"line":3431},[3416,9158,8585],{"class":6387},[3416,9160,6391],{"class":3795},[3416,9162,6394],{"class":4368},[3416,9164,6456],{"class":6397},[3416,9166,5861],{"class":3795},[3416,9168,6461],{"class":4368},[3416,9170,4384],{"class":3795},[3416,9172,9173],{"class":6397},"List",[3416,9175,5861],{"class":3795},[3416,9177,9178],{"class":6397},"WriteRequest",[3416,9180,8656],{"class":3795},[3416,9182,9183],{"class":3418,"line":3437},[3416,9184,6474],{"class":3795},[3416,9186,9187],{"class":3418,"line":3444},[3416,9188,8611],{"class":3795},[3416,9190,9191,9193,9195,9197,9199,9201,9203],{"class":3418,"line":3450},[3416,9192,8616],{"class":3808},[3416,9194,4384],{"class":3795},[3416,9196,6394],{"class":4368},[3416,9198,8640],{"class":6397},[3416,9200,5861],{"class":3795},[3416,9202,9178],{"class":6397},[3416,9204,6469],{"class":3795},[3416,9206,9207],{"class":3418,"line":3456},[3416,9208,8628],{"class":3795},[3416,9210,9211,9214],{"class":3418,"line":3462},[3416,9212,9213],{"class":4368},"                new",[3416,9215,9216],{"class":6397}," WriteRequest\n",[3416,9218,9219],{"class":3418,"line":3468},[3416,9220,8661],{"class":3795},[3416,9222,9223,9226,9228,9230],{"class":3418,"line":3474},[3416,9224,9225],{"class":6387},"                    PutRequest",[3416,9227,6391],{"class":3795},[3416,9229,6394],{"class":4368},[3416,9231,9232],{"class":6397}," PutRequest\n",[3416,9234,9235],{"class":3418,"line":3480},[3416,9236,8683],{"class":3795},[3416,9238,9239,9242,9244,9246,9248,9250,9252,9254,9256],{"class":3418,"line":3486},[3416,9240,9241],{"class":6387},"                        Item",[3416,9243,6391],{"class":3795},[3416,9245,6394],{"class":4368},[3416,9247,6456],{"class":6397},[3416,9249,5861],{"class":3795},[3416,9251,6461],{"class":4368},[3416,9253,4384],{"class":3795},[3416,9255,6466],{"class":6397},[3416,9257,6469],{"class":3795},[3416,9259,9260],{"class":3418,"line":3492},[3416,9261,9262],{"class":3795},"                        {\n",[3416,9264,9265,9268,9270,9272,9274,9276,9278,9280,9282,9284],{"class":3418,"line":3498},[3416,9266,9267],{"class":3795},"                            { ",[3416,9269,6482],{"class":3808},[3416,9271,4384],{"class":3795},[3416,9273,6394],{"class":4368},[3416,9275,6489],{"class":6397},[3416,9277,6492],{"class":3795},[3416,9279,6495],{"class":6387},[3416,9281,6391],{"class":3795},[3416,9283,6500],{"class":3808},[3416,9285,6503],{"class":3795},[3416,9287,9288,9290,9292,9294,9296,9298,9300,9302,9304,9307],{"class":3418,"line":3504},[3416,9289,9267],{"class":3795},[3416,9291,6510],{"class":3808},[3416,9293,4384],{"class":3795},[3416,9295,6394],{"class":4368},[3416,9297,6489],{"class":6397},[3416,9299,6492],{"class":3795},[3416,9301,6495],{"class":6387},[3416,9303,6391],{"class":3795},[3416,9305,9306],{"class":3808},"\"sess-e5f6\"",[3416,9308,6503],{"class":3795},[3416,9310,9311,9313,9315,9317,9319,9321,9323,9325,9327,9329],{"class":3418,"line":3510},[3416,9312,9267],{"class":3795},[3416,9314,6839],{"class":3808},[3416,9316,4384],{"class":3795},[3416,9318,6394],{"class":4368},[3416,9320,6489],{"class":6397},[3416,9322,6492],{"class":3795},[3416,9324,6850],{"class":6387},[3416,9326,6391],{"class":3795},[3416,9328,4038],{"class":4368},[3416,9330,6528],{"class":3795},[3416,9332,9333],{"class":3418,"line":3515},[3416,9334,9335],{"class":3795},"                        }\n",[3416,9337,9338],{"class":3418,"line":3521},[3416,9339,8805],{"class":3795},[3416,9341,9342],{"class":3418,"line":3527},[3416,9343,9344],{"class":3795},"                },\n",[3416,9346,9347,9349],{"class":3418,"line":3533},[3416,9348,9213],{"class":4368},[3416,9350,9216],{"class":6397},[3416,9352,9353],{"class":3418,"line":3539},[3416,9354,8661],{"class":3795},[3416,9356,9357,9360,9362,9364],{"class":3418,"line":3545},[3416,9358,9359],{"class":6387},"                    DeleteRequest",[3416,9361,6391],{"class":3795},[3416,9363,6394],{"class":4368},[3416,9365,9366],{"class":6397}," DeleteRequest\n",[3416,9368,9369],{"class":3418,"line":3551},[3416,9370,8683],{"class":3795},[3416,9372,9373,9376,9378,9380,9382,9384,9386,9388,9390],{"class":3418,"line":3557},[3416,9374,9375],{"class":6387},"                        Key",[3416,9377,6391],{"class":3795},[3416,9379,6394],{"class":4368},[3416,9381,6456],{"class":6397},[3416,9383,5861],{"class":3795},[3416,9385,6461],{"class":4368},[3416,9387,4384],{"class":3795},[3416,9389,6466],{"class":6397},[3416,9391,6469],{"class":3795},[3416,9393,9394],{"class":3418,"line":3563},[3416,9395,9262],{"class":3795},[3416,9397,9398,9400,9402,9404,9406,9408,9410,9412,9414,9416],{"class":3418,"line":3569},[3416,9399,9267],{"class":3795},[3416,9401,6482],{"class":3808},[3416,9403,4384],{"class":3795},[3416,9405,6394],{"class":4368},[3416,9407,6489],{"class":6397},[3416,9409,6492],{"class":3795},[3416,9411,6495],{"class":6387},[3416,9413,6391],{"class":3795},[3416,9415,8775],{"class":3808},[3416,9417,6503],{"class":3795},[3416,9419,9420,9422,9424,9426,9428,9430,9432,9434,9436,9439],{"class":3418,"line":3574},[3416,9421,9267],{"class":3795},[3416,9423,6510],{"class":3808},[3416,9425,4384],{"class":3795},[3416,9427,6394],{"class":4368},[3416,9429,6489],{"class":6397},[3416,9431,6492],{"class":3795},[3416,9433,6495],{"class":6387},[3416,9435,6391],{"class":3795},[3416,9437,9438],{"class":3808},"\"sess-old\"",[3416,9440,6528],{"class":3795},[3416,9442,9443],{"class":3418,"line":3579},[3416,9444,9335],{"class":3795},[3416,9446,9447],{"class":3418,"line":3584},[3416,9448,8805],{"class":3795},[3416,9450,9451],{"class":3418,"line":3590},[3416,9452,8810],{"class":3795},[3416,9454,9455],{"class":3418,"line":3596},[3416,9456,8815],{"class":3795},[3416,9458,9459],{"class":3418,"line":3602},[3416,9460,8533],{"class":3795},[3416,9462,9463],{"class":3418,"line":3608},[3416,9464,4167],{"class":3795},[3416,9466,9467],{"class":3418,"line":3614},[3416,9468,6537],{"class":3795},[6311,9470,9471],{"label":6540},[3406,9472,9474],{"className":6543,"code":9473,"language":6545,"meta":3411,"style":3411},"# Пакетний запис та видалення кількох елементів\n$writeRequests = @(\n    [Amazon.DynamoDBv2.Model.WriteRequest]@{\n        PutRequest = @{\n            Item = @{\n                UserId    = New-DDBEntry -S 'usr-001'\n                SessionId = New-DDBEntry -S 'sess-e5f6'\n                IsActive  = New-DDBEntry -BOOL $true\n            }\n        }\n    },\n    [Amazon.DynamoDBv2.Model.WriteRequest]@{\n        DeleteRequest = @{\n            Key = @{\n                UserId    = New-DDBEntry -S 'usr-002'\n                SessionId = New-DDBEntry -S 'sess-old'\n            }\n        }\n    }\n)\n$requestItems = @{ 'UserSessions' = $writeRequests }\nWrite-DDBItemBatch -RequestItems $requestItems -Region eu-central-1\n",[3413,9475,9476,9481,9492,9506,9517,9528,9541,9555,9568,9572,9576,9580,9592,9603,9614,9627,9640,9644,9648,9652,9657,9676],{"__ignoreMap":3411},[3416,9477,9478],{"class":3418,"line":3419},[3416,9479,9480],{"class":3789},"# Пакетний запис та видалення кількох елементів\n",[3416,9482,9483,9486,9488,9490],{"class":3418,"line":3425},[3416,9484,9485],{"class":6387},"$writeRequests",[3416,9487,6391],{"class":3795},[3416,9489,6561],{"class":4368},[3416,9491,8878],{"class":3795},[3416,9493,9494,9497,9500,9502,9504],{"class":3418,"line":3431},[3416,9495,9496],{"class":3795},"    [",[3416,9498,9499],{"class":4368},"Amazon.DynamoDBv2.Model.WriteRequest",[3416,9501,7280],{"class":3795},[3416,9503,6561],{"class":4368},[3416,9505,3796],{"class":3795},[3416,9507,9508,9511,9513,9515],{"class":3418,"line":3437},[3416,9509,9510],{"class":6387},"        PutRequest",[3416,9512,6391],{"class":3795},[3416,9514,6561],{"class":4368},[3416,9516,3796],{"class":3795},[3416,9518,9519,9522,9524,9526],{"class":3418,"line":3444},[3416,9520,9521],{"class":6387},"            Item",[3416,9523,6391],{"class":3795},[3416,9525,6561],{"class":4368},[3416,9527,3796],{"class":3795},[3416,9529,9530,9533,9535,9537,9539],{"class":3418,"line":3450},[3416,9531,9532],{"class":6387},"                UserId",[3416,9534,6571],{"class":3795},[3416,9536,6574],{"class":6330},[3416,9538,6577],{"class":3795},[3416,9540,6580],{"class":3808},[3416,9542,9543,9546,9548,9550,9552],{"class":3418,"line":3456},[3416,9544,9545],{"class":6387},"                SessionId",[3416,9547,6391],{"class":3795},[3416,9549,6574],{"class":6330},[3416,9551,6577],{"class":3795},[3416,9553,9554],{"class":3808},"'sess-e5f6'\n",[3416,9556,9557,9560,9562,9564,9566],{"class":3418,"line":3462},[3416,9558,9559],{"class":6387},"                IsActive",[3416,9561,6933],{"class":3795},[3416,9563,6574],{"class":6330},[3416,9565,6938],{"class":3795},[3416,9567,6941],{"class":4368},[3416,9569,9570],{"class":3418,"line":3468},[3416,9571,8815],{"class":3795},[3416,9573,9574],{"class":3418,"line":3474},[3416,9575,8533],{"class":3795},[3416,9577,9578],{"class":3418,"line":3480},[3416,9579,4442],{"class":3795},[3416,9581,9582,9584,9586,9588,9590],{"class":3418,"line":3486},[3416,9583,9496],{"class":3795},[3416,9585,9499],{"class":4368},[3416,9587,7280],{"class":3795},[3416,9589,6561],{"class":4368},[3416,9591,3796],{"class":3795},[3416,9593,9594,9597,9599,9601],{"class":3418,"line":3492},[3416,9595,9596],{"class":6387},"        DeleteRequest",[3416,9598,6391],{"class":3795},[3416,9600,6561],{"class":4368},[3416,9602,3796],{"class":3795},[3416,9604,9605,9608,9610,9612],{"class":3418,"line":3498},[3416,9606,9607],{"class":6387},"            Key",[3416,9609,6391],{"class":3795},[3416,9611,6561],{"class":4368},[3416,9613,3796],{"class":3795},[3416,9615,9616,9618,9620,9622,9624],{"class":3418,"line":3504},[3416,9617,9532],{"class":6387},[3416,9619,6571],{"class":3795},[3416,9621,6574],{"class":6330},[3416,9623,6577],{"class":3795},[3416,9625,9626],{"class":3808},"'usr-002'\n",[3416,9628,9629,9631,9633,9635,9637],{"class":3418,"line":3510},[3416,9630,9545],{"class":6387},[3416,9632,6391],{"class":3795},[3416,9634,6574],{"class":6330},[3416,9636,6577],{"class":3795},[3416,9638,9639],{"class":3808},"'sess-old'\n",[3416,9641,9642],{"class":3418,"line":3515},[3416,9643,8815],{"class":3795},[3416,9645,9646],{"class":3418,"line":3521},[3416,9647,8533],{"class":3795},[3416,9649,9650],{"class":3418,"line":3527},[3416,9651,4167],{"class":3795},[3416,9653,9654],{"class":3418,"line":3533},[3416,9655,9656],{"class":3795},")\n",[3416,9658,9659,9661,9663,9665,9667,9670,9672,9674],{"class":3418,"line":3539},[3416,9660,8844],{"class":6387},[3416,9662,6391],{"class":3795},[3416,9664,6561],{"class":4368},[3416,9666,8886],{"class":3795},[3416,9668,9669],{"class":3808},"'UserSessions'",[3416,9671,6391],{"class":3795},[3416,9673,9485],{"class":6387},[3416,9675,8948],{"class":3795},[3416,9677,9678,9681,9683,9685,9687],{"class":3418,"line":3545},[3416,9679,9680],{"class":6330},"Write-DDBItemBatch",[3416,9682,8969],{"class":3795},[3416,9684,8844],{"class":6387},[3416,9686,6611],{"class":3795},[3416,9688,6614],{"class":3870},[3353,9690,9691,9694],{},[3363,9692,9693],{},"TransactWriteItems \u002F TransactGetItems"," — атомарні транзакції через кілька елементів і таблиць (детально розглянемо у відповідному розділі).",[6308,9696,9697,9825,10196],{},[6311,9698,9699],{"label":6313},[3406,9700,9702],{"className":6316,"code":9701,"language":6318,"meta":3411,"style":3411},"# Атомарна транзакція: запис нової сесії та збільшення лічильника сесій користувача\naws dynamodb transact-write-items \\\n    --transact-items '[\n        {\n            \"Put\": {\n                \"TableName\": \"UserSessions\",\n                \"Item\": {\n                    \"UserId\":    {\"S\": \"usr-001\"},\n                    \"SessionId\": {\"S\": \"sess-new\"},\n                    \"IsActive\":  {\"BOOL\": true}\n                }\n            }\n        },\n        {\n            \"Update\": {\n                \"TableName\": \"Users\",\n                \"Key\": {\"UserId\": {\"S\": \"usr-001\"}},\n                \"UpdateExpression\": \"ADD ActiveSessionsCount :one\",\n                \"ExpressionAttributeValues\": {\":one\": {\"N\": \"1\"}}\n            }\n        }\n    ]' \\\n    --region eu-central-1\n",[3413,9703,9704,9709,9720,9728,9732,9737,9742,9747,9752,9757,9762,9766,9770,9775,9779,9784,9789,9794,9799,9804,9808,9812,9819],{"__ignoreMap":3411},[3416,9705,9706],{"class":3418,"line":3419},[3416,9707,9708],{"class":3789},"# Атомарна транзакція: запис нової сесії та збільшення лічильника сесій користувача\n",[3416,9710,9711,9713,9715,9718],{"class":3418,"line":3425},[3416,9712,6331],{"class":6330},[3416,9714,6334],{"class":3808},[3416,9716,9717],{"class":3808}," transact-write-items",[3416,9719,6341],{"class":6340},[3416,9721,9722,9725],{"class":3418,"line":3431},[3416,9723,9724],{"class":4368},"    --transact-items",[3416,9726,9727],{"class":3808}," '[\n",[3416,9729,9730],{"class":3418,"line":3437},[3416,9731,8611],{"class":3808},[3416,9733,9734],{"class":3418,"line":3444},[3416,9735,9736],{"class":3808},"            \"Put\": {\n",[3416,9738,9739],{"class":3418,"line":3450},[3416,9740,9741],{"class":3808},"                \"TableName\": \"UserSessions\",\n",[3416,9743,9744],{"class":3418,"line":3456},[3416,9745,9746],{"class":3808},"                \"Item\": {\n",[3416,9748,9749],{"class":3418,"line":3462},[3416,9750,9751],{"class":3808},"                    \"UserId\":    {\"S\": \"usr-001\"},\n",[3416,9753,9754],{"class":3418,"line":3468},[3416,9755,9756],{"class":3808},"                    \"SessionId\": {\"S\": \"sess-new\"},\n",[3416,9758,9759],{"class":3418,"line":3474},[3416,9760,9761],{"class":3808},"                    \"IsActive\":  {\"BOOL\": true}\n",[3416,9763,9764],{"class":3418,"line":3480},[3416,9765,8810],{"class":3808},[3416,9767,9768],{"class":3418,"line":3486},[3416,9769,8815],{"class":3808},[3416,9771,9772],{"class":3418,"line":3492},[3416,9773,9774],{"class":3808},"        },\n",[3416,9776,9777],{"class":3418,"line":3498},[3416,9778,8611],{"class":3808},[3416,9780,9781],{"class":3418,"line":3504},[3416,9782,9783],{"class":3808},"            \"Update\": {\n",[3416,9785,9786],{"class":3418,"line":3510},[3416,9787,9788],{"class":3808},"                \"TableName\": \"Users\",\n",[3416,9790,9791],{"class":3418,"line":3515},[3416,9792,9793],{"class":3808},"                \"Key\": {\"UserId\": {\"S\": \"usr-001\"}},\n",[3416,9795,9796],{"class":3418,"line":3521},[3416,9797,9798],{"class":3808},"                \"UpdateExpression\": \"ADD ActiveSessionsCount :one\",\n",[3416,9800,9801],{"class":3418,"line":3527},[3416,9802,9803],{"class":3808},"                \"ExpressionAttributeValues\": {\":one\": {\"N\": \"1\"}}\n",[3416,9805,9806],{"class":3418,"line":3533},[3416,9807,8815],{"class":3808},[3416,9809,9810],{"class":3418,"line":3539},[3416,9811,8533],{"class":3808},[3416,9813,9814,9817],{"class":3418,"line":3545},[3416,9815,9816],{"class":3808},"    ]'",[3416,9818,6341],{"class":6340},[3416,9820,9821,9823],{"class":3418,"line":3551},[3416,9822,6366],{"class":4368},[3416,9824,6369],{"class":3808},[6311,9826,9827],{"label":6372},[3406,9828,9830],{"className":6375,"code":9829,"language":6377,"meta":3411,"style":3411},"var response = await client.TransactWriteItemsAsync(new TransactWriteItemsRequest\n{\n    TransactItems = new List\u003CTransactWriteItem>\n    {\n        new TransactWriteItem\n        {\n            Put = new Put\n            {\n                TableName = \"UserSessions\",\n                Item = new Dictionary\u003Cstring, AttributeValue>\n                {\n                    { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n                    { \"SessionId\", new AttributeValue { S = \"sess-new\" } },\n                    { \"IsActive\", new AttributeValue { BOOL = true } }\n                }\n            }\n        },\n        new TransactWriteItem\n        {\n            Update = new Update\n            {\n                TableName = \"Users\",\n                Key = new Dictionary\u003Cstring, AttributeValue>\n                {\n                    { \"UserId\", new AttributeValue { S = \"usr-001\" } }\n                },\n                UpdateExpression = \"ADD ActiveSessionsCount :one\",\n                ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n                {\n                    { \":one\", new AttributeValue { N = \"1\" } }\n                }\n            }\n        }\n    }\n});\n",[3413,9831,9832,9856,9860,9878,9882,9890,9894,9906,9910,9921,9942,9946,9969,9992,10014,10018,10022,10026,10032,10036,10048,10052,10063,10084,10088,10110,10114,10126,10147,10151,10176,10180,10184,10188,10192],{"__ignoreMap":3411},[3416,9833,9834,9836,9838,9840,9842,9844,9846,9849,9851,9853],{"class":3418,"line":3419},[3416,9835,6384],{"class":4368},[3416,9837,6408],{"class":6387},[3416,9839,6391],{"class":3795},[3416,9841,6413],{"class":4368},[3416,9843,6388],{"class":6387},[3416,9845,4043],{"class":3795},[3416,9847,9848],{"class":6330},"TransactWriteItemsAsync",[3416,9850,6423],{"class":3795},[3416,9852,6394],{"class":4368},[3416,9854,9855],{"class":6397}," TransactWriteItemsRequest\n",[3416,9857,9858],{"class":3418,"line":3425},[3416,9859,3796],{"class":3795},[3416,9861,9862,9865,9867,9869,9871,9873,9876],{"class":3418,"line":3431},[3416,9863,9864],{"class":6387},"    TransactItems",[3416,9866,6391],{"class":3795},[3416,9868,6394],{"class":4368},[3416,9870,8640],{"class":6397},[3416,9872,5861],{"class":3795},[3416,9874,9875],{"class":6397},"TransactWriteItem",[3416,9877,6469],{"class":3795},[3416,9879,9880],{"class":3418,"line":3437},[3416,9881,6474],{"class":3795},[3416,9883,9884,9887],{"class":3418,"line":3444},[3416,9885,9886],{"class":4368},"        new",[3416,9888,9889],{"class":6397}," TransactWriteItem\n",[3416,9891,9892],{"class":3418,"line":3450},[3416,9893,8611],{"class":3795},[3416,9895,9896,9899,9901,9903],{"class":3418,"line":3456},[3416,9897,9898],{"class":6387},"            Put",[3416,9900,6391],{"class":3795},[3416,9902,6394],{"class":4368},[3416,9904,9905],{"class":6397}," Put\n",[3416,9907,9908],{"class":3418,"line":3462},[3416,9909,8628],{"class":3795},[3416,9911,9912,9915,9917,9919],{"class":3418,"line":3468},[3416,9913,9914],{"class":6387},"                TableName",[3416,9916,6391],{"class":3795},[3416,9918,6442],{"class":3808},[3416,9920,3812],{"class":3795},[3416,9922,9923,9926,9928,9930,9932,9934,9936,9938,9940],{"class":3418,"line":3474},[3416,9924,9925],{"class":6387},"                Item",[3416,9927,6391],{"class":3795},[3416,9929,6394],{"class":4368},[3416,9931,6456],{"class":6397},[3416,9933,5861],{"class":3795},[3416,9935,6461],{"class":4368},[3416,9937,4384],{"class":3795},[3416,9939,6466],{"class":6397},[3416,9941,6469],{"class":3795},[3416,9943,9944],{"class":3418,"line":3480},[3416,9945,8661],{"class":3795},[3416,9947,9948,9951,9953,9955,9957,9959,9961,9963,9965,9967],{"class":3418,"line":3486},[3416,9949,9950],{"class":3795},"                    { ",[3416,9952,6482],{"class":3808},[3416,9954,4384],{"class":3795},[3416,9956,6394],{"class":4368},[3416,9958,6489],{"class":6397},[3416,9960,6492],{"class":3795},[3416,9962,6495],{"class":6387},[3416,9964,6391],{"class":3795},[3416,9966,6500],{"class":3808},[3416,9968,6503],{"class":3795},[3416,9970,9971,9973,9975,9977,9979,9981,9983,9985,9987,9990],{"class":3418,"line":3492},[3416,9972,9950],{"class":3795},[3416,9974,6510],{"class":3808},[3416,9976,4384],{"class":3795},[3416,9978,6394],{"class":4368},[3416,9980,6489],{"class":6397},[3416,9982,6492],{"class":3795},[3416,9984,6495],{"class":6387},[3416,9986,6391],{"class":3795},[3416,9988,9989],{"class":3808},"\"sess-new\"",[3416,9991,6503],{"class":3795},[3416,9993,9994,9996,9998,10000,10002,10004,10006,10008,10010,10012],{"class":3418,"line":3498},[3416,9995,9950],{"class":3795},[3416,9997,6839],{"class":3808},[3416,9999,4384],{"class":3795},[3416,10001,6394],{"class":4368},[3416,10003,6489],{"class":6397},[3416,10005,6492],{"class":3795},[3416,10007,6850],{"class":6387},[3416,10009,6391],{"class":3795},[3416,10011,4038],{"class":4368},[3416,10013,6528],{"class":3795},[3416,10015,10016],{"class":3418,"line":3504},[3416,10017,8810],{"class":3795},[3416,10019,10020],{"class":3418,"line":3510},[3416,10021,8815],{"class":3795},[3416,10023,10024],{"class":3418,"line":3515},[3416,10025,9774],{"class":3795},[3416,10027,10028,10030],{"class":3418,"line":3521},[3416,10029,9886],{"class":4368},[3416,10031,9889],{"class":6397},[3416,10033,10034],{"class":3418,"line":3527},[3416,10035,8611],{"class":3795},[3416,10037,10038,10041,10043,10045],{"class":3418,"line":3533},[3416,10039,10040],{"class":6387},"            Update",[3416,10042,6391],{"class":3795},[3416,10044,6394],{"class":4368},[3416,10046,10047],{"class":6397}," Update\n",[3416,10049,10050],{"class":3418,"line":3539},[3416,10051,8628],{"class":3795},[3416,10053,10054,10056,10058,10061],{"class":3418,"line":3545},[3416,10055,9914],{"class":6387},[3416,10057,6391],{"class":3795},[3416,10059,10060],{"class":3808},"\"Users\"",[3416,10062,3812],{"class":3795},[3416,10064,10065,10068,10070,10072,10074,10076,10078,10080,10082],{"class":3418,"line":3551},[3416,10066,10067],{"class":6387},"                Key",[3416,10069,6391],{"class":3795},[3416,10071,6394],{"class":4368},[3416,10073,6456],{"class":6397},[3416,10075,5861],{"class":3795},[3416,10077,6461],{"class":4368},[3416,10079,4384],{"class":3795},[3416,10081,6466],{"class":6397},[3416,10083,6469],{"class":3795},[3416,10085,10086],{"class":3418,"line":3557},[3416,10087,8661],{"class":3795},[3416,10089,10090,10092,10094,10096,10098,10100,10102,10104,10106,10108],{"class":3418,"line":3563},[3416,10091,9950],{"class":3795},[3416,10093,6482],{"class":3808},[3416,10095,4384],{"class":3795},[3416,10097,6394],{"class":4368},[3416,10099,6489],{"class":6397},[3416,10101,6492],{"class":3795},[3416,10103,6495],{"class":6387},[3416,10105,6391],{"class":3795},[3416,10107,6500],{"class":3808},[3416,10109,6528],{"class":3795},[3416,10111,10112],{"class":3418,"line":3569},[3416,10113,9344],{"class":3795},[3416,10115,10116,10119,10121,10124],{"class":3418,"line":3574},[3416,10117,10118],{"class":6387},"                UpdateExpression",[3416,10120,6391],{"class":3795},[3416,10122,10123],{"class":3808},"\"ADD ActiveSessionsCount :one\"",[3416,10125,3812],{"class":3795},[3416,10127,10128,10131,10133,10135,10137,10139,10141,10143,10145],{"class":3418,"line":3579},[3416,10129,10130],{"class":6387},"                ExpressionAttributeValues",[3416,10132,6391],{"class":3795},[3416,10134,6394],{"class":4368},[3416,10136,6456],{"class":6397},[3416,10138,5861],{"class":3795},[3416,10140,6461],{"class":4368},[3416,10142,4384],{"class":3795},[3416,10144,6466],{"class":6397},[3416,10146,6469],{"class":3795},[3416,10148,10149],{"class":3418,"line":3584},[3416,10150,8661],{"class":3795},[3416,10152,10153,10155,10158,10160,10162,10164,10166,10169,10171,10174],{"class":3418,"line":3590},[3416,10154,9950],{"class":3795},[3416,10156,10157],{"class":3808},"\":one\"",[3416,10159,4384],{"class":3795},[3416,10161,6394],{"class":4368},[3416,10163,6489],{"class":6397},[3416,10165,6492],{"class":3795},[3416,10167,10168],{"class":6387},"N",[3416,10170,6391],{"class":3795},[3416,10172,10173],{"class":3808},"\"1\"",[3416,10175,6528],{"class":3795},[3416,10177,10178],{"class":3418,"line":3596},[3416,10179,8810],{"class":3795},[3416,10181,10182],{"class":3418,"line":3602},[3416,10183,8815],{"class":3795},[3416,10185,10186],{"class":3418,"line":3608},[3416,10187,8533],{"class":3795},[3416,10189,10190],{"class":3418,"line":3614},[3416,10191,4167],{"class":3795},[3416,10193,10194],{"class":3418,"line":3620},[3416,10195,6537],{"class":3795},[6311,10197,10198],{"label":6540},[3406,10199,10201],{"className":6543,"code":10200,"language":6545,"meta":3411,"style":3411},"# Атомарна транзакція з кількох операцій запису\u002Fоновлення\n$transactItems = @(\n    [Amazon.DynamoDBv2.Model.TransactWriteItem]@{\n        Put = @{\n            TableName = 'UserSessions'\n            Item = @{\n                UserId    = New-DDBEntry -S 'usr-001'\n                SessionId = New-DDBEntry -S 'sess-new'\n                IsActive  = New-DDBEntry -BOOL $true\n            }\n        }\n    },\n    [Amazon.DynamoDBv2.Model.TransactWriteItem]@{\n        Update = @{\n            TableName = 'Users'\n            Key = @{ UserId = New-DDBEntry -S 'usr-001' }\n            UpdateExpression = 'ADD ActiveSessionsCount :one'\n            ExpressionAttributeValues = @{ ':one' = New-DDBEntry -N '1' }\n        }\n    }\n)\nSubmit-DDBTransactWriteItems -TransactItem $transactItems -Region eu-central-1\n",[3413,10202,10203,10208,10219,10232,10243,10252,10262,10274,10287,10299,10303,10307,10311,10323,10334,10343,10365,10375,10401,10405,10409,10413],{"__ignoreMap":3411},[3416,10204,10205],{"class":3418,"line":3419},[3416,10206,10207],{"class":3789},"# Атомарна транзакція з кількох операцій запису\u002Fоновлення\n",[3416,10209,10210,10213,10215,10217],{"class":3418,"line":3425},[3416,10211,10212],{"class":6387},"$transactItems",[3416,10214,6391],{"class":3795},[3416,10216,6561],{"class":4368},[3416,10218,8878],{"class":3795},[3416,10220,10221,10223,10226,10228,10230],{"class":3418,"line":3431},[3416,10222,9496],{"class":3795},[3416,10224,10225],{"class":4368},"Amazon.DynamoDBv2.Model.TransactWriteItem",[3416,10227,7280],{"class":3795},[3416,10229,6561],{"class":4368},[3416,10231,3796],{"class":3795},[3416,10233,10234,10237,10239,10241],{"class":3418,"line":3437},[3416,10235,10236],{"class":6387},"        Put",[3416,10238,6391],{"class":3795},[3416,10240,6561],{"class":4368},[3416,10242,3796],{"class":3795},[3416,10244,10245,10248,10250],{"class":3418,"line":3444},[3416,10246,10247],{"class":6387},"            TableName",[3416,10249,6391],{"class":3795},[3416,10251,7293],{"class":3808},[3416,10253,10254,10256,10258,10260],{"class":3418,"line":3450},[3416,10255,9521],{"class":6387},[3416,10257,6391],{"class":3795},[3416,10259,6561],{"class":4368},[3416,10261,3796],{"class":3795},[3416,10263,10264,10266,10268,10270,10272],{"class":3418,"line":3456},[3416,10265,9532],{"class":6387},[3416,10267,6571],{"class":3795},[3416,10269,6574],{"class":6330},[3416,10271,6577],{"class":3795},[3416,10273,6580],{"class":3808},[3416,10275,10276,10278,10280,10282,10284],{"class":3418,"line":3462},[3416,10277,9545],{"class":6387},[3416,10279,6391],{"class":3795},[3416,10281,6574],{"class":6330},[3416,10283,6577],{"class":3795},[3416,10285,10286],{"class":3808},"'sess-new'\n",[3416,10288,10289,10291,10293,10295,10297],{"class":3418,"line":3468},[3416,10290,9559],{"class":6387},[3416,10292,6933],{"class":3795},[3416,10294,6574],{"class":6330},[3416,10296,6938],{"class":3795},[3416,10298,6941],{"class":4368},[3416,10300,10301],{"class":3418,"line":3474},[3416,10302,8815],{"class":3795},[3416,10304,10305],{"class":3418,"line":3480},[3416,10306,8533],{"class":3795},[3416,10308,10309],{"class":3418,"line":3486},[3416,10310,4442],{"class":3795},[3416,10312,10313,10315,10317,10319,10321],{"class":3418,"line":3492},[3416,10314,9496],{"class":3795},[3416,10316,10225],{"class":4368},[3416,10318,7280],{"class":3795},[3416,10320,6561],{"class":4368},[3416,10322,3796],{"class":3795},[3416,10324,10325,10328,10330,10332],{"class":3418,"line":3498},[3416,10326,10327],{"class":6387},"        Update",[3416,10329,6391],{"class":3795},[3416,10331,6561],{"class":4368},[3416,10333,3796],{"class":3795},[3416,10335,10336,10338,10340],{"class":3418,"line":3504},[3416,10337,10247],{"class":6387},[3416,10339,6391],{"class":3795},[3416,10341,10342],{"class":3808},"'Users'\n",[3416,10344,10345,10347,10349,10351,10353,10355,10357,10359,10361,10363],{"class":3418,"line":3510},[3416,10346,9607],{"class":6387},[3416,10348,6391],{"class":3795},[3416,10350,6561],{"class":4368},[3416,10352,8886],{"class":3795},[3416,10354,4494],{"class":6387},[3416,10356,6391],{"class":3795},[3416,10358,6574],{"class":6330},[3416,10360,6577],{"class":3795},[3416,10362,8897],{"class":3808},[3416,10364,8948],{"class":3795},[3416,10366,10367,10370,10372],{"class":3418,"line":3515},[3416,10368,10369],{"class":6387},"            UpdateExpression",[3416,10371,6391],{"class":3795},[3416,10373,10374],{"class":3808},"'ADD ActiveSessionsCount :one'\n",[3416,10376,10377,10380,10382,10384,10386,10389,10391,10393,10396,10399],{"class":3418,"line":3521},[3416,10378,10379],{"class":6387},"            ExpressionAttributeValues",[3416,10381,6391],{"class":3795},[3416,10383,6561],{"class":4368},[3416,10385,8886],{"class":3795},[3416,10387,10388],{"class":3808},"':one'",[3416,10390,6391],{"class":3795},[3416,10392,6574],{"class":6330},[3416,10394,10395],{"class":3795}," -N ",[3416,10397,10398],{"class":3808},"'1'",[3416,10400,8948],{"class":3795},[3416,10402,10403],{"class":3418,"line":3527},[3416,10404,8533],{"class":3795},[3416,10406,10407],{"class":3418,"line":3533},[3416,10408,4167],{"class":3795},[3416,10410,10411],{"class":3418,"line":3539},[3416,10412,9656],{"class":3795},[3416,10414,10415,10418,10421,10423,10425],{"class":3418,"line":3545},[3416,10416,10417],{"class":6330},"Submit-DDBTransactWriteItems",[3416,10419,10420],{"class":3795}," -TransactItem ",[3416,10422,10212],{"class":6387},[3416,10424,6611],{"class":3795},[3416,10426,6614],{"class":3870},[3720,10428],{},[3348,10430,10432],{"id":10431},"створення-таблиці-dynamodb-консоль-та-aws-cli","Створення таблиці DynamoDB: консоль та AWS CLI",[3727,10434,10436],{"id":10435},"консоль-aws-management-console","Консоль AWS Management Console",[3353,10438,10439,10440,10443,10444,10443,10447,4043],{},"Найпростіший спосіб ознайомитися з DynamoDB — створити таблицю через web-консоль. Перейдіть до сервісу ",[3363,10441,10442],{},"DynamoDB"," → ",[3363,10445,10446],{},"Tables",[3363,10448,10449],{},"Create table",[3353,10451,10452],{},[3363,10453,10454,10455,10458],{},"Кроки створення таблиці ",[3413,10456,10457],{},"UserSessions",":",[3374,10460,10461,10469,10477,10488,10498],{},[3377,10462,10463,10466,10467],{},[3363,10464,10465],{},"Table name:"," ",[3413,10468,10457],{},[3377,10470,10471,10466,10474,10476],{},[3363,10472,10473],{},"Partition key:",[3413,10475,4494],{}," (тип String)",[3377,10478,10479,10466,10482,10484,10485],{},[3363,10480,10481],{},"Sort key:",[3413,10483,8903],{}," (тип String) ",[4091,10486,10487],{},"(необов'язково, але рекомендовано)",[3377,10489,10490,10493,10494,10497],{},[3363,10491,10492],{},"Table settings:"," для початку — ",[3363,10495,10496],{},"Default settings"," (On-Demand capacity mode)",[3377,10499,10500],{},[3363,10501,10449],{},[3403,10503,10504],{},[3406,10505,10507],{"className":3408,"code":10506,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Таблиця UserSessions: схема з Composite Primary Key\"\n\nclass \"UserSessions\" as T {\n    **PK: UserId** (S)\n    **SK: SessionId** (S)\n    ──────────────────────\n    CreatedAt: String (ISO8601)\n    ExpiresAt: String (ISO8601)\n    UserAgent: String\n    IpAddress: String\n    IsActive: Boolean\n    DeviceInfo: Map\n    Permissions: StringSet\n}\n\nnote right of T\n  PK + SK = Composite Primary Key\n  ─────────────────────────────\n  Запит: \"всі активні сесії usr-001\"\n  → Query(PK=\"usr-001\")\n  → Filter(IsActive=true)\n\n  Запит: \"конкретна сесія\"\n  → GetItem(PK=\"usr-001\", SK=\"sess-XYZ\")\n\n  Запит: \"сесії із закінченим терміном\"\n  → потребує GSI (розглянемо далі)\nend note\n\n@enduml\n",[3413,10508,10509,10513,10517,10521,10525,10530,10534,10539,10544,10549,10554,10559,10564,10569,10574,10579,10584,10589,10593,10597,10602,10607,10612,10617,10622,10627,10631,10636,10641,10645,10650,10655,10659,10663],{"__ignoreMap":3411},[3416,10510,10511],{"class":3418,"line":3419},[3416,10512,3422],{},[3416,10514,10515],{"class":3418,"line":3425},[3416,10516,3428],{},[3416,10518,10519],{"class":3418,"line":3431},[3416,10520,3434],{},[3416,10522,10523],{"class":3418,"line":3437},[3416,10524,3441],{"emptyLinePlaceholder":3440},[3416,10526,10527],{"class":3418,"line":3444},[3416,10528,10529],{},"title \"Таблиця UserSessions: схема з Composite Primary Key\"\n",[3416,10531,10532],{"class":3418,"line":3450},[3416,10533,3441],{"emptyLinePlaceholder":3440},[3416,10535,10536],{"class":3418,"line":3456},[3416,10537,10538],{},"class \"UserSessions\" as T {\n",[3416,10540,10541],{"class":3418,"line":3462},[3416,10542,10543],{},"    **PK: UserId** (S)\n",[3416,10545,10546],{"class":3418,"line":3468},[3416,10547,10548],{},"    **SK: SessionId** (S)\n",[3416,10550,10551],{"class":3418,"line":3474},[3416,10552,10553],{},"    ──────────────────────\n",[3416,10555,10556],{"class":3418,"line":3480},[3416,10557,10558],{},"    CreatedAt: String (ISO8601)\n",[3416,10560,10561],{"class":3418,"line":3486},[3416,10562,10563],{},"    ExpiresAt: String (ISO8601)\n",[3416,10565,10566],{"class":3418,"line":3492},[3416,10567,10568],{},"    UserAgent: String\n",[3416,10570,10571],{"class":3418,"line":3498},[3416,10572,10573],{},"    IpAddress: String\n",[3416,10575,10576],{"class":3418,"line":3504},[3416,10577,10578],{},"    IsActive: Boolean\n",[3416,10580,10581],{"class":3418,"line":3510},[3416,10582,10583],{},"    DeviceInfo: Map\n",[3416,10585,10586],{"class":3418,"line":3515},[3416,10587,10588],{},"    Permissions: StringSet\n",[3416,10590,10591],{"class":3418,"line":3521},[3416,10592,3507],{},[3416,10594,10595],{"class":3418,"line":3527},[3416,10596,3441],{"emptyLinePlaceholder":3440},[3416,10598,10599],{"class":3418,"line":3533},[3416,10600,10601],{},"note right of T\n",[3416,10603,10604],{"class":3418,"line":3539},[3416,10605,10606],{},"  PK + SK = Composite Primary Key\n",[3416,10608,10609],{"class":3418,"line":3545},[3416,10610,10611],{},"  ─────────────────────────────\n",[3416,10613,10614],{"class":3418,"line":3551},[3416,10615,10616],{},"  Запит: \"всі активні сесії usr-001\"\n",[3416,10618,10619],{"class":3418,"line":3557},[3416,10620,10621],{},"  → Query(PK=\"usr-001\")\n",[3416,10623,10624],{"class":3418,"line":3563},[3416,10625,10626],{},"  → Filter(IsActive=true)\n",[3416,10628,10629],{"class":3418,"line":3569},[3416,10630,3441],{"emptyLinePlaceholder":3440},[3416,10632,10633],{"class":3418,"line":3574},[3416,10634,10635],{},"  Запит: \"конкретна сесія\"\n",[3416,10637,10638],{"class":3418,"line":3579},[3416,10639,10640],{},"  → GetItem(PK=\"usr-001\", SK=\"sess-XYZ\")\n",[3416,10642,10643],{"class":3418,"line":3584},[3416,10644,3441],{"emptyLinePlaceholder":3440},[3416,10646,10647],{"class":3418,"line":3590},[3416,10648,10649],{},"  Запит: \"сесії із закінченим терміном\"\n",[3416,10651,10652],{"class":3418,"line":3596},[3416,10653,10654],{},"  → потребує GSI (розглянемо далі)\n",[3416,10656,10657],{"class":3418,"line":3602},[3416,10658,5088],{},[3416,10660,10661],{"class":3418,"line":3608},[3416,10662,3441],{"emptyLinePlaceholder":3440},[3416,10664,10665],{"class":3418,"line":3614},[3416,10666,3718],{},[3727,10668,10670],{"id":10669},"створення-через-aws-cli-та-powershell","Створення через AWS CLI та PowerShell",[3353,10672,10673],{},"AWS CLI надає повний контроль над параметрами таблиці та є основою для автоматизації та Infrastructure-as-Code:",[6308,10675,10676,10765,11015],{},[6311,10677,10678],{"label":6313},[3406,10679,10681],{"className":6316,"code":10680,"language":6318,"meta":3411,"style":3411},"# Створення таблиці UserSessions з Composite Primary Key\naws dynamodb create-table \\\n    --table-name UserSessions \\\n    --attribute-definitions \\\n        AttributeName=UserId,AttributeType=S \\\n        AttributeName=SessionId,AttributeType=S \\\n    --key-schema \\\n        AttributeName=UserId,KeyType=HASH \\\n        AttributeName=SessionId,KeyType=RANGE \\\n    --billing-mode PAY_PER_REQUEST \\\n    --region eu-central-1\n",[3413,10682,10683,10688,10699,10707,10714,10721,10728,10735,10742,10749,10759],{"__ignoreMap":3411},[3416,10684,10685],{"class":3418,"line":3419},[3416,10686,10687],{"class":3789},"# Створення таблиці UserSessions з Composite Primary Key\n",[3416,10689,10690,10692,10694,10697],{"class":3418,"line":3425},[3416,10691,6331],{"class":6330},[3416,10693,6334],{"class":3808},[3416,10695,10696],{"class":3808}," create-table",[3416,10698,6341],{"class":6340},[3416,10700,10701,10703,10705],{"class":3418,"line":3431},[3416,10702,6346],{"class":4368},[3416,10704,6349],{"class":3808},[3416,10706,6341],{"class":6340},[3416,10708,10709,10712],{"class":3418,"line":3437},[3416,10710,10711],{"class":4368},"    --attribute-definitions",[3416,10713,6341],{"class":6340},[3416,10715,10716,10719],{"class":3418,"line":3444},[3416,10717,10718],{"class":3808},"        AttributeName=UserId,AttributeType=S",[3416,10720,6341],{"class":6340},[3416,10722,10723,10726],{"class":3418,"line":3450},[3416,10724,10725],{"class":3808},"        AttributeName=SessionId,AttributeType=S",[3416,10727,6341],{"class":6340},[3416,10729,10730,10733],{"class":3418,"line":3456},[3416,10731,10732],{"class":4368},"    --key-schema",[3416,10734,6341],{"class":6340},[3416,10736,10737,10740],{"class":3418,"line":3462},[3416,10738,10739],{"class":3808},"        AttributeName=UserId,KeyType=HASH",[3416,10741,6341],{"class":6340},[3416,10743,10744,10747],{"class":3418,"line":3468},[3416,10745,10746],{"class":3808},"        AttributeName=SessionId,KeyType=RANGE",[3416,10748,6341],{"class":6340},[3416,10750,10751,10754,10757],{"class":3418,"line":3474},[3416,10752,10753],{"class":4368},"    --billing-mode",[3416,10755,10756],{"class":3808}," PAY_PER_REQUEST",[3416,10758,6341],{"class":6340},[3416,10760,10761,10763],{"class":3418,"line":3480},[3416,10762,6366],{"class":4368},[3416,10764,6369],{"class":3808},[6311,10766,10767],{"label":6372},[3406,10768,10770],{"className":6375,"code":10769,"language":6377,"meta":3411,"style":3411},"var client = new AmazonDynamoDBClient();\nvar response = await client.CreateTableAsync(new CreateTableRequest\n{\n    TableName = \"UserSessions\",\n    AttributeDefinitions = new List\u003CAttributeDefinition>\n    {\n        new AttributeDefinition { AttributeName = \"UserId\", AttributeType = ScalarAttributeType.S },\n        new AttributeDefinition { AttributeName = \"SessionId\", AttributeType = ScalarAttributeType.S }\n    },\n    KeySchema = new List\u003CKeySchemaElement>\n    {\n        new KeySchemaElement { AttributeName = \"UserId\", KeyType = KeyType.HASH },\n        new KeySchemaElement { AttributeName = \"SessionId\", KeyType = KeyType.RANGE }\n    },\n    BillingMode = BillingMode.PAY_PER_REQUEST\n});\n",[3413,10771,10772,10786,10810,10814,10824,10842,10846,10878,10906,10910,10928,10932,10963,10992,10996,11011],{"__ignoreMap":3411},[3416,10773,10774,10776,10778,10780,10782,10784],{"class":3418,"line":3419},[3416,10775,6384],{"class":4368},[3416,10777,6388],{"class":6387},[3416,10779,6391],{"class":3795},[3416,10781,6394],{"class":4368},[3416,10783,6398],{"class":6397},[3416,10785,6401],{"class":3795},[3416,10787,10788,10790,10792,10794,10796,10798,10800,10803,10805,10807],{"class":3418,"line":3425},[3416,10789,6384],{"class":4368},[3416,10791,6408],{"class":6387},[3416,10793,6391],{"class":3795},[3416,10795,6413],{"class":4368},[3416,10797,6388],{"class":6387},[3416,10799,4043],{"class":3795},[3416,10801,10802],{"class":6330},"CreateTableAsync",[3416,10804,6423],{"class":3795},[3416,10806,6394],{"class":4368},[3416,10808,10809],{"class":6397}," CreateTableRequest\n",[3416,10811,10812],{"class":3418,"line":3431},[3416,10813,3796],{"class":3795},[3416,10815,10816,10818,10820,10822],{"class":3418,"line":3437},[3416,10817,6437],{"class":6387},[3416,10819,6391],{"class":3795},[3416,10821,6442],{"class":3808},[3416,10823,3812],{"class":3795},[3416,10825,10826,10829,10831,10833,10835,10837,10840],{"class":3418,"line":3444},[3416,10827,10828],{"class":6387},"    AttributeDefinitions",[3416,10830,6391],{"class":3795},[3416,10832,6394],{"class":4368},[3416,10834,8640],{"class":6397},[3416,10836,5861],{"class":3795},[3416,10838,10839],{"class":6397},"AttributeDefinition",[3416,10841,6469],{"class":3795},[3416,10843,10844],{"class":3418,"line":3450},[3416,10845,6474],{"class":3795},[3416,10847,10848,10850,10853,10855,10858,10860,10862,10864,10867,10869,10872,10874,10876],{"class":3418,"line":3456},[3416,10849,9886],{"class":4368},[3416,10851,10852],{"class":6397}," AttributeDefinition",[3416,10854,6492],{"class":3795},[3416,10856,10857],{"class":6387},"AttributeName",[3416,10859,6391],{"class":3795},[3416,10861,6482],{"class":3808},[3416,10863,4384],{"class":3795},[3416,10865,10866],{"class":6387},"AttributeType",[3416,10868,6391],{"class":3795},[3416,10870,10871],{"class":6387},"ScalarAttributeType",[3416,10873,4043],{"class":3795},[3416,10875,6495],{"class":6387},[3416,10877,8915],{"class":3795},[3416,10879,10880,10882,10884,10886,10888,10890,10892,10894,10896,10898,10900,10902,10904],{"class":3418,"line":3462},[3416,10881,9886],{"class":4368},[3416,10883,10852],{"class":6397},[3416,10885,6492],{"class":3795},[3416,10887,10857],{"class":6387},[3416,10889,6391],{"class":3795},[3416,10891,6510],{"class":3808},[3416,10893,4384],{"class":3795},[3416,10895,10866],{"class":6387},[3416,10897,6391],{"class":3795},[3416,10899,10871],{"class":6387},[3416,10901,4043],{"class":3795},[3416,10903,6495],{"class":6387},[3416,10905,8948],{"class":3795},[3416,10907,10908],{"class":3418,"line":3468},[3416,10909,4442],{"class":3795},[3416,10911,10912,10915,10917,10919,10921,10923,10926],{"class":3418,"line":3474},[3416,10913,10914],{"class":6387},"    KeySchema",[3416,10916,6391],{"class":3795},[3416,10918,6394],{"class":4368},[3416,10920,8640],{"class":6397},[3416,10922,5861],{"class":3795},[3416,10924,10925],{"class":6397},"KeySchemaElement",[3416,10927,6469],{"class":3795},[3416,10929,10930],{"class":3418,"line":3480},[3416,10931,6474],{"class":3795},[3416,10933,10934,10936,10939,10941,10943,10945,10947,10949,10952,10954,10956,10958,10961],{"class":3418,"line":3486},[3416,10935,9886],{"class":4368},[3416,10937,10938],{"class":6397}," KeySchemaElement",[3416,10940,6492],{"class":3795},[3416,10942,10857],{"class":6387},[3416,10944,6391],{"class":3795},[3416,10946,6482],{"class":3808},[3416,10948,4384],{"class":3795},[3416,10950,10951],{"class":6387},"KeyType",[3416,10953,6391],{"class":3795},[3416,10955,10951],{"class":6387},[3416,10957,4043],{"class":3795},[3416,10959,10960],{"class":6387},"HASH",[3416,10962,8915],{"class":3795},[3416,10964,10965,10967,10969,10971,10973,10975,10977,10979,10981,10983,10985,10987,10990],{"class":3418,"line":3492},[3416,10966,9886],{"class":4368},[3416,10968,10938],{"class":6397},[3416,10970,6492],{"class":3795},[3416,10972,10857],{"class":6387},[3416,10974,6391],{"class":3795},[3416,10976,6510],{"class":3808},[3416,10978,4384],{"class":3795},[3416,10980,10951],{"class":6387},[3416,10982,6391],{"class":3795},[3416,10984,10951],{"class":6387},[3416,10986,4043],{"class":3795},[3416,10988,10989],{"class":6387},"RANGE",[3416,10991,8948],{"class":3795},[3416,10993,10994],{"class":3418,"line":3498},[3416,10995,4442],{"class":3795},[3416,10997,10998,11001,11003,11006,11008],{"class":3418,"line":3504},[3416,10999,11000],{"class":6387},"    BillingMode",[3416,11002,6391],{"class":3795},[3416,11004,11005],{"class":6387},"BillingMode",[3416,11007,4043],{"class":3795},[3416,11009,11010],{"class":6387},"PAY_PER_REQUEST\n",[3416,11012,11013],{"class":3418,"line":3510},[3416,11014,6537],{"class":3795},[6311,11016,11017],{"label":6540},[3406,11018,11020],{"className":6543,"code":11019,"language":6545,"meta":3411,"style":3411},"# Встановити AWS Tools for PowerShell (якщо ще не встановлено)\n# Install-Module -Name AWS.Tools.DynamoDBv2 -Force\n\n# Створення таблиці UserSessions з Composite Primary Key\n$attrUserId    = New-DDBAttributeDefinition -AttributeName UserId    -AttributeType S\n$attrSessionId = New-DDBAttributeDefinition -AttributeName SessionId -AttributeType S\n\n$keyUserId    = New-DDBKeySchemaElement -AttributeName UserId    -KeyType HASH\n$keySessionId = New-DDBKeySchemaElement -AttributeName SessionId -KeyType RANGE\n\nNew-DDBTable `\n    -TableName   UserSessions `\n    -AttributeDefinition @($attrUserId, $attrSessionId) `\n    -KeySchema   @($keyUserId, $keySessionId) `\n    -BillingMode PAY_PER_REQUEST `\n    -Region      eu-central-1\n",[3413,11021,11022,11027,11032,11036,11040,11053,11065,11069,11082,11094,11098,11106,11111,11129,11146,11151],{"__ignoreMap":3411},[3416,11023,11024],{"class":3418,"line":3419},[3416,11025,11026],{"class":3789},"# Встановити AWS Tools for PowerShell (якщо ще не встановлено)\n",[3416,11028,11029],{"class":3418,"line":3425},[3416,11030,11031],{"class":3789},"# Install-Module -Name AWS.Tools.DynamoDBv2 -Force\n",[3416,11033,11034],{"class":3418,"line":3431},[3416,11035,3441],{"emptyLinePlaceholder":3440},[3416,11037,11038],{"class":3418,"line":3437},[3416,11039,10687],{"class":3789},[3416,11041,11042,11045,11047,11050],{"class":3418,"line":3444},[3416,11043,11044],{"class":6387},"$attrUserId",[3416,11046,6571],{"class":3795},[3416,11048,11049],{"class":6330},"New-DDBAttributeDefinition",[3416,11051,11052],{"class":3795}," -AttributeName UserId    -AttributeType S\n",[3416,11054,11055,11058,11060,11062],{"class":3418,"line":3450},[3416,11056,11057],{"class":6387},"$attrSessionId",[3416,11059,6391],{"class":3795},[3416,11061,11049],{"class":6330},[3416,11063,11064],{"class":3795}," -AttributeName SessionId -AttributeType S\n",[3416,11066,11067],{"class":3418,"line":3456},[3416,11068,3441],{"emptyLinePlaceholder":3440},[3416,11070,11071,11074,11076,11079],{"class":3418,"line":3462},[3416,11072,11073],{"class":6387},"$keyUserId",[3416,11075,6571],{"class":3795},[3416,11077,11078],{"class":6330},"New-DDBKeySchemaElement",[3416,11080,11081],{"class":3795}," -AttributeName UserId    -KeyType HASH\n",[3416,11083,11084,11087,11089,11091],{"class":3418,"line":3468},[3416,11085,11086],{"class":6387},"$keySessionId",[3416,11088,6391],{"class":3795},[3416,11090,11078],{"class":6330},[3416,11092,11093],{"class":3795}," -AttributeName SessionId -KeyType RANGE\n",[3416,11095,11096],{"class":3418,"line":3474},[3416,11097,3441],{"emptyLinePlaceholder":3440},[3416,11099,11100,11103],{"class":3418,"line":3480},[3416,11101,11102],{"class":6330},"New-DDBTable",[3416,11104,11105],{"class":3795}," `\n",[3416,11107,11108],{"class":3418,"line":3486},[3416,11109,11110],{"class":3795},"    -TableName   UserSessions `\n",[3416,11112,11113,11116,11118,11120,11122,11124,11126],{"class":3418,"line":3492},[3416,11114,11115],{"class":3795},"    -AttributeDefinition ",[3416,11117,6561],{"class":4368},[3416,11119,6423],{"class":3795},[3416,11121,11044],{"class":6387},[3416,11123,4384],{"class":3795},[3416,11125,11057],{"class":6387},[3416,11127,11128],{"class":3795},") `\n",[3416,11130,11131,11134,11136,11138,11140,11142,11144],{"class":3418,"line":3498},[3416,11132,11133],{"class":3795},"    -KeySchema   ",[3416,11135,6561],{"class":4368},[3416,11137,6423],{"class":3795},[3416,11139,11073],{"class":6387},[3416,11141,4384],{"class":3795},[3416,11143,11086],{"class":6387},[3416,11145,11128],{"class":3795},[3416,11147,11148],{"class":3418,"line":3504},[3416,11149,11150],{"class":3795},"    -BillingMode PAY_PER_REQUEST `\n",[3416,11152,11153,11156],{"class":3418,"line":3510},[3416,11154,11155],{"class":3795},"    -Region      eu-central-",[3416,11157,6614],{"class":3870},[11159,11160,11162,11174,11178,11188,11201,11213,11224,11231,11251,11268,11272,11279,11291,11295,11299],"terminal-preview",{"title":11161},"Створення таблиці UserSessions",[11163,11164,11166,10466,11171],"div",{"className":11165},[3418],[3416,11167,11170],{"className":11168},[11169],"opacity-40","$",[3363,11172,11173],{},"aws dynamodb create-table --table-name UserSessions ...",[11163,11175,11177],{"className":11176},[3418],"{",[11163,11179,11181,11182,11187],{"className":11180},[3418],"    ",[3416,11183,11186],{"className":11184},[11185],"text-blue-400","\"TableDescription\"",": {",[11163,11189,11191,11192,3805,11196,11200],{"className":11190},[3418],"        ",[3416,11193,11195],{"className":11194},[11185],"\"TableName\"",[3416,11197,6442],{"className":11198},[11199],"text-green-400",",",[11163,11202,11191,11204,3805,11208,11200],{"className":11203},[3418],[3416,11205,11207],{"className":11206},[11185],"\"TableStatus\"",[3416,11209,11212],{"className":11210},[11211],"text-yellow-400","\"CREATING\"",[11163,11214,11191,11216,3805,11220,11200],{"className":11215},[3418],[3416,11217,11219],{"className":11218},[11185],"\"TableArn\"",[3416,11221,11223],{"className":11222},[11199],"\"arn:aws:dynamodb:eu-central-1:123456789012:table\u002FUserSessions\"",[11163,11225,11191,11227,4378],{"className":11226},[3418],[3416,11228,11230],{"className":11229},[11185],"\"KeySchema\"",[11163,11232,11234,11235,3805,11239,4384,11242,3805,11246,11250],{"className":11233},[3418],"            { ",[3416,11236,11238],{"className":11237},[11185],"\"AttributeName\"",[3416,11240,6482],{"className":11241},[11199],[3416,11243,11245],{"className":11244},[11185],"\"KeyType\"",[3416,11247,11249],{"className":11248},[11199],"\"HASH\""," },",[11163,11252,11234,11254,3805,11257,4384,11260,3805,11263,11267],{"className":11253},[3418],[3416,11255,11238],{"className":11256},[11185],[3416,11258,6510],{"className":11259},[11199],[3416,11261,11245],{"className":11262},[11185],[3416,11264,11266],{"className":11265},[11199],"\"RANGE\""," }",[11163,11269,11271],{"className":11270},[3418],"        ],",[11163,11273,11191,11275,11187],{"className":11274},[3418],[3416,11276,11278],{"className":11277},[11185],"\"BillingModeSummary\"",[11163,11280,11282,11283,3805,11287],{"className":11281},[3418],"            ",[3416,11284,11286],{"className":11285},[11185],"\"BillingMode\"",[3416,11288,11290],{"className":11289},[11199],"\"PAY_PER_REQUEST\"",[11163,11292,11294],{"className":11293},[3418],"        }",[11163,11296,11298],{"className":11297},[3418],"    }",[11163,11300,11302],{"className":11301},[3418],"}",[6308,11304,11305,11402,11623],{},[6311,11306,11307],{"label":6313},[3406,11308,11310],{"className":6316,"code":11309,"language":6318,"meta":3411,"style":3411},"# Дочекатися поки таблиця перейде у стан ACTIVE\naws dynamodb wait table-exists \\\n    --table-name UserSessions \\\n    --region eu-central-1\n\necho \"Таблиця UserSessions готова\"\n\n# Перевірити статус таблиці\naws dynamodb describe-table \\\n    --table-name UserSessions \\\n    --region eu-central-1 \\\n    --query \"Table.{Status: TableStatus, ItemCount: ItemCount, SizeBytes: TableSizeBytes}\"\n",[3413,11311,11312,11317,11331,11339,11345,11349,11357,11361,11366,11377,11385,11394],{"__ignoreMap":3411},[3416,11313,11314],{"class":3418,"line":3419},[3416,11315,11316],{"class":3789},"# Дочекатися поки таблиця перейде у стан ACTIVE\n",[3416,11318,11319,11321,11323,11326,11329],{"class":3418,"line":3425},[3416,11320,6331],{"class":6330},[3416,11322,6334],{"class":3808},[3416,11324,11325],{"class":3808}," wait",[3416,11327,11328],{"class":3808}," table-exists",[3416,11330,6341],{"class":6340},[3416,11332,11333,11335,11337],{"class":3418,"line":3431},[3416,11334,6346],{"class":4368},[3416,11336,6349],{"class":3808},[3416,11338,6341],{"class":6340},[3416,11340,11341,11343],{"class":3418,"line":3437},[3416,11342,6366],{"class":4368},[3416,11344,6369],{"class":3808},[3416,11346,11347],{"class":3418,"line":3444},[3416,11348,3441],{"emptyLinePlaceholder":3440},[3416,11350,11351,11354],{"class":3418,"line":3450},[3416,11352,11353],{"class":6330},"echo",[3416,11355,11356],{"class":3808}," \"Таблиця UserSessions готова\"\n",[3416,11358,11359],{"class":3418,"line":3456},[3416,11360,3441],{"emptyLinePlaceholder":3440},[3416,11362,11363],{"class":3418,"line":3462},[3416,11364,11365],{"class":3789},"# Перевірити статус таблиці\n",[3416,11367,11368,11370,11372,11375],{"class":3418,"line":3468},[3416,11369,6331],{"class":6330},[3416,11371,6334],{"class":3808},[3416,11373,11374],{"class":3808}," describe-table",[3416,11376,6341],{"class":6340},[3416,11378,11379,11381,11383],{"class":3418,"line":3474},[3416,11380,6346],{"class":4368},[3416,11382,6349],{"class":3808},[3416,11384,6341],{"class":6340},[3416,11386,11387,11389,11392],{"class":3418,"line":3480},[3416,11388,6366],{"class":4368},[3416,11390,11391],{"class":3808}," eu-central-1",[3416,11393,6341],{"class":6340},[3416,11395,11396,11399],{"class":3418,"line":3486},[3416,11397,11398],{"class":4368},"    --query",[3416,11400,11401],{"class":3808}," \"Table.{Status: TableStatus, ItemCount: ItemCount, SizeBytes: TableSizeBytes}\"\n",[6311,11403,11404],{"label":6372},[3406,11405,11407],{"className":6375,"code":11406,"language":6377,"meta":3411,"style":3411},"var client = new AmazonDynamoDBClient();\nwhile (true)\n{\n    var res = await client.DescribeTableAsync(\"UserSessions\");\n    if (res.Table.TableStatus == TableStatus.ACTIVE)\n    {\n        Console.WriteLine(\"Таблиця UserSessions готова\");\n        Console.WriteLine($\"Status: {res.Table.TableStatus}, Items: {res.Table.ItemCount}, Size: {res.Table.TableSizeBytes} bytes\");\n        break;\n    }\n    await Task.Delay(5000);\n}\n",[3413,11408,11409,11423,11436,11440,11466,11497,11501,11518,11587,11595,11599,11619],{"__ignoreMap":3411},[3416,11410,11411,11413,11415,11417,11419,11421],{"class":3418,"line":3419},[3416,11412,6384],{"class":4368},[3416,11414,6388],{"class":6387},[3416,11416,6391],{"class":3795},[3416,11418,6394],{"class":4368},[3416,11420,6398],{"class":6397},[3416,11422,6401],{"class":3795},[3416,11424,11425,11429,11432,11434],{"class":3418,"line":3425},[3416,11426,11428],{"class":11427},"s8xlr","while",[3416,11430,11431],{"class":3795}," (",[3416,11433,4038],{"class":4368},[3416,11435,9656],{"class":3795},[3416,11437,11438],{"class":3418,"line":3431},[3416,11439,3796],{"class":3795},[3416,11441,11442,11445,11448,11450,11452,11454,11456,11459,11461,11463],{"class":3418,"line":3437},[3416,11443,11444],{"class":4368},"    var",[3416,11446,11447],{"class":6387}," res",[3416,11449,6391],{"class":3795},[3416,11451,6413],{"class":4368},[3416,11453,6388],{"class":6387},[3416,11455,4043],{"class":3795},[3416,11457,11458],{"class":6330},"DescribeTableAsync",[3416,11460,6423],{"class":3795},[3416,11462,6442],{"class":3808},[3416,11464,11465],{"class":3795},");\n",[3416,11467,11468,11471,11473,11476,11478,11481,11483,11486,11489,11491,11493,11495],{"class":3418,"line":3444},[3416,11469,11470],{"class":11427},"    if",[3416,11472,11431],{"class":3795},[3416,11474,11475],{"class":6387},"res",[3416,11477,4043],{"class":3795},[3416,11479,11480],{"class":6387},"Table",[3416,11482,4043],{"class":3795},[3416,11484,11485],{"class":6387},"TableStatus",[3416,11487,11488],{"class":3795}," == ",[3416,11490,11485],{"class":6387},[3416,11492,4043],{"class":3795},[3416,11494,4795],{"class":6387},[3416,11496,9656],{"class":3795},[3416,11498,11499],{"class":3418,"line":3450},[3416,11500,6474],{"class":3795},[3416,11502,11503,11506,11508,11511,11513,11516],{"class":3418,"line":3456},[3416,11504,11505],{"class":6387},"        Console",[3416,11507,4043],{"class":3795},[3416,11509,11510],{"class":6330},"WriteLine",[3416,11512,6423],{"class":3795},[3416,11514,11515],{"class":3808},"\"Таблиця UserSessions готова\"",[3416,11517,11465],{"class":3795},[3416,11519,11520,11522,11524,11526,11528,11531,11534,11536,11538,11540,11542,11544,11546,11549,11551,11553,11555,11557,11559,11562,11564,11567,11569,11571,11573,11575,11577,11580,11582,11585],{"class":3418,"line":3462},[3416,11521,11505],{"class":6387},[3416,11523,4043],{"class":3795},[3416,11525,11510],{"class":6330},[3416,11527,6423],{"class":3795},[3416,11529,11530],{"class":3808},"$\"Status: ",[3416,11532,11177],{"class":11533},"sD7JJ",[3416,11535,11475],{"class":6387},[3416,11537,4043],{"class":11533},[3416,11539,11480],{"class":6387},[3416,11541,4043],{"class":11533},[3416,11543,11485],{"class":6387},[3416,11545,11302],{"class":11533},[3416,11547,11548],{"class":3808},", Items: ",[3416,11550,11177],{"class":11533},[3416,11552,11475],{"class":6387},[3416,11554,4043],{"class":11533},[3416,11556,11480],{"class":6387},[3416,11558,4043],{"class":11533},[3416,11560,11561],{"class":6387},"ItemCount",[3416,11563,11302],{"class":11533},[3416,11565,11566],{"class":3808},", Size: ",[3416,11568,11177],{"class":11533},[3416,11570,11475],{"class":6387},[3416,11572,4043],{"class":11533},[3416,11574,11480],{"class":6387},[3416,11576,4043],{"class":11533},[3416,11578,11579],{"class":6387},"TableSizeBytes",[3416,11581,11302],{"class":11533},[3416,11583,11584],{"class":3808}," bytes\"",[3416,11586,11465],{"class":3795},[3416,11588,11589,11592],{"class":3418,"line":3468},[3416,11590,11591],{"class":11427},"        break",[3416,11593,11594],{"class":3795},";\n",[3416,11596,11597],{"class":3418,"line":3474},[3416,11598,4167],{"class":3795},[3416,11600,11601,11604,11607,11609,11612,11614,11617],{"class":3418,"line":3480},[3416,11602,11603],{"class":4368},"    await",[3416,11605,11606],{"class":6387}," Task",[3416,11608,4043],{"class":3795},[3416,11610,11611],{"class":6330},"Delay",[3416,11613,6423],{"class":3795},[3416,11615,11616],{"class":3870},"5000",[3416,11618,11465],{"class":3795},[3416,11620,11621],{"class":3418,"line":3486},[3416,11622,3507],{"class":3795},[6311,11624,11625],{"label":6540},[3406,11626,11628],{"className":6543,"code":11627,"language":6545,"meta":3411,"style":3411},"# Дочекатися стану ACTIVE (з timeout 5 хвилин)\n$timeout = [DateTime]::UtcNow.AddMinutes(5)\ndo {\n    $table = Get-DDBTable -TableName UserSessions -Region eu-central-1\n    if ($table.TableStatus -eq 'ACTIVE') { break }\n    Write-Host \"Статус: $($table.TableStatus) — очікуємо...\"\n    Start-Sleep -Seconds 5\n} until ([DateTime]::UtcNow -ge $timeout)\n\nWrite-Host \"Таблиця UserSessions готова\"\n\n# Перевірити статус таблиці\n$t = Get-DDBTable -TableName UserSessions -Region eu-central-1\n[PSCustomObject]@{\n    Status    = $t.TableStatus\n    ItemCount = $t.ItemCount\n    SizeBytes = $t.TableSizeBytes\n}\n",[3413,11629,11630,11635,11653,11661,11676,11702,11722,11733,11753,11757,11764,11768,11772,11785,11799,11811,11823,11835],{"__ignoreMap":3411},[3416,11631,11632],{"class":3418,"line":3419},[3416,11633,11634],{"class":3789},"# Дочекатися стану ACTIVE (з timeout 5 хвилин)\n",[3416,11636,11637,11640,11642,11645,11648,11651],{"class":3418,"line":3425},[3416,11638,11639],{"class":6387},"$timeout",[3416,11641,7274],{"class":3795},[3416,11643,11644],{"class":4368},"DateTime",[3416,11646,11647],{"class":3795},"]::UtcNow.AddMinutes(",[3416,11649,11650],{"class":3870},"5",[3416,11652,9656],{"class":3795},[3416,11654,11655,11658],{"class":3418,"line":3431},[3416,11656,11657],{"class":11427},"do",[3416,11659,11660],{"class":3795}," {\n",[3416,11662,11663,11666,11668,11671,11674],{"class":3418,"line":3437},[3416,11664,11665],{"class":6387},"    $table",[3416,11667,6391],{"class":3795},[3416,11669,11670],{"class":6330},"Get-DDBTable",[3416,11672,11673],{"class":3795}," -TableName UserSessions -Region eu-central-",[3416,11675,6614],{"class":3870},[3416,11677,11678,11680,11682,11685,11688,11691,11694,11697,11700],{"class":3418,"line":3444},[3416,11679,11470],{"class":11427},[3416,11681,11431],{"class":3795},[3416,11683,11684],{"class":6387},"$table",[3416,11686,11687],{"class":6330},".TableStatus",[3416,11689,11690],{"class":3795}," -eq ",[3416,11692,11693],{"class":3808},"'ACTIVE'",[3416,11695,11696],{"class":3795},") { ",[3416,11698,11699],{"class":11427},"break",[3416,11701,8948],{"class":3795},[3416,11703,11704,11707,11710,11713,11715,11717,11719],{"class":3418,"line":3450},[3416,11705,11706],{"class":6330},"    Write-Host",[3416,11708,11709],{"class":3808}," \"Статус: ",[3416,11711,11712],{"class":4368},"$(",[3416,11714,11684],{"class":6387},[3416,11716,11687],{"class":6330},[3416,11718,6259],{"class":4368},[3416,11720,11721],{"class":3808}," — очікуємо...\"\n",[3416,11723,11724,11727,11730],{"class":3418,"line":3456},[3416,11725,11726],{"class":6330},"    Start-Sleep",[3416,11728,11729],{"class":3795}," -Seconds ",[3416,11731,11732],{"class":3870},"5\n",[3416,11734,11735,11738,11741,11744,11746,11749,11751],{"class":3418,"line":3462},[3416,11736,11737],{"class":3795},"} ",[3416,11739,11740],{"class":11427},"until",[3416,11742,11743],{"class":3795}," ([",[3416,11745,11644],{"class":4368},[3416,11747,11748],{"class":3795},"]::UtcNow -ge ",[3416,11750,11639],{"class":6387},[3416,11752,9656],{"class":3795},[3416,11754,11755],{"class":3418,"line":3468},[3416,11756,3441],{"emptyLinePlaceholder":3440},[3416,11758,11759,11762],{"class":3418,"line":3474},[3416,11760,11761],{"class":6330},"Write-Host",[3416,11763,11356],{"class":3808},[3416,11765,11766],{"class":3418,"line":3480},[3416,11767,3441],{"emptyLinePlaceholder":3440},[3416,11769,11770],{"class":3418,"line":3486},[3416,11771,11365],{"class":3789},[3416,11773,11774,11777,11779,11781,11783],{"class":3418,"line":3492},[3416,11775,11776],{"class":6387},"$t",[3416,11778,6391],{"class":3795},[3416,11780,11670],{"class":6330},[3416,11782,11673],{"class":3795},[3416,11784,6614],{"class":3870},[3416,11786,11787,11790,11793,11795,11797],{"class":3418,"line":3498},[3416,11788,11789],{"class":3795},"[",[3416,11791,11792],{"class":4368},"PSCustomObject",[3416,11794,7280],{"class":3795},[3416,11796,6561],{"class":4368},[3416,11798,3796],{"class":3795},[3416,11800,11801,11804,11806,11808],{"class":3418,"line":3504},[3416,11802,11803],{"class":6387},"    Status",[3416,11805,6571],{"class":3795},[3416,11807,11776],{"class":6387},[3416,11809,11810],{"class":6330},".TableStatus\n",[3416,11812,11813,11816,11818,11820],{"class":3418,"line":3510},[3416,11814,11815],{"class":6387},"    ItemCount",[3416,11817,6391],{"class":3795},[3416,11819,11776],{"class":6387},[3416,11821,11822],{"class":6330},".ItemCount\n",[3416,11824,11825,11828,11830,11832],{"class":3418,"line":3515},[3416,11826,11827],{"class":6387},"    SizeBytes",[3416,11829,6391],{"class":3795},[3416,11831,11776],{"class":6387},[3416,11833,11834],{"class":6330},".TableSizeBytes\n",[3416,11836,11837],{"class":3418,"line":3521},[3416,11838,3507],{"class":3795},[11159,11840,11842,11851,11854,11865,11876,11886],{"title":11841},"Статус таблиці після створення",[11163,11843,11845,10466,11848],{"className":11844},[3418],[3416,11846,11170],{"className":11847},[11169],[3363,11849,11850],{},"aws dynamodb describe-table --table-name UserSessions ...",[11163,11852,11177],{"className":11853},[3418],[11163,11855,11181,11857,3805,11861,11200],{"className":11856},[3418],[3416,11858,11860],{"className":11859},[11185],"\"Status\"",[3416,11862,11864],{"className":11863},[11199],"\"ACTIVE\"",[11163,11866,11181,11868,3805,11872,11200],{"className":11867},[3418],[3416,11869,11871],{"className":11870},[11185],"\"ItemCount\"",[3416,11873,11875],{"className":11874},[11211],"0",[11163,11877,11181,11879,3805,11883],{"className":11878},[3418],[3416,11880,11882],{"className":11881},[11185],"\"SizeBytes\"",[3416,11884,11875],{"className":11885},[11211],[11163,11887,11302],{"className":11888},[3418],[3727,11890,11892],{"id":11891},"crud-операції","CRUD-операції",[6308,11894,11895,12166,12956],{},[6311,11896,11897],{"label":6313},[3406,11898,11900],{"className":6316,"code":11899,"language":6318,"meta":3411,"style":3411},"# ── PutItem: записати новий елемент ───────────────────────────────────────\naws dynamodb put-item \\\n    --table-name UserSessions \\\n    --item '{\n        \"UserId\":    {\"S\": \"usr-001\"},\n        \"SessionId\": {\"S\": \"sess-a1b2c3d4\"},\n        \"CreatedAt\": {\"S\": \"2025-06-01T10:00:00Z\"},\n        \"ExpiresAt\": {\"S\": \"2025-06-01T22:00:00Z\"},\n        \"IpAddress\": {\"S\": \"203.0.113.42\"},\n        \"UserAgent\": {\"S\": \"Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)\"},\n        \"IsActive\":  {\"BOOL\": true}\n    }' \\\n    --region eu-central-1\n\n# ── GetItem: отримати один елемент ────────────────────────────────────────\naws dynamodb get-item \\\n    --table-name UserSessions \\\n    --key '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}' \\\n    --region eu-central-1\n\n# ── Query: знайти всі сесії користувача ──────────────────────────────────\naws dynamodb query \\\n    --table-name UserSessions \\\n    --key-condition-expression \"UserId = :uid\" \\\n    --expression-attribute-values '{\":uid\": {\"S\": \"usr-001\"}}' \\\n    --region eu-central-1\n\n# ── UpdateItem: деактивувати сесію ────────────────────────────────────────\naws dynamodb update-item \\\n    --table-name UserSessions \\\n    --key '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}' \\\n    --update-expression \"SET IsActive = :false\" \\\n    --expression-attribute-values '{\":false\": {\"BOOL\": false}}' \\\n    --region eu-central-1\n\n# ── DeleteItem: видалити сесію ───────────────────────────────────────────\naws dynamodb delete-item \\\n    --table-name UserSessions \\\n    --key '{\"UserId\": {\"S\": \"usr-001\"}, \"SessionId\": {\"S\": \"sess-a1b2c3d4\"}}' \\\n    --region eu-central-1\n",[3413,11901,11902,11907,11917,11925,11931,11935,11939,11943,11948,11953,11958,11962,11968,11974,11978,11983,11993,12001,12009,12015,12019,12024,12034,12042,12051,12060,12066,12070,12075,12085,12093,12101,12110,12119,12125,12129,12134,12144,12152,12160],{"__ignoreMap":3411},[3416,11903,11904],{"class":3418,"line":3419},[3416,11905,11906],{"class":3789},"# ── PutItem: записати новий елемент ───────────────────────────────────────\n",[3416,11908,11909,11911,11913,11915],{"class":3418,"line":3425},[3416,11910,6331],{"class":6330},[3416,11912,6334],{"class":3808},[3416,11914,6643],{"class":3808},[3416,11916,6341],{"class":6340},[3416,11918,11919,11921,11923],{"class":3418,"line":3431},[3416,11920,6346],{"class":4368},[3416,11922,6349],{"class":3808},[3416,11924,6341],{"class":6340},[3416,11926,11927,11929],{"class":3418,"line":3437},[3416,11928,6658],{"class":4368},[3416,11930,6661],{"class":3808},[3416,11932,11933],{"class":3418,"line":3444},[3416,11934,6666],{"class":3808},[3416,11936,11937],{"class":3418,"line":3450},[3416,11938,6671],{"class":3808},[3416,11940,11941],{"class":3418,"line":3456},[3416,11942,6676],{"class":3808},[3416,11944,11945],{"class":3418,"line":3462},[3416,11946,11947],{"class":3808},"        \"ExpiresAt\": {\"S\": \"2025-06-01T22:00:00Z\"},\n",[3416,11949,11950],{"class":3418,"line":3468},[3416,11951,11952],{"class":3808},"        \"IpAddress\": {\"S\": \"203.0.113.42\"},\n",[3416,11954,11955],{"class":3418,"line":3474},[3416,11956,11957],{"class":3808},"        \"UserAgent\": {\"S\": \"Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)\"},\n",[3416,11959,11960],{"class":3418,"line":3480},[3416,11961,6681],{"class":3808},[3416,11963,11964,11966],{"class":3418,"line":3486},[3416,11965,6686],{"class":3808},[3416,11967,6341],{"class":6340},[3416,11969,11970,11972],{"class":3418,"line":3492},[3416,11971,6366],{"class":4368},[3416,11973,6369],{"class":3808},[3416,11975,11976],{"class":3418,"line":3498},[3416,11977,3441],{"emptyLinePlaceholder":3440},[3416,11979,11980],{"class":3418,"line":3504},[3416,11981,11982],{"class":3789},"# ── GetItem: отримати один елемент ────────────────────────────────────────\n",[3416,11984,11985,11987,11989,11991],{"class":3418,"line":3510},[3416,11986,6331],{"class":6330},[3416,11988,6334],{"class":3808},[3416,11990,6337],{"class":3808},[3416,11992,6341],{"class":6340},[3416,11994,11995,11997,11999],{"class":3418,"line":3515},[3416,11996,6346],{"class":4368},[3416,11998,6349],{"class":3808},[3416,12000,6341],{"class":6340},[3416,12002,12003,12005,12007],{"class":3418,"line":3521},[3416,12004,6356],{"class":4368},[3416,12006,6359],{"class":3808},[3416,12008,6341],{"class":6340},[3416,12010,12011,12013],{"class":3418,"line":3527},[3416,12012,6366],{"class":4368},[3416,12014,6369],{"class":3808},[3416,12016,12017],{"class":3418,"line":3533},[3416,12018,3441],{"emptyLinePlaceholder":3440},[3416,12020,12021],{"class":3418,"line":3539},[3416,12022,12023],{"class":3789},"# ── Query: знайти всі сесії користувача ──────────────────────────────────\n",[3416,12025,12026,12028,12030,12032],{"class":3418,"line":3545},[3416,12027,6331],{"class":6330},[3416,12029,6334],{"class":3808},[3416,12031,7676],{"class":3808},[3416,12033,6341],{"class":6340},[3416,12035,12036,12038,12040],{"class":3418,"line":3551},[3416,12037,6346],{"class":4368},[3416,12039,6349],{"class":3808},[3416,12041,6341],{"class":6340},[3416,12043,12044,12046,12049],{"class":3418,"line":3557},[3416,12045,7691],{"class":4368},[3416,12047,12048],{"class":3808}," \"UserId = :uid\"",[3416,12050,6341],{"class":6340},[3416,12052,12053,12055,12058],{"class":3418,"line":3563},[3416,12054,7021],{"class":4368},[3416,12056,12057],{"class":3808}," '{\":uid\": {\"S\": \"usr-001\"}}'",[3416,12059,6341],{"class":6340},[3416,12061,12062,12064],{"class":3418,"line":3569},[3416,12063,6366],{"class":4368},[3416,12065,6369],{"class":3808},[3416,12067,12068],{"class":3418,"line":3574},[3416,12069,3441],{"emptyLinePlaceholder":3440},[3416,12071,12072],{"class":3418,"line":3579},[3416,12073,12074],{"class":3789},"# ── UpdateItem: деактивувати сесію ────────────────────────────────────────\n",[3416,12076,12077,12079,12081,12083],{"class":3418,"line":3584},[3416,12078,6331],{"class":6330},[3416,12080,6334],{"class":3808},[3416,12082,6988],{"class":3808},[3416,12084,6341],{"class":6340},[3416,12086,12087,12089,12091],{"class":3418,"line":3590},[3416,12088,6346],{"class":4368},[3416,12090,6349],{"class":3808},[3416,12092,6341],{"class":6340},[3416,12094,12095,12097,12099],{"class":3418,"line":3596},[3416,12096,6356],{"class":4368},[3416,12098,6359],{"class":3808},[3416,12100,6341],{"class":6340},[3416,12102,12103,12105,12108],{"class":3418,"line":3602},[3416,12104,7011],{"class":4368},[3416,12106,12107],{"class":3808}," \"SET IsActive = :false\"",[3416,12109,6341],{"class":6340},[3416,12111,12112,12114,12117],{"class":3418,"line":3608},[3416,12113,7021],{"class":4368},[3416,12115,12116],{"class":3808}," '{\":false\": {\"BOOL\": false}}'",[3416,12118,6341],{"class":6340},[3416,12120,12121,12123],{"class":3418,"line":3614},[3416,12122,6366],{"class":4368},[3416,12124,6369],{"class":3808},[3416,12126,12127],{"class":3418,"line":3620},[3416,12128,3441],{"emptyLinePlaceholder":3440},[3416,12130,12131],{"class":3418,"line":3626},[3416,12132,12133],{"class":3789},"# ── DeleteItem: видалити сесію ───────────────────────────────────────────\n",[3416,12135,12136,12138,12140,12142],{"class":3418,"line":3631},[3416,12137,6331],{"class":6330},[3416,12139,6334],{"class":3808},[3416,12141,7432],{"class":3808},[3416,12143,6341],{"class":6340},[3416,12145,12146,12148,12150],{"class":3418,"line":3636},[3416,12147,6346],{"class":4368},[3416,12149,6349],{"class":3808},[3416,12151,6341],{"class":6340},[3416,12153,12154,12156,12158],{"class":3418,"line":3641},[3416,12155,6356],{"class":4368},[3416,12157,6359],{"class":3808},[3416,12159,6341],{"class":6340},[3416,12161,12162,12164],{"class":3418,"line":3647},[3416,12163,6366],{"class":4368},[3416,12165,6369],{"class":3808},[6311,12167,12168],{"label":6372},[3406,12169,12171],{"className":6375,"code":12170,"language":6377,"meta":3411,"style":3411},"var client = new AmazonDynamoDBClient();\n\n\u002F\u002F ── PutItem: записати новий елемент ───────────────────────────────────────\nawait client.PutItemAsync(new PutItemRequest\n{\n    TableName = \"UserSessions\",\n    Item = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } },\n        { \"CreatedAt\", new AttributeValue { S = \"2025-06-01T10:00:00Z\" } },\n        { \"ExpiresAt\", new AttributeValue { S = \"2025-06-01T22:00:00Z\" } },\n        { \"IpAddress\", new AttributeValue { S = \"203.0.113.42\" } },\n        { \"UserAgent\", new AttributeValue { S = \"Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)\" } },\n        { \"IsActive\", new AttributeValue { BOOL = true } }\n    }\n});\n\n\u002F\u002F ── GetItem: отримати один елемент ────────────────────────────────────────\nvar getResponse = await client.GetItemAsync(new GetItemRequest\n{\n    TableName = \"UserSessions\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } }\n    }\n});\n\n\u002F\u002F ── Query: знайти всі сесії користувача ──────────────────────────────────\nvar queryResponse = await client.QueryAsync(new QueryRequest\n{\n    TableName = \"UserSessions\",\n    KeyConditionExpression = \"UserId = :uid\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":uid\", new AttributeValue { S = \"usr-001\" } }\n    }\n});\n\n\u002F\u002F ── UpdateItem: деактивувати сесію ────────────────────────────────────────\nawait client.UpdateItemAsync(new UpdateItemRequest\n{\n    TableName = \"UserSessions\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } }\n    },\n    UpdateExpression = \"SET IsActive = :false\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":false\", new AttributeValue { BOOL = false } }\n    }\n});\n\n\u002F\u002F ── DeleteItem: видалити сесію ───────────────────────────────────────────\nawait client.DeleteItemAsync(new DeleteItemRequest\n{\n    TableName = \"UserSessions\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-a1b2c3d4\" } }\n    }\n});\n",[3413,12172,12173,12187,12191,12196,12212,12216,12226,12246,12250,12272,12294,12316,12340,12364,12388,12410,12414,12418,12422,12427,12450,12454,12464,12484,12488,12510,12532,12536,12540,12544,12549,12572,12576,12586,12597,12617,12621,12643,12647,12651,12655,12660,12676,12680,12690,12710,12714,12736,12758,12762,12773,12793,12797,12820,12825,12830,12835,12841,12858,12863,12874,12895,12900,12923,12946,12951],{"__ignoreMap":3411},[3416,12174,12175,12177,12179,12181,12183,12185],{"class":3418,"line":3419},[3416,12176,6384],{"class":4368},[3416,12178,6388],{"class":6387},[3416,12180,6391],{"class":3795},[3416,12182,6394],{"class":4368},[3416,12184,6398],{"class":6397},[3416,12186,6401],{"class":3795},[3416,12188,12189],{"class":3418,"line":3425},[3416,12190,3441],{"emptyLinePlaceholder":3440},[3416,12192,12193],{"class":3418,"line":3431},[3416,12194,12195],{"class":3789},"\u002F\u002F ── PutItem: записати новий елемент ───────────────────────────────────────\n",[3416,12197,12198,12200,12202,12204,12206,12208,12210],{"class":3418,"line":3437},[3416,12199,6413],{"class":4368},[3416,12201,6388],{"class":6387},[3416,12203,4043],{"class":3795},[3416,12205,6718],{"class":6330},[3416,12207,6423],{"class":3795},[3416,12209,6394],{"class":4368},[3416,12211,6725],{"class":6397},[3416,12213,12214],{"class":3418,"line":3444},[3416,12215,3796],{"class":3795},[3416,12217,12218,12220,12222,12224],{"class":3418,"line":3450},[3416,12219,6437],{"class":6387},[3416,12221,6391],{"class":3795},[3416,12223,6442],{"class":3808},[3416,12225,3812],{"class":3795},[3416,12227,12228,12230,12232,12234,12236,12238,12240,12242,12244],{"class":3418,"line":3456},[3416,12229,6744],{"class":6387},[3416,12231,6391],{"class":3795},[3416,12233,6394],{"class":4368},[3416,12235,6456],{"class":6397},[3416,12237,5861],{"class":3795},[3416,12239,6461],{"class":4368},[3416,12241,4384],{"class":3795},[3416,12243,6466],{"class":6397},[3416,12245,6469],{"class":3795},[3416,12247,12248],{"class":3418,"line":3462},[3416,12249,6474],{"class":3795},[3416,12251,12252,12254,12256,12258,12260,12262,12264,12266,12268,12270],{"class":3418,"line":3468},[3416,12253,6479],{"class":3795},[3416,12255,6482],{"class":3808},[3416,12257,4384],{"class":3795},[3416,12259,6394],{"class":4368},[3416,12261,6489],{"class":6397},[3416,12263,6492],{"class":3795},[3416,12265,6495],{"class":6387},[3416,12267,6391],{"class":3795},[3416,12269,6500],{"class":3808},[3416,12271,6503],{"class":3795},[3416,12273,12274,12276,12278,12280,12282,12284,12286,12288,12290,12292],{"class":3418,"line":3474},[3416,12275,6479],{"class":3795},[3416,12277,6510],{"class":3808},[3416,12279,4384],{"class":3795},[3416,12281,6394],{"class":4368},[3416,12283,6489],{"class":6397},[3416,12285,6492],{"class":3795},[3416,12287,6495],{"class":6387},[3416,12289,6391],{"class":3795},[3416,12291,6525],{"class":3808},[3416,12293,6503],{"class":3795},[3416,12295,12296,12298,12300,12302,12304,12306,12308,12310,12312,12314],{"class":3418,"line":3480},[3416,12297,6479],{"class":3795},[3416,12299,6815],{"class":3808},[3416,12301,4384],{"class":3795},[3416,12303,6394],{"class":4368},[3416,12305,6489],{"class":6397},[3416,12307,6492],{"class":3795},[3416,12309,6495],{"class":6387},[3416,12311,6391],{"class":3795},[3416,12313,6830],{"class":3808},[3416,12315,6503],{"class":3795},[3416,12317,12318,12320,12323,12325,12327,12329,12331,12333,12335,12338],{"class":3418,"line":3486},[3416,12319,6479],{"class":3795},[3416,12321,12322],{"class":3808},"\"ExpiresAt\"",[3416,12324,4384],{"class":3795},[3416,12326,6394],{"class":4368},[3416,12328,6489],{"class":6397},[3416,12330,6492],{"class":3795},[3416,12332,6495],{"class":6387},[3416,12334,6391],{"class":3795},[3416,12336,12337],{"class":3808},"\"2025-06-01T22:00:00Z\"",[3416,12339,6503],{"class":3795},[3416,12341,12342,12344,12347,12349,12351,12353,12355,12357,12359,12362],{"class":3418,"line":3492},[3416,12343,6479],{"class":3795},[3416,12345,12346],{"class":3808},"\"IpAddress\"",[3416,12348,4384],{"class":3795},[3416,12350,6394],{"class":4368},[3416,12352,6489],{"class":6397},[3416,12354,6492],{"class":3795},[3416,12356,6495],{"class":6387},[3416,12358,6391],{"class":3795},[3416,12360,12361],{"class":3808},"\"203.0.113.42\"",[3416,12363,6503],{"class":3795},[3416,12365,12366,12368,12371,12373,12375,12377,12379,12381,12383,12386],{"class":3418,"line":3498},[3416,12367,6479],{"class":3795},[3416,12369,12370],{"class":3808},"\"UserAgent\"",[3416,12372,4384],{"class":3795},[3416,12374,6394],{"class":4368},[3416,12376,6489],{"class":6397},[3416,12378,6492],{"class":3795},[3416,12380,6495],{"class":6387},[3416,12382,6391],{"class":3795},[3416,12384,12385],{"class":3808},"\"Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)\"",[3416,12387,6503],{"class":3795},[3416,12389,12390,12392,12394,12396,12398,12400,12402,12404,12406,12408],{"class":3418,"line":3504},[3416,12391,6479],{"class":3795},[3416,12393,6839],{"class":3808},[3416,12395,4384],{"class":3795},[3416,12397,6394],{"class":4368},[3416,12399,6489],{"class":6397},[3416,12401,6492],{"class":3795},[3416,12403,6850],{"class":6387},[3416,12405,6391],{"class":3795},[3416,12407,4038],{"class":4368},[3416,12409,6528],{"class":3795},[3416,12411,12412],{"class":3418,"line":3510},[3416,12413,4167],{"class":3795},[3416,12415,12416],{"class":3418,"line":3515},[3416,12417,6537],{"class":3795},[3416,12419,12420],{"class":3418,"line":3521},[3416,12421,3441],{"emptyLinePlaceholder":3440},[3416,12423,12424],{"class":3418,"line":3527},[3416,12425,12426],{"class":3789},"\u002F\u002F ── GetItem: отримати один елемент ────────────────────────────────────────\n",[3416,12428,12429,12431,12434,12436,12438,12440,12442,12444,12446,12448],{"class":3418,"line":3533},[3416,12430,6384],{"class":4368},[3416,12432,12433],{"class":6387}," getResponse",[3416,12435,6391],{"class":3795},[3416,12437,6413],{"class":4368},[3416,12439,6388],{"class":6387},[3416,12441,4043],{"class":3795},[3416,12443,6420],{"class":6330},[3416,12445,6423],{"class":3795},[3416,12447,6394],{"class":4368},[3416,12449,6428],{"class":6397},[3416,12451,12452],{"class":3418,"line":3539},[3416,12453,3796],{"class":3795},[3416,12455,12456,12458,12460,12462],{"class":3418,"line":3545},[3416,12457,6437],{"class":6387},[3416,12459,6391],{"class":3795},[3416,12461,6442],{"class":3808},[3416,12463,3812],{"class":3795},[3416,12465,12466,12468,12470,12472,12474,12476,12478,12480,12482],{"class":3418,"line":3551},[3416,12467,6449],{"class":6387},[3416,12469,6391],{"class":3795},[3416,12471,6394],{"class":4368},[3416,12473,6456],{"class":6397},[3416,12475,5861],{"class":3795},[3416,12477,6461],{"class":4368},[3416,12479,4384],{"class":3795},[3416,12481,6466],{"class":6397},[3416,12483,6469],{"class":3795},[3416,12485,12486],{"class":3418,"line":3557},[3416,12487,6474],{"class":3795},[3416,12489,12490,12492,12494,12496,12498,12500,12502,12504,12506,12508],{"class":3418,"line":3563},[3416,12491,6479],{"class":3795},[3416,12493,6482],{"class":3808},[3416,12495,4384],{"class":3795},[3416,12497,6394],{"class":4368},[3416,12499,6489],{"class":6397},[3416,12501,6492],{"class":3795},[3416,12503,6495],{"class":6387},[3416,12505,6391],{"class":3795},[3416,12507,6500],{"class":3808},[3416,12509,6503],{"class":3795},[3416,12511,12512,12514,12516,12518,12520,12522,12524,12526,12528,12530],{"class":3418,"line":3569},[3416,12513,6479],{"class":3795},[3416,12515,6510],{"class":3808},[3416,12517,4384],{"class":3795},[3416,12519,6394],{"class":4368},[3416,12521,6489],{"class":6397},[3416,12523,6492],{"class":3795},[3416,12525,6495],{"class":6387},[3416,12527,6391],{"class":3795},[3416,12529,6525],{"class":3808},[3416,12531,6528],{"class":3795},[3416,12533,12534],{"class":3418,"line":3574},[3416,12535,4167],{"class":3795},[3416,12537,12538],{"class":3418,"line":3579},[3416,12539,6537],{"class":3795},[3416,12541,12542],{"class":3418,"line":3584},[3416,12543,3441],{"emptyLinePlaceholder":3440},[3416,12545,12546],{"class":3418,"line":3590},[3416,12547,12548],{"class":3789},"\u002F\u002F ── Query: знайти всі сесії користувача ──────────────────────────────────\n",[3416,12550,12551,12553,12556,12558,12560,12562,12564,12566,12568,12570],{"class":3418,"line":3596},[3416,12552,6384],{"class":4368},[3416,12554,12555],{"class":6387}," queryResponse",[3416,12557,6391],{"class":3795},[3416,12559,6413],{"class":4368},[3416,12561,6388],{"class":6387},[3416,12563,4043],{"class":3795},[3416,12565,7748],{"class":6330},[3416,12567,6423],{"class":3795},[3416,12569,6394],{"class":4368},[3416,12571,7755],{"class":6397},[3416,12573,12574],{"class":3418,"line":3602},[3416,12575,3796],{"class":3795},[3416,12577,12578,12580,12582,12584],{"class":3418,"line":3608},[3416,12579,6437],{"class":6387},[3416,12581,6391],{"class":3795},[3416,12583,6442],{"class":3808},[3416,12585,3812],{"class":3795},[3416,12587,12588,12590,12592,12595],{"class":3418,"line":3614},[3416,12589,7774],{"class":6387},[3416,12591,6391],{"class":3795},[3416,12593,12594],{"class":3808},"\"UserId = :uid\"",[3416,12596,3812],{"class":3795},[3416,12598,12599,12601,12603,12605,12607,12609,12611,12613,12615],{"class":3418,"line":3620},[3416,12600,7179],{"class":6387},[3416,12602,6391],{"class":3795},[3416,12604,6394],{"class":4368},[3416,12606,6456],{"class":6397},[3416,12608,5861],{"class":3795},[3416,12610,6461],{"class":4368},[3416,12612,4384],{"class":3795},[3416,12614,6466],{"class":6397},[3416,12616,6469],{"class":3795},[3416,12618,12619],{"class":3418,"line":3626},[3416,12620,6474],{"class":3795},[3416,12622,12623,12625,12627,12629,12631,12633,12635,12637,12639,12641],{"class":3418,"line":3631},[3416,12624,6479],{"class":3795},[3416,12626,7812],{"class":3808},[3416,12628,4384],{"class":3795},[3416,12630,6394],{"class":4368},[3416,12632,6489],{"class":6397},[3416,12634,6492],{"class":3795},[3416,12636,6495],{"class":6387},[3416,12638,6391],{"class":3795},[3416,12640,6500],{"class":3808},[3416,12642,6528],{"class":3795},[3416,12644,12645],{"class":3418,"line":3636},[3416,12646,4167],{"class":3795},[3416,12648,12649],{"class":3418,"line":3641},[3416,12650,6537],{"class":3795},[3416,12652,12653],{"class":3418,"line":3647},[3416,12654,3441],{"emptyLinePlaceholder":3440},[3416,12656,12657],{"class":3418,"line":3653},[3416,12658,12659],{"class":3789},"\u002F\u002F ── UpdateItem: деактивувати сесію ────────────────────────────────────────\n",[3416,12661,12662,12664,12666,12668,12670,12672,12674],{"class":3418,"line":3659},[3416,12663,6413],{"class":4368},[3416,12665,6388],{"class":6387},[3416,12667,4043],{"class":3795},[3416,12669,7069],{"class":6330},[3416,12671,6423],{"class":3795},[3416,12673,6394],{"class":4368},[3416,12675,7076],{"class":6397},[3416,12677,12678],{"class":3418,"line":3665},[3416,12679,3796],{"class":3795},[3416,12681,12682,12684,12686,12688],{"class":3418,"line":3671},[3416,12683,6437],{"class":6387},[3416,12685,6391],{"class":3795},[3416,12687,6442],{"class":3808},[3416,12689,3812],{"class":3795},[3416,12691,12692,12694,12696,12698,12700,12702,12704,12706,12708],{"class":3418,"line":3677},[3416,12693,6449],{"class":6387},[3416,12695,6391],{"class":3795},[3416,12697,6394],{"class":4368},[3416,12699,6456],{"class":6397},[3416,12701,5861],{"class":3795},[3416,12703,6461],{"class":4368},[3416,12705,4384],{"class":3795},[3416,12707,6466],{"class":6397},[3416,12709,6469],{"class":3795},[3416,12711,12712],{"class":3418,"line":3683},[3416,12713,6474],{"class":3795},[3416,12715,12716,12718,12720,12722,12724,12726,12728,12730,12732,12734],{"class":3418,"line":3688},[3416,12717,6479],{"class":3795},[3416,12719,6482],{"class":3808},[3416,12721,4384],{"class":3795},[3416,12723,6394],{"class":4368},[3416,12725,6489],{"class":6397},[3416,12727,6492],{"class":3795},[3416,12729,6495],{"class":6387},[3416,12731,6391],{"class":3795},[3416,12733,6500],{"class":3808},[3416,12735,6503],{"class":3795},[3416,12737,12738,12740,12742,12744,12746,12748,12750,12752,12754,12756],{"class":3418,"line":3693},[3416,12739,6479],{"class":3795},[3416,12741,6510],{"class":3808},[3416,12743,4384],{"class":3795},[3416,12745,6394],{"class":4368},[3416,12747,6489],{"class":6397},[3416,12749,6492],{"class":3795},[3416,12751,6495],{"class":6387},[3416,12753,6391],{"class":3795},[3416,12755,6525],{"class":3808},[3416,12757,6528],{"class":3795},[3416,12759,12760],{"class":3418,"line":3698},[3416,12761,4442],{"class":3795},[3416,12763,12764,12766,12768,12771],{"class":3418,"line":3704},[3416,12765,7167],{"class":6387},[3416,12767,6391],{"class":3795},[3416,12769,12770],{"class":3808},"\"SET IsActive = :false\"",[3416,12772,3812],{"class":3795},[3416,12774,12775,12777,12779,12781,12783,12785,12787,12789,12791],{"class":3418,"line":3710},[3416,12776,7179],{"class":6387},[3416,12778,6391],{"class":3795},[3416,12780,6394],{"class":4368},[3416,12782,6456],{"class":6397},[3416,12784,5861],{"class":3795},[3416,12786,6461],{"class":4368},[3416,12788,4384],{"class":3795},[3416,12790,6466],{"class":6397},[3416,12792,6469],{"class":3795},[3416,12794,12795],{"class":3418,"line":3715},[3416,12796,6474],{"class":3795},[3416,12798,12800,12802,12804,12806,12808,12810,12812,12814,12816,12818],{"class":3418,"line":12799},53,[3416,12801,6479],{"class":3795},[3416,12803,7206],{"class":3808},[3416,12805,4384],{"class":3795},[3416,12807,6394],{"class":4368},[3416,12809,6489],{"class":6397},[3416,12811,6492],{"class":3795},[3416,12813,6850],{"class":6387},[3416,12815,6391],{"class":3795},[3416,12817,4042],{"class":4368},[3416,12819,6528],{"class":3795},[3416,12821,12823],{"class":3418,"line":12822},54,[3416,12824,4167],{"class":3795},[3416,12826,12828],{"class":3418,"line":12827},55,[3416,12829,6537],{"class":3795},[3416,12831,12833],{"class":3418,"line":12832},56,[3416,12834,3441],{"emptyLinePlaceholder":3440},[3416,12836,12838],{"class":3418,"line":12837},57,[3416,12839,12840],{"class":3789},"\u002F\u002F ── DeleteItem: видалити сесію ───────────────────────────────────────────\n",[3416,12842,12844,12846,12848,12850,12852,12854,12856],{"class":3418,"line":12843},58,[3416,12845,6413],{"class":4368},[3416,12847,6388],{"class":6387},[3416,12849,4043],{"class":3795},[3416,12851,7480],{"class":6330},[3416,12853,6423],{"class":3795},[3416,12855,6394],{"class":4368},[3416,12857,7487],{"class":6397},[3416,12859,12861],{"class":3418,"line":12860},59,[3416,12862,3796],{"class":3795},[3416,12864,12866,12868,12870,12872],{"class":3418,"line":12865},60,[3416,12867,6437],{"class":6387},[3416,12869,6391],{"class":3795},[3416,12871,6442],{"class":3808},[3416,12873,3812],{"class":3795},[3416,12875,12877,12879,12881,12883,12885,12887,12889,12891,12893],{"class":3418,"line":12876},61,[3416,12878,6449],{"class":6387},[3416,12880,6391],{"class":3795},[3416,12882,6394],{"class":4368},[3416,12884,6456],{"class":6397},[3416,12886,5861],{"class":3795},[3416,12888,6461],{"class":4368},[3416,12890,4384],{"class":3795},[3416,12892,6466],{"class":6397},[3416,12894,6469],{"class":3795},[3416,12896,12898],{"class":3418,"line":12897},62,[3416,12899,6474],{"class":3795},[3416,12901,12903,12905,12907,12909,12911,12913,12915,12917,12919,12921],{"class":3418,"line":12902},63,[3416,12904,6479],{"class":3795},[3416,12906,6482],{"class":3808},[3416,12908,4384],{"class":3795},[3416,12910,6394],{"class":4368},[3416,12912,6489],{"class":6397},[3416,12914,6492],{"class":3795},[3416,12916,6495],{"class":6387},[3416,12918,6391],{"class":3795},[3416,12920,6500],{"class":3808},[3416,12922,6503],{"class":3795},[3416,12924,12926,12928,12930,12932,12934,12936,12938,12940,12942,12944],{"class":3418,"line":12925},64,[3416,12927,6479],{"class":3795},[3416,12929,6510],{"class":3808},[3416,12931,4384],{"class":3795},[3416,12933,6394],{"class":4368},[3416,12935,6489],{"class":6397},[3416,12937,6492],{"class":3795},[3416,12939,6495],{"class":6387},[3416,12941,6391],{"class":3795},[3416,12943,6525],{"class":3808},[3416,12945,6528],{"class":3795},[3416,12947,12949],{"class":3418,"line":12948},65,[3416,12950,4167],{"class":3795},[3416,12952,12954],{"class":3418,"line":12953},66,[3416,12955,6537],{"class":3795},[6311,12957,12958],{"label":6540},[3406,12959,12961],{"className":6543,"code":12960,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n# ── PutItem: записати новий елемент ───────────────────────────────────────\n$item = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n    CreatedAt = New-DDBEntry -S '2025-06-01T10:00:00Z'\n    ExpiresAt = New-DDBEntry -S '2025-06-01T22:00:00Z'\n    IpAddress = New-DDBEntry -S '203.0.113.42'\n    UserAgent = New-DDBEntry -S 'Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)'\n    IsActive  = New-DDBEntry -BOOL $true\n}\nSet-DDBItem -TableName UserSessions -Item $item -Region eu-central-1\n\n# ── GetItem: отримати один елемент ────────────────────────────────────────\n$key = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n}\nGet-DDBItem -TableName UserSessions -Key $key -Region eu-central-1\n\n# ── Query: знайти всі сесії користувача ──────────────────────────────────\n$queryRequest = [Amazon.DynamoDBv2.Model.QueryRequest]@{\n    TableName                 = 'UserSessions'\n    KeyConditionExpression    = 'UserId = :uid'\n    ExpressionAttributeValues = @{\n        ':uid' = New-DDBEntry -S 'usr-001'\n    }\n}\nInvoke-DDBQuery -QueryRequest $queryRequest -Region eu-central-1\n\n# ── UpdateItem: деактивувати сесію ────────────────────────────────────────\n$updateRequest = [Amazon.DynamoDBv2.Model.UpdateItemRequest]@{\n    TableName        = 'UserSessions'\n    Key              = @{\n        UserId    = New-DDBEntry -S 'usr-001'\n        SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n    }\n    UpdateExpression = 'SET IsActive = :false'\n    ExpressionAttributeValues = @{\n        ':false' = New-DDBEntry -BOOL $false\n    }\n}\nUpdate-DDBItem -UpdateItemRequest $updateRequest -Region eu-central-1\n\n# ── DeleteItem: видалити сесію ───────────────────────────────────────────\n$delKey = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-a1b2c3d4'\n}\nRemove-DDBItem -TableName UserSessions -Key $delKey -Region eu-central-1\n",[3413,12962,12963,12971,12975,12979,12989,13001,13013,13025,13039,13053,13067,13079,13083,13095,13099,13103,13113,13125,13137,13141,13153,13157,13161,13175,13184,13193,13203,13215,13219,13223,13235,13239,13243,13257,13265,13276,13288,13300,13304,13313,13323,13335,13339,13343,13355,13359,13363,13374,13386,13398,13402],{"__ignoreMap":3411},[3416,12964,12965,12968],{"class":3418,"line":3419},[3416,12966,12967],{"class":6330},"Import-Module",[3416,12969,12970],{"class":3795}," AWS.Tools.DynamoDBv2\n",[3416,12972,12973],{"class":3418,"line":3425},[3416,12974,3441],{"emptyLinePlaceholder":3440},[3416,12976,12977],{"class":3418,"line":3431},[3416,12978,11906],{"class":3789},[3416,12980,12981,12983,12985,12987],{"class":3418,"line":3437},[3416,12982,6881],{"class":6387},[3416,12984,6391],{"class":3795},[3416,12986,6561],{"class":4368},[3416,12988,3796],{"class":3795},[3416,12990,12991,12993,12995,12997,12999],{"class":3418,"line":3444},[3416,12992,6568],{"class":6387},[3416,12994,6571],{"class":3795},[3416,12996,6574],{"class":6330},[3416,12998,6577],{"class":3795},[3416,13000,6580],{"class":3808},[3416,13002,13003,13005,13007,13009,13011],{"class":3418,"line":3450},[3416,13004,6585],{"class":6387},[3416,13006,6391],{"class":3795},[3416,13008,6574],{"class":6330},[3416,13010,6577],{"class":3795},[3416,13012,6594],{"class":3808},[3416,13014,13015,13017,13019,13021,13023],{"class":3418,"line":3456},[3416,13016,6916],{"class":6387},[3416,13018,6391],{"class":3795},[3416,13020,6574],{"class":6330},[3416,13022,6577],{"class":3795},[3416,13024,6925],{"class":3808},[3416,13026,13027,13030,13032,13034,13036],{"class":3418,"line":3462},[3416,13028,13029],{"class":6387},"    ExpiresAt",[3416,13031,6391],{"class":3795},[3416,13033,6574],{"class":6330},[3416,13035,6577],{"class":3795},[3416,13037,13038],{"class":3808},"'2025-06-01T22:00:00Z'\n",[3416,13040,13041,13044,13046,13048,13050],{"class":3418,"line":3468},[3416,13042,13043],{"class":6387},"    IpAddress",[3416,13045,6391],{"class":3795},[3416,13047,6574],{"class":6330},[3416,13049,6577],{"class":3795},[3416,13051,13052],{"class":3808},"'203.0.113.42'\n",[3416,13054,13055,13058,13060,13062,13064],{"class":3418,"line":3474},[3416,13056,13057],{"class":6387},"    UserAgent",[3416,13059,6391],{"class":3795},[3416,13061,6574],{"class":6330},[3416,13063,6577],{"class":3795},[3416,13065,13066],{"class":3808},"'Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64)'\n",[3416,13068,13069,13071,13073,13075,13077],{"class":3418,"line":3480},[3416,13070,6930],{"class":6387},[3416,13072,6933],{"class":3795},[3416,13074,6574],{"class":6330},[3416,13076,6938],{"class":3795},[3416,13078,6941],{"class":4368},[3416,13080,13081],{"class":3418,"line":3486},[3416,13082,3507],{"class":3795},[3416,13084,13085,13087,13089,13091,13093],{"class":3418,"line":3492},[3416,13086,6950],{"class":6330},[3416,13088,6953],{"class":3795},[3416,13090,6881],{"class":6387},[3416,13092,6611],{"class":3795},[3416,13094,6614],{"class":3870},[3416,13096,13097],{"class":3418,"line":3498},[3416,13098,3441],{"emptyLinePlaceholder":3440},[3416,13100,13101],{"class":3418,"line":3504},[3416,13102,11982],{"class":3789},[3416,13104,13105,13107,13109,13111],{"class":3418,"line":3510},[3416,13106,6556],{"class":6387},[3416,13108,6391],{"class":3795},[3416,13110,6561],{"class":4368},[3416,13112,3796],{"class":3795},[3416,13114,13115,13117,13119,13121,13123],{"class":3418,"line":3515},[3416,13116,6568],{"class":6387},[3416,13118,6571],{"class":3795},[3416,13120,6574],{"class":6330},[3416,13122,6577],{"class":3795},[3416,13124,6580],{"class":3808},[3416,13126,13127,13129,13131,13133,13135],{"class":3418,"line":3521},[3416,13128,6585],{"class":6387},[3416,13130,6391],{"class":3795},[3416,13132,6574],{"class":6330},[3416,13134,6577],{"class":3795},[3416,13136,6594],{"class":3808},[3416,13138,13139],{"class":3418,"line":3527},[3416,13140,3507],{"class":3795},[3416,13142,13143,13145,13147,13149,13151],{"class":3418,"line":3533},[3416,13144,6603],{"class":6330},[3416,13146,6606],{"class":3795},[3416,13148,6556],{"class":6387},[3416,13150,6611],{"class":3795},[3416,13152,6614],{"class":3870},[3416,13154,13155],{"class":3418,"line":3539},[3416,13156,3441],{"emptyLinePlaceholder":3440},[3416,13158,13159],{"class":3418,"line":3545},[3416,13160,12023],{"class":3789},[3416,13162,13163,13165,13167,13169,13171,13173],{"class":3418,"line":3551},[3416,13164,7877],{"class":6387},[3416,13166,7274],{"class":3795},[3416,13168,7882],{"class":4368},[3416,13170,7280],{"class":3795},[3416,13172,6561],{"class":4368},[3416,13174,3796],{"class":3795},[3416,13176,13177,13179,13182],{"class":3418,"line":3557},[3416,13178,6437],{"class":6387},[3416,13180,13181],{"class":3795},"                 = ",[3416,13183,7293],{"class":3808},[3416,13185,13186,13188,13190],{"class":3418,"line":3563},[3416,13187,7774],{"class":6387},[3416,13189,6571],{"class":3795},[3416,13191,13192],{"class":3808},"'UserId = :uid'\n",[3416,13194,13195,13197,13199,13201],{"class":3418,"line":3569},[3416,13196,7179],{"class":6387},[3416,13198,6391],{"class":3795},[3416,13200,6561],{"class":4368},[3416,13202,3796],{"class":3795},[3416,13204,13205,13207,13209,13211,13213],{"class":3418,"line":3574},[3416,13206,7920],{"class":3808},[3416,13208,6391],{"class":3795},[3416,13210,6574],{"class":6330},[3416,13212,6577],{"class":3795},[3416,13214,6580],{"class":3808},[3416,13216,13217],{"class":3418,"line":3579},[3416,13218,4167],{"class":3795},[3416,13220,13221],{"class":3418,"line":3584},[3416,13222,3507],{"class":3795},[3416,13224,13225,13227,13229,13231,13233],{"class":3418,"line":3590},[3416,13226,7956],{"class":6330},[3416,13228,7959],{"class":3795},[3416,13230,7877],{"class":6387},[3416,13232,6611],{"class":3795},[3416,13234,6614],{"class":3870},[3416,13236,13237],{"class":3418,"line":3596},[3416,13238,3441],{"emptyLinePlaceholder":3440},[3416,13240,13241],{"class":3418,"line":3602},[3416,13242,12074],{"class":3789},[3416,13244,13245,13247,13249,13251,13253,13255],{"class":3418,"line":3608},[3416,13246,7271],{"class":6387},[3416,13248,7274],{"class":3795},[3416,13250,7277],{"class":4368},[3416,13252,7280],{"class":3795},[3416,13254,6561],{"class":4368},[3416,13256,3796],{"class":3795},[3416,13258,13259,13261,13263],{"class":3418,"line":3614},[3416,13260,6437],{"class":6387},[3416,13262,7923],{"class":3795},[3416,13264,7293],{"class":3808},[3416,13266,13267,13269,13272,13274],{"class":3418,"line":3620},[3416,13268,6449],{"class":6387},[3416,13270,13271],{"class":3795},"              = ",[3416,13273,6561],{"class":4368},[3416,13275,3796],{"class":3795},[3416,13277,13278,13280,13282,13284,13286],{"class":3418,"line":3626},[3416,13279,7308],{"class":6387},[3416,13281,6571],{"class":3795},[3416,13283,6574],{"class":6330},[3416,13285,6577],{"class":3795},[3416,13287,6580],{"class":3808},[3416,13289,13290,13292,13294,13296,13298],{"class":3418,"line":3631},[3416,13291,7321],{"class":6387},[3416,13293,6391],{"class":3795},[3416,13295,6574],{"class":6330},[3416,13297,6577],{"class":3795},[3416,13299,6594],{"class":3808},[3416,13301,13302],{"class":3418,"line":3636},[3416,13303,4167],{"class":3795},[3416,13305,13306,13308,13310],{"class":3418,"line":3641},[3416,13307,7167],{"class":6387},[3416,13309,6391],{"class":3795},[3416,13311,13312],{"class":3808},"'SET IsActive = :false'\n",[3416,13314,13315,13317,13319,13321],{"class":3418,"line":3647},[3416,13316,7179],{"class":6387},[3416,13318,6391],{"class":3795},[3416,13320,6561],{"class":4368},[3416,13322,3796],{"class":3795},[3416,13324,13325,13327,13329,13331,13333],{"class":3418,"line":3653},[3416,13326,7357],{"class":3808},[3416,13328,6391],{"class":3795},[3416,13330,6574],{"class":6330},[3416,13332,6938],{"class":3795},[3416,13334,7366],{"class":4368},[3416,13336,13337],{"class":3418,"line":3659},[3416,13338,4167],{"class":3795},[3416,13340,13341],{"class":3418,"line":3665},[3416,13342,3507],{"class":3795},[3416,13344,13345,13347,13349,13351,13353],{"class":3418,"line":3671},[3416,13346,7394],{"class":6330},[3416,13348,7397],{"class":3795},[3416,13350,7271],{"class":6387},[3416,13352,6611],{"class":3795},[3416,13354,6614],{"class":3870},[3416,13356,13357],{"class":3418,"line":3677},[3416,13358,3441],{"emptyLinePlaceholder":3440},[3416,13360,13361],{"class":3418,"line":3683},[3416,13362,12133],{"class":3789},[3416,13364,13365,13368,13370,13372],{"class":3418,"line":3688},[3416,13366,13367],{"class":6387},"$delKey",[3416,13369,6391],{"class":3795},[3416,13371,6561],{"class":4368},[3416,13373,3796],{"class":3795},[3416,13375,13376,13378,13380,13382,13384],{"class":3418,"line":3693},[3416,13377,6568],{"class":6387},[3416,13379,6571],{"class":3795},[3416,13381,6574],{"class":6330},[3416,13383,6577],{"class":3795},[3416,13385,6580],{"class":3808},[3416,13387,13388,13390,13392,13394,13396],{"class":3418,"line":3698},[3416,13389,6585],{"class":6387},[3416,13391,6391],{"class":3795},[3416,13393,6574],{"class":6330},[3416,13395,6577],{"class":3795},[3416,13397,6594],{"class":3808},[3416,13399,13400],{"class":3418,"line":3704},[3416,13401,3507],{"class":3795},[3416,13403,13404,13406,13408,13410,13412],{"class":3418,"line":3710},[3416,13405,7632],{"class":6330},[3416,13407,6606],{"class":3795},[3416,13409,13367],{"class":6387},[3416,13411,6611],{"class":3795},[3416,13413,6614],{"class":3870},[11159,13415,13417,13426,13429,13436,13440,13454,13467,13481,13493,13496,13500,13511,13521],{"title":13416},"Query: всі сесії користувача usr-001",[11163,13418,13420,10466,13423],{"className":13419},[3418],[3416,13421,11170],{"className":13422},[11169],[3363,13424,13425],{},"aws dynamodb query --table-name UserSessions --key-condition-expression \"UserId = :uid\" ...",[11163,13427,11177],{"className":13428},[3418],[11163,13430,11181,13432,4378],{"className":13431},[3418],[3416,13433,13435],{"className":13434},[11185],"\"Items\"",[11163,13437,13439],{"className":13438},[3418],"        {",[11163,13441,11282,13443,13446,13447,3805,13451,11250],{"className":13442},[3418],[3416,13444,6482],{"className":13445},[11185],":    { ",[3416,13448,13450],{"className":13449},[11185],"\"S\"",[3416,13452,6500],{"className":13453},[11199],[11163,13455,11282,13457,13460,13461,3805,13464,11250],{"className":13456},[3418],[3416,13458,6510],{"className":13459},[11185],": { ",[3416,13462,13450],{"className":13463},[11185],[3416,13465,6525],{"className":13466},[11199],[11163,13468,11282,13470,13473,13474,3805,13478,11250],{"className":13469},[3418],[3416,13471,6839],{"className":13472},[11185],":  { ",[3416,13475,13477],{"className":13476},[11185],"\"BOOL\"",[3416,13479,4038],{"className":13480},[11211],[11163,13482,11282,13484,13460,13487,3805,13490,11267],{"className":13483},[3418],[3416,13485,6815],{"className":13486},[11185],[3416,13488,13450],{"className":13489},[11185],[3416,13491,6830],{"className":13492},[11199],[11163,13494,11294],{"className":13495},[3418],[11163,13497,13499],{"className":13498},[3418],"    ],",[11163,13501,11181,13503,3805,13507,11200],{"className":13502},[3418],[3416,13504,13506],{"className":13505},[11185],"\"Count\"",[3416,13508,13510],{"className":13509},[11211],"1",[11163,13512,11181,13514,3805,13518],{"className":13513},[3418],[3416,13515,13517],{"className":13516},[11185],"\"ScannedCount\"",[3416,13519,13510],{"className":13520},[11211],[11163,13522,11302],{"className":13523},[3418],[3720,13525],{},[3348,13527,13529],{"id":13528},"одиниці-пропускної-здатності-rcu-та-wcu","Одиниці пропускної здатності: RCU та WCU",[3353,13531,13532,13533,4043],{},"Для розробки ефективних архітектур на базі Amazon DynamoDB та прогнозування витрат критично важливо розуміти її внутрішню модель тарифікації та розподілу ресурсів. На відміну від традиційних реляційних СУБД, де продуктивність лімітується апаратними характеристиками сервера (кількістю ядер CPU, обсягом RAM та IOPS накопичувачів), DynamoDB абстрагує фізичні ресурси за допомогою ",[3363,13534,13535],{},"одиниць пропускної здатності (Capacity Units)",[3353,13537,13538,13539,13542,13543,13546],{},"Цей підхід дозволяє гарантувати передбачувану пропускну здатність незалежно від загального обсягу даних у таблиці. Вся ємність вимірюється двома метриками: ",[3363,13540,13541],{},"Read Capacity Units (RCU)"," для операцій читання та ",[3363,13544,13545],{},"Write Capacity Units (WCU)"," для операцій запису.",[3720,13548],{},[3727,13550,13541],{"id":13551},"read-capacity-units-rcu",[3353,13553,13554,13557],{},[3363,13555,13556],{},"1 RCU (Read Capacity Unit)"," визначається як потужність системи, необхідна для виконання:",[4488,13559,13560,13570,13578],{},[3377,13561,13562,13565,13566,13569],{},[3363,13563,13564],{},"1 Strongly Consistent Read"," (сильно узгодженого читання) одного елемента розміром до ",[3363,13567,13568],{},"4 KB"," за секунду.",[3377,13571,13572,13575,13576,13569],{},[3363,13573,13574],{},"2 Eventually Consistent Reads"," (кінцево узгоджених читань) елементів розміром до ",[3363,13577,13568],{},[3377,13579,13580,13583,13584,13586,13587,13590],{},[3363,13581,13582],{},"0.5 Transactional Read"," (транзакційного читання) одного елемента розміром до ",[3363,13585,13568],{}," за секунду (тобто для транзакційного читання 1 елемента до 4 KB потрібно ",[3363,13588,13589],{},"2 RCU",").",[4584,13592,13594],{"id":13593},"моделі-узгодженості-читання-read-consistency-models","Моделі узгодженості читання (Read Consistency Models)",[3374,13596,13597,13607,13616],{},[3377,13598,13599,13602,13603,13606],{},[3363,13600,13601],{},"Eventually Consistent Reads (Кінцева узгодженість):","\nПри записі даних DynamoDB асинхронно реплікує зміни на три географічно розподілені вузли зберігання (storage nodes) в межах однієї Availability Zone. Eventually Consistent читання повертає результат з будь-якої випадкової репліки. Існує мінімальна ймовірність (зазвичай \u003C 1 секунди), що запит поверне застарілі дані, якщо реплікація ще не завершилась. Цей режим споживає вдвічі менше ресурсів — ",[3363,13604,13605],{},"0.5 RCU"," за кожні 4 KB.",[3377,13608,13609,13612,13613,13606],{},[3363,13610,13611],{},"Strongly Consistent Reads (Сильна узгодженість):","\nЗапит направляється до реплік та очікує підтвердження від більшості вузлів (quorum), гарантуючи повернення найактуальнішого стану даних. Цей режим є дорожчим та споживає ",[3363,13614,13615],{},"1 RCU",[3377,13617,13618,13621,13622,13625,13626,13606],{},[3363,13619,13620],{},"Transactional Reads (Транзакційне читання):","\nВикористовується в межах ACID-транзакцій через API ",[3413,13623,13624],{},"TransactGetItems",". Забезпечує ізольовано та атомарно читання групи елементів. Споживає ",[3363,13627,13589],{},[4584,13629,13631],{"id":13630},"математичне-округлення-розміру-елементів","Математичне округлення розміру елементів",[3353,13633,13634,13635,13637],{},"При обчисленні RCU розмір кожного зчитуваного елемента спочатку округляється в більшу сторону до найближчого кратного ",[3363,13636,13568],{},". Наприклад:",[4488,13639,13640,13650],{},[3377,13641,13642,13643,13646,13647,13649],{},"Елемент розміром ",[3363,13644,13645],{},"2.5 KB"," округляється до ",[3363,13648,13568],{}," (1 блок).",[3377,13651,13642,13652,13646,13655,13658],{},[3363,13653,13654],{},"5.0 KB",[3363,13656,13657],{},"8 KB"," (2 блоки).",[4584,13660,13662],{"id":13661},"формула-розрахунку-rcu","Формула розрахунку RCU",[3353,13664,13665],{},"Математична модель розрахунку необхідної кількості RCU виглядає наступним чином:",[13667,13668,13669],"math-formula",{},"\\text{RCU} = \\left\\lceil \\frac{\\text{Розмір елемента (KB)}}{4\\text{ KB}} \\right\\rceil \\times \\text{Кількість операцій\u002Fсек} \\times \\text{Коефіцієнт узгодженості}",[3353,13671,13672,13673,13676],{},"Де ",[3363,13674,13675],{},"Коефіцієнт узгодженості"," дорівнює:",[4488,13678,13679,13685,13691],{},[3377,13680,13681,13684],{},[3363,13682,13683],{},"0.5"," — для Eventually Consistent читання.",[3377,13686,13687,13690],{},[3363,13688,13689],{},"1.0"," — для Strongly Consistent читання.",[3377,13692,13693,13696,13697,13590],{},[3363,13694,13695],{},"2.0"," — для Transactional читання (",[3413,13698,13624],{},[4584,13700,13702],{"id":13701},"покрокові-приклади-розрахунку-rcu","Покрокові приклади розрахунку RCU",[4488,13704,13705,13730,13752],{},[3377,13706,13707,13710],{},[3363,13708,13709],{},"Приклад 1: Масове читання профілів користувачів",[4488,13711,13712,13718,13724],{},[3377,13713,13714,13717],{},[4091,13715,13716],{},"Умова:"," Потрібно забезпечити 150 Eventually Consistent читань на секунду. Розмір одного профілю (елемента) становить 3.5 KB.",[3377,13719,13720,13723],{},[4091,13721,13722],{},"Крок 1 (Округлення розміру):"," ⌈3.5 KB \u002F 4 KB⌉ = 1 блок.",[3377,13725,13726,13729],{},[4091,13727,13728],{},"Крок 2 (Розрахунок за формулою):"," 1 × 150 × 0.5 = 75 RCU.",[3377,13731,13732,13735],{},[3363,13733,13734],{},"Приклад 2: Читання фінансових транзакцій з високою узгодженістю",[4488,13736,13737,13742,13747],{},[3377,13738,13739,13741],{},[4091,13740,13716],{}," Необхідно виконувати 80 Strongly Consistent читань на секунду. Розмір елемента транзакції — 9.2 KB.",[3377,13743,13744,13746],{},[4091,13745,13722],{}," ⌈9.2 KB \u002F 4 KB⌉ = ⌈2.3 блоки⌉ = 3 блоки.",[3377,13748,13749,13751],{},[4091,13750,13728],{}," 3 × 80 × 1.0 = 240 RCU.",[3377,13753,13754,13757],{},[3363,13755,13756],{},"Приклад 3: Транзакційна перевірка балансу",[4488,13758,13759,13767,13772],{},[3377,13760,13761,13763,13764,13766],{},[4091,13762,13716],{}," Потрібно зчитувати 50 балансів на секунду через ",[3413,13765,13624],{},". Розмір запису балансу — 1.5 KB.",[3377,13768,13769,13771],{},[4091,13770,13722],{}," ⌈1.5 KB \u002F 4 KB⌉ = 1 блок.",[3377,13773,13774,13776],{},[4091,13775,13728],{}," 1 × 50 × 2.0 = 100 RCU.",[3720,13778],{},[3727,13780,13545],{"id":13781},"write-capacity-units-wcu",[3353,13783,13784,13557],{},[3363,13785,13786],{},"1 WCU (Write Capacity Unit)",[4488,13788,13789,13798],{},[3377,13790,13791,13794,13795,13569],{},[3363,13792,13793],{},"1 стандартного запису"," (PutItem, UpdateItem, DeleteItem) одного елемента розміром до ",[3363,13796,13797],{},"1 KB",[3377,13799,13800,13803,13804,13806,13807,13590],{},[3363,13801,13802],{},"0.5 транзакційного запису"," (TransactWriteItems) одного елемента розміром до ",[3363,13805,13797],{}," за секунду (тобто для транзакційного запису 1 елемента до 1 KB потрібно ",[3363,13808,13809],{},"2 WCU",[4584,13811,13813],{"id":13812},"особливості-операцій-запису","Особливості операцій запису",[3374,13815,13816,13822,13832],{},[3377,13817,13818,13821],{},[3363,13819,13820],{},"Співвідношення з читанням:","\nЗаписи в DynamoDB є в 4 рази \"дорожчими\" з точки зору розміру даних: якщо 1 RCU покриває 4 KB, то 1 WCU покриває лише 1 KB. Це зумовлено необхідністю синхронної реплікації змін на кілька фізичних вузлів для запобігання втрати даних.",[3377,13823,13824,13827,13828,13831],{},[3363,13825,13826],{},"Умовні записи (Conditional Writes):","\nВикористання ",[3413,13829,13830],{},"ConditionExpression"," (наприклад, перевірка чи існує email перед створенням користувача) не змінює вартість успішного запису. Однак, якщо умова не виконується і запис скасовується, DynamoDB все одно стягує WCU за перевірку, якщо запит намагався перезаписати існуючий елемент.",[3377,13833,13834,13837,13838,13841,13842,13844],{},[3363,13835,13836],{},"Транзакційні записи (Transactional Writes):","\nВиконуються через ",[3413,13839,13840],{},"TransactWriteItems"," для забезпечення атомарності групи записів (до 100 елементів). Кожен запис у транзакції коштує вдвічі дорожче — ",[3363,13843,13809],{}," за 1 KB.",[4584,13846,13848],{"id":13847},"математичне-округшення-розміру-елементів","Математичне округшення розміру елементів",[3353,13850,13851,13852,13637],{},"При обчисленні WCU розмір кожного записуваного або оновлюваного елемента округляється в більшу сторону до найближчого кратного ",[3363,13853,13797],{},[4488,13855,13856,13864],{},[3377,13857,13858,13859,13646,13862,13649],{},"Запис розміром ",[3363,13860,13861],{},"450 байт",[3363,13863,13797],{},[3377,13865,13858,13866,13646,13869,13872],{},[3363,13867,13868],{},"2.1 KB",[3363,13870,13871],{},"3 KB"," (3 блоки).",[4584,13874,13876],{"id":13875},"формула-розрахунку-wcu","Формула розрахунку WCU",[3353,13878,13879],{},"Математична модель розрахунку необхідної кількості WCU:",[13667,13881,13882],{},"\\text{WCU} = \\left\\lceil \\frac{\\text{Розмір елемента (KB)}}{1\\text{ KB}} \\right\\rceil \\times \\text{Кількість операцій\u002Fсек} \\times \\text{Коефіцієнт запису}",[3353,13884,13672,13885,13676],{},[3363,13886,13887],{},"Коефіцієнт запису",[4488,13889,13890,13895],{},[3377,13891,13892,13894],{},[3363,13893,13689],{}," — для стандартних записів (Put, Update, Delete, включно з умовними).",[3377,13896,13897,13899,13900,13590],{},[3363,13898,13695],{}," — для транзакційних записів (",[3413,13901,13840],{},[4584,13903,13905],{"id":13904},"покрокові-приклади-розрахунку-wcu","Покрокові приклади розрахунку WCU",[4488,13907,13908,13930,13952],{},[3377,13909,13910,13913],{},[3363,13911,13912],{},"Приклад 1: Логування IoT-метрик",[4488,13914,13915,13920,13925],{},[3377,13916,13917,13919],{},[4091,13918,13716],{}," Пристрій відправляє 200 метрик на секунду. Розмір одного повідомлення — 600 байт.",[3377,13921,13922,13924],{},[4091,13923,13722],{}," ⌈0.6 KB \u002F 1 KB⌉ = 1 блок.",[3377,13926,13927,13929],{},[4091,13928,13728],{}," 1 × 200 × 1.0 = 200 WCU.",[3377,13931,13932,13935],{},[3363,13933,13934],{},"Приклад 2: Оновлення профілів користувачів",[4488,13936,13937,13942,13947],{},[3377,13938,13939,13941],{},[4091,13940,13716],{}," Користувачі роблять 45 оновлень профілю на секунду. Розмір оновленого запису — 2.4 KB.",[3377,13943,13944,13946],{},[4091,13945,13722],{}," ⌈2.4 KB \u002F 1 KB⌉ = 3 блоки.",[3377,13948,13949,13951],{},[4091,13950,13728],{}," 3 × 45 × 1.0 = 135 WCU.",[3377,13953,13954,13957],{},[3363,13955,13956],{},"Приклад 3: Оформлення замовлення транзакцією",[4488,13958,13959,13964,13970,13976],{},[3377,13960,13961,13963],{},[4091,13962,13716],{}," Система обробляє 10 замовлень на секунду. Транзакція записує 1 замовлення (розмір 1.2 KB) та оновлює складські запаси (розмір 0.8 KB).",[3377,13965,13966,13969],{},[4091,13967,13968],{},"Крок 1 (Замовлення):"," Розмір 1.2 KB оновлюється до 2 KB. Вартість: 2 × 10 × 2.0 = 40 WCU.",[3377,13971,13972,13975],{},[4091,13973,13974],{},"Крок 2 (Склад):"," Розмір 0.8 KB оновлюється до 1 KB. Вартість: 1 × 10 × 2.0 = 20 WCU.",[3377,13977,13978,13981],{},[4091,13979,13980],{},"Загальна вартість:"," 40 + 20 = 60 WCU.",[3720,13983],{},[3727,13985,13987],{"id":13986},"зведена-порівняльна-таблиця-вартості-ємностей","Зведена порівняльна таблиця вартості ємностей",[3756,13989,13990,14006],{},[4617,13991,13992],{},[4620,13993,13994,13997,14000,14003],{},[4623,13995,13996],{"align":4625},"Операція",[4623,13998,13999],{"align":4625},"Одиниці базового виміру",[4623,14001,14002],{"align":4625},"Коефіцієнт (Multiplier)",[4623,14004,14005],{"align":4625},"Вартість 1 операції до базового розміру",[4657,14007,14008,14023,14039,14055,14071],{},[4620,14009,14010,14015,14017,14019],{},[4662,14011,14012],{"align":4625},[3363,14013,14014],{},"Eventually Consistent Read",[4662,14016,13568],{"align":4625},[4662,14018,13683],{"align":4625},[4662,14020,14021],{"align":4625},[3363,14022,13605],{},[4620,14024,14025,14030,14032,14034],{},[4662,14026,14027],{"align":4625},[3363,14028,14029],{},"Strongly Consistent Read",[4662,14031,13568],{"align":4625},[4662,14033,13689],{"align":4625},[4662,14035,14036],{"align":4625},[3363,14037,14038],{},"1.0 RCU",[4620,14040,14041,14046,14048,14050],{},[4662,14042,14043],{"align":4625},[3363,14044,14045],{},"Transactional Read",[4662,14047,13568],{"align":4625},[4662,14049,13695],{"align":4625},[4662,14051,14052],{"align":4625},[3363,14053,14054],{},"2.0 RCU",[4620,14056,14057,14062,14064,14066],{},[4662,14058,14059],{"align":4625},[3363,14060,14061],{},"Standard Write (Put\u002FUpdate\u002FDelete)",[4662,14063,13797],{"align":4625},[4662,14065,13689],{"align":4625},[4662,14067,14068],{"align":4625},[3363,14069,14070],{},"1.0 WCU",[4620,14072,14073,14078,14080,14082],{},[4662,14074,14075],{"align":4625},[3363,14076,14077],{},"Transactional Write",[4662,14079,13797],{"align":4625},[4662,14081,13695],{"align":4625},[4662,14083,14084],{"align":4625},[3363,14085,14086],{},"2.0 WCU",[3353,14088,14089],{},"::",[3403,14091,14092],{},[3406,14093,14095],{"className":3408,"code":14094,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Розрахунок потрібних RCU\u002FWCU для UserSessions API\"\n\nrectangle \"Вимоги системи (peak load)\" as REQ #fef3c7 {\n    note as REQ_NOTE\n      - 500 GetItem (сесій\u002Fс)   — розмір ~0.5 KB, eventually consistent\n      - 200 PutItem (нових сесій\u002Fс) — розмір ~0.8 KB\n      - 100 Query (списків сесій\u002Fс) — по 5 елементів, ~0.5 KB кожен\n      - 50  UpdateItem (оновлень\u002Fс) — розмір ~0.8 KB\n    end note\n}\n\nrectangle \"Розрахунок RCU\" as CALC_RCU #dbeafe {\n    note as CALC_RCU_NOTE\n      GetItem: ceil(0.5\u002F4) × 500 × 0.5 = 1 × 500 × 0.5 = 250 RCU\n      Query:   ceil(0.5\u002F4) × 5 elem × 100 × 0.5 = 250 RCU\n      ─────────────────────────────────────────────────\n      Разом RCU: 250 + 250 = 500 RCU\n    end note\n}\n\nrectangle \"Розрахунок WCU\" as CALC_WCU #d1fae5 {\n    note as CALC_WCU_NOTE\n      PutItem:    ceil(0.8\u002F1) × 200 = 1 × 200 = 200 WCU\n      UpdateItem: ceil(0.8\u002F1) × 50  = 1 × 50  =  50 WCU\n      ─────────────────────────────────────────────────\n      Разом WCU: 200 + 50 = 250 WCU\n    end note\n}\n\nREQ --> CALC_RCU\nREQ --> CALC_WCU\n\nnote bottom of CALC_WCU\n  У режимі On-Demand: платите лише за\n  використані RCU\u002FWCU — не потрібно\n  прогнозувати заздалегідь.\n  У режимі Provisioned: виставити\n  Provisioned RCU=500, WCU=250\n  (або з Auto Scaling).\nend note\n\n@enduml\n",[3413,14096,14097,14101,14105,14109,14113,14118,14122,14127,14132,14137,14142,14147,14152,14156,14160,14164,14169,14174,14179,14184,14189,14194,14198,14202,14206,14211,14216,14221,14226,14230,14235,14239,14243,14247,14252,14257,14261,14266,14271,14276,14281,14286,14291,14296,14300,14304],{"__ignoreMap":3411},[3416,14098,14099],{"class":3418,"line":3419},[3416,14100,3422],{},[3416,14102,14103],{"class":3418,"line":3425},[3416,14104,3428],{},[3416,14106,14107],{"class":3418,"line":3431},[3416,14108,3434],{},[3416,14110,14111],{"class":3418,"line":3437},[3416,14112,3441],{"emptyLinePlaceholder":3440},[3416,14114,14115],{"class":3418,"line":3444},[3416,14116,14117],{},"title \"Розрахунок потрібних RCU\u002FWCU для UserSessions API\"\n",[3416,14119,14120],{"class":3418,"line":3450},[3416,14121,3441],{"emptyLinePlaceholder":3440},[3416,14123,14124],{"class":3418,"line":3456},[3416,14125,14126],{},"rectangle \"Вимоги системи (peak load)\" as REQ #fef3c7 {\n",[3416,14128,14129],{"class":3418,"line":3462},[3416,14130,14131],{},"    note as REQ_NOTE\n",[3416,14133,14134],{"class":3418,"line":3468},[3416,14135,14136],{},"      - 500 GetItem (сесій\u002Fс)   — розмір ~0.5 KB, eventually consistent\n",[3416,14138,14139],{"class":3418,"line":3474},[3416,14140,14141],{},"      - 200 PutItem (нових сесій\u002Fс) — розмір ~0.8 KB\n",[3416,14143,14144],{"class":3418,"line":3480},[3416,14145,14146],{},"      - 100 Query (списків сесій\u002Fс) — по 5 елементів, ~0.5 KB кожен\n",[3416,14148,14149],{"class":3418,"line":3486},[3416,14150,14151],{},"      - 50  UpdateItem (оновлень\u002Fс) — розмір ~0.8 KB\n",[3416,14153,14154],{"class":3418,"line":3492},[3416,14155,3501],{},[3416,14157,14158],{"class":3418,"line":3498},[3416,14159,3507],{},[3416,14161,14162],{"class":3418,"line":3504},[3416,14163,3441],{"emptyLinePlaceholder":3440},[3416,14165,14166],{"class":3418,"line":3510},[3416,14167,14168],{},"rectangle \"Розрахунок RCU\" as CALC_RCU #dbeafe {\n",[3416,14170,14171],{"class":3418,"line":3515},[3416,14172,14173],{},"    note as CALC_RCU_NOTE\n",[3416,14175,14176],{"class":3418,"line":3521},[3416,14177,14178],{},"      GetItem: ceil(0.5\u002F4) × 500 × 0.5 = 1 × 500 × 0.5 = 250 RCU\n",[3416,14180,14181],{"class":3418,"line":3527},[3416,14182,14183],{},"      Query:   ceil(0.5\u002F4) × 5 elem × 100 × 0.5 = 250 RCU\n",[3416,14185,14186],{"class":3418,"line":3533},[3416,14187,14188],{},"      ─────────────────────────────────────────────────\n",[3416,14190,14191],{"class":3418,"line":3539},[3416,14192,14193],{},"      Разом RCU: 250 + 250 = 500 RCU\n",[3416,14195,14196],{"class":3418,"line":3545},[3416,14197,3501],{},[3416,14199,14200],{"class":3418,"line":3551},[3416,14201,3507],{},[3416,14203,14204],{"class":3418,"line":3557},[3416,14205,3441],{"emptyLinePlaceholder":3440},[3416,14207,14208],{"class":3418,"line":3563},[3416,14209,14210],{},"rectangle \"Розрахунок WCU\" as CALC_WCU #d1fae5 {\n",[3416,14212,14213],{"class":3418,"line":3569},[3416,14214,14215],{},"    note as CALC_WCU_NOTE\n",[3416,14217,14218],{"class":3418,"line":3574},[3416,14219,14220],{},"      PutItem:    ceil(0.8\u002F1) × 200 = 1 × 200 = 200 WCU\n",[3416,14222,14223],{"class":3418,"line":3579},[3416,14224,14225],{},"      UpdateItem: ceil(0.8\u002F1) × 50  = 1 × 50  =  50 WCU\n",[3416,14227,14228],{"class":3418,"line":3584},[3416,14229,14188],{},[3416,14231,14232],{"class":3418,"line":3590},[3416,14233,14234],{},"      Разом WCU: 200 + 50 = 250 WCU\n",[3416,14236,14237],{"class":3418,"line":3596},[3416,14238,3501],{},[3416,14240,14241],{"class":3418,"line":3602},[3416,14242,3507],{},[3416,14244,14245],{"class":3418,"line":3608},[3416,14246,3441],{"emptyLinePlaceholder":3440},[3416,14248,14249],{"class":3418,"line":3614},[3416,14250,14251],{},"REQ --> CALC_RCU\n",[3416,14253,14254],{"class":3418,"line":3620},[3416,14255,14256],{},"REQ --> CALC_WCU\n",[3416,14258,14259],{"class":3418,"line":3626},[3416,14260,3441],{"emptyLinePlaceholder":3440},[3416,14262,14263],{"class":3418,"line":3631},[3416,14264,14265],{},"note bottom of CALC_WCU\n",[3416,14267,14268],{"class":3418,"line":3636},[3416,14269,14270],{},"  У режимі On-Demand: платите лише за\n",[3416,14272,14273],{"class":3418,"line":3641},[3416,14274,14275],{},"  використані RCU\u002FWCU — не потрібно\n",[3416,14277,14278],{"class":3418,"line":3647},[3416,14279,14280],{},"  прогнозувати заздалегідь.\n",[3416,14282,14283],{"class":3418,"line":3653},[3416,14284,14285],{},"  У режимі Provisioned: виставити\n",[3416,14287,14288],{"class":3418,"line":3659},[3416,14289,14290],{},"  Provisioned RCU=500, WCU=250\n",[3416,14292,14293],{"class":3418,"line":3665},[3416,14294,14295],{},"  (або з Auto Scaling).\n",[3416,14297,14298],{"class":3418,"line":3671},[3416,14299,5088],{},[3416,14301,14302],{"class":3418,"line":3677},[3416,14303,3441],{"emptyLinePlaceholder":3440},[3416,14305,14306],{"class":3418,"line":3683},[3416,14307,3718],{},[3720,14309],{},[3348,14311,14313],{"id":14312},"secondary-indexes-запити-поза-первинним-ключем","Secondary Indexes: запити поза первинним ключем",[3353,14315,14316,14317,14320,14321,14323,14324,14326,14327,14329],{},"Ми з'ясували фундаментальне обмеження DynamoDB: операція Query може шукати елементи ",[3363,14318,14319],{},"лише за Partition Key"," основної таблиці. Це означає, що таблиця ",[3413,14322,10457],{}," з PK=",[3413,14325,4494],{}," \u002F SK=",[3413,14328,8903],{}," ефективно відповідає на запитання «які сесії має користувач X?», але абсолютно не здатна відповісти на «які сесії закінчились до певної дати?» або «які сесії з конкретної IP-адреси?» — без повного Scan всієї таблиці.",[3353,14331,14332,14333,14336],{},"DynamoDB вирішує цю проблему через ",[3363,14334,14335],{},"Secondary Indexes"," — механізм, що дозволяє визначити альтернативну схему ключів для таблиці та виконувати Query за цією альтернативною схемою. Існує два типи Secondary Indexes з принципово різними характеристиками.",[3353,14338,14339,14340,14342,14343,14345,14346,14348],{},"Для наочності розглянемо поточний стан основної таблиці ",[3413,14341,10457],{}," (з первинним ключем ",[3413,14344,4494],{}," + ",[3413,14347,8903],{},"), на прикладі якої ми будемо вивчати обидва типи індексів:",[3353,14350,14351],{},[3363,14352,14353,14354,10458],{},"Вихідний набір даних таблиці ",[3413,14355,10457],{},[3756,14357,14358,14379],{},[4617,14359,14360],{},[4620,14361,14362,14365,14368,14371,14374,14376],{},[4623,14363,14364],{"align":4625},"UserId (Partition Key)",[4623,14366,14367],{"align":4625},"SessionId (Sort Key)",[4623,14369,14370],{"align":4625},"ExpiresAt",[4623,14372,14373],{"align":4625},"IpAddress",[4623,14375,4518],{"align":4625},[4623,14377,14378],{"align":4625},"CreatedAt",[4657,14380,14381,14411,14441,14470],{},[4620,14382,14383,14387,14392,14397,14402,14406],{},[4662,14384,14385],{"align":4625},[3413,14386,4666],{},[4662,14388,14389],{"align":4625},[3413,14390,14391],{},"sess-A",[4662,14393,14394],{"align":4625},[3413,14395,14396],{},"2025-06-01T22:00:00Z",[4662,14398,14399],{"align":4625},[3413,14400,14401],{},"203.0.113.42",[4662,14403,14404],{"align":4625},[3413,14405,4038],{},[4662,14407,14408],{"align":4625},[3413,14409,14410],{},"2025-06-01T10:00:00Z",[4620,14412,14413,14417,14422,14427,14432,14436],{},[4662,14414,14415],{"align":4625},[3413,14416,4666],{},[4662,14418,14419],{"align":4625},[3413,14420,14421],{},"sess-B",[4662,14423,14424],{"align":4625},[3413,14425,14426],{},"2025-06-02T10:00:00Z",[4662,14428,14429],{"align":4625},[3413,14430,14431],{},"198.51.100.7",[4662,14433,14434],{"align":4625},[3413,14435,4038],{},[4662,14437,14438],{"align":4625},[3413,14439,14440],{},"2025-06-01T11:00:00Z",[4620,14442,14443,14447,14452,14457,14461,14465],{},[4662,14444,14445],{"align":4625},[3413,14446,4666],{},[4662,14448,14449],{"align":4625},[3413,14450,14451],{},"sess-C",[4662,14453,14454],{"align":4625},[3413,14455,14456],{},"2025-05-31T08:00:00Z",[4662,14458,14459],{"align":4625},[3413,14460,14401],{},[4662,14462,14463],{"align":4625},[3413,14464,4042],{},[4662,14466,14467],{"align":4625},[3413,14468,14469],{},"2025-05-30T16:00:00Z",[4620,14471,14472,14476,14481,14486,14491,14495],{},[4662,14473,14474],{"align":4625},[3413,14475,4685],{},[4662,14477,14478],{"align":4625},[3413,14479,14480],{},"sess-D",[4662,14482,14483],{"align":4625},[3413,14484,14485],{},"2025-06-03T14:00:00Z",[4662,14487,14488],{"align":4625},[3413,14489,14490],{},"10.0.0.5",[4662,14492,14493],{"align":4625},[3413,14494,4038],{},[4662,14496,14497],{"align":4625},[3413,14498,14499],{},"2025-06-01T13:00:00Z",[3720,14501],{},[3403,14503,14504],{},[3406,14505,14507],{"className":3408,"code":14506,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"Secondary Indexes: два типи з різними обмеженнями\"\n\npackage \"Таблиця: UserSessions\" as MAIN #fef3c7 {\n    note as MAIN_NOTE\n      PK: UserId (S)\n      SK: SessionId (S)\n      ──────────────────\n      ExpiresAt: String\n      IpAddress: String\n      IsActive: Boolean\n      CreatedAt: String\n    end note\n}\n\npackage \"LSI: SessionsByExpiry\" as LSI #dbeafe {\n    note as LSI_NOTE\n      PK: UserId (S) ← той самий!\n      SK: ExpiresAt (S) ← новий!\n      ──────────────────\n      ProjectionType: ALL\n      ──────────────────\n      Обмеження:\n      - Той самий PK що й таблиця\n      - Тільки при создані таблиці\n      - Max 5 LSI на таблицю\n      - 10 GB ліміт на партицію\n    end note\n}\n\npackage \"GSI: SessionsByIp\" as GSI #d1fae5 {\n    note as GSI_NOTE\n      PK: IpAddress (S) ← будь-який атрибут!\n      SK: CreatedAt (S) ← будь-який атрибут!\n      ──────────────────\n      ProjectionType: KEYS_ONLY\n      ──────────────────\n      Обмеження:\n      - Окрема пропускна здатність\n      - Eventual consistency лише\n      - Додається в будь-який момент\n      - Max 20 GSI на таблицю\n    end note\n}\n\nMAIN -right-> LSI : \"автоматично синхронізується\"\nMAIN -down-> GSI  : \"автоматично синхронізується\"\n\n@enduml\n",[3413,14508,14509,14513,14517,14521,14525,14530,14534,14539,14544,14549,14554,14559,14564,14569,14574,14579,14583,14587,14591,14596,14601,14606,14611,14615,14620,14624,14629,14634,14639,14644,14649,14653,14657,14661,14666,14671,14676,14681,14685,14690,14694,14698,14703,14708,14713,14718,14722,14726,14730,14735,14740,14744],{"__ignoreMap":3411},[3416,14510,14511],{"class":3418,"line":3419},[3416,14512,3422],{},[3416,14514,14515],{"class":3418,"line":3425},[3416,14516,3428],{},[3416,14518,14519],{"class":3418,"line":3431},[3416,14520,3434],{},[3416,14522,14523],{"class":3418,"line":3437},[3416,14524,3441],{"emptyLinePlaceholder":3440},[3416,14526,14527],{"class":3418,"line":3444},[3416,14528,14529],{},"title \"Secondary Indexes: два типи з різними обмеженнями\"\n",[3416,14531,14532],{"class":3418,"line":3450},[3416,14533,3441],{"emptyLinePlaceholder":3440},[3416,14535,14536],{"class":3418,"line":3456},[3416,14537,14538],{},"package \"Таблиця: UserSessions\" as MAIN #fef3c7 {\n",[3416,14540,14541],{"class":3418,"line":3462},[3416,14542,14543],{},"    note as MAIN_NOTE\n",[3416,14545,14546],{"class":3418,"line":3468},[3416,14547,14548],{},"      PK: UserId (S)\n",[3416,14550,14551],{"class":3418,"line":3474},[3416,14552,14553],{},"      SK: SessionId (S)\n",[3416,14555,14556],{"class":3418,"line":3480},[3416,14557,14558],{},"      ──────────────────\n",[3416,14560,14561],{"class":3418,"line":3486},[3416,14562,14563],{},"      ExpiresAt: String\n",[3416,14565,14566],{"class":3418,"line":3492},[3416,14567,14568],{},"      IpAddress: String\n",[3416,14570,14571],{"class":3418,"line":3498},[3416,14572,14573],{},"      IsActive: Boolean\n",[3416,14575,14576],{"class":3418,"line":3504},[3416,14577,14578],{},"      CreatedAt: String\n",[3416,14580,14581],{"class":3418,"line":3510},[3416,14582,3501],{},[3416,14584,14585],{"class":3418,"line":3515},[3416,14586,3507],{},[3416,14588,14589],{"class":3418,"line":3521},[3416,14590,3441],{"emptyLinePlaceholder":3440},[3416,14592,14593],{"class":3418,"line":3527},[3416,14594,14595],{},"package \"LSI: SessionsByExpiry\" as LSI #dbeafe {\n",[3416,14597,14598],{"class":3418,"line":3533},[3416,14599,14600],{},"    note as LSI_NOTE\n",[3416,14602,14603],{"class":3418,"line":3539},[3416,14604,14605],{},"      PK: UserId (S) ← той самий!\n",[3416,14607,14608],{"class":3418,"line":3545},[3416,14609,14610],{},"      SK: ExpiresAt (S) ← новий!\n",[3416,14612,14613],{"class":3418,"line":3551},[3416,14614,14558],{},[3416,14616,14617],{"class":3418,"line":3557},[3416,14618,14619],{},"      ProjectionType: ALL\n",[3416,14621,14622],{"class":3418,"line":3563},[3416,14623,14558],{},[3416,14625,14626],{"class":3418,"line":3569},[3416,14627,14628],{},"      Обмеження:\n",[3416,14630,14631],{"class":3418,"line":3574},[3416,14632,14633],{},"      - Той самий PK що й таблиця\n",[3416,14635,14636],{"class":3418,"line":3579},[3416,14637,14638],{},"      - Тільки при создані таблиці\n",[3416,14640,14641],{"class":3418,"line":3584},[3416,14642,14643],{},"      - Max 5 LSI на таблицю\n",[3416,14645,14646],{"class":3418,"line":3590},[3416,14647,14648],{},"      - 10 GB ліміт на партицію\n",[3416,14650,14651],{"class":3418,"line":3596},[3416,14652,3501],{},[3416,14654,14655],{"class":3418,"line":3602},[3416,14656,3507],{},[3416,14658,14659],{"class":3418,"line":3608},[3416,14660,3441],{"emptyLinePlaceholder":3440},[3416,14662,14663],{"class":3418,"line":3614},[3416,14664,14665],{},"package \"GSI: SessionsByIp\" as GSI #d1fae5 {\n",[3416,14667,14668],{"class":3418,"line":3620},[3416,14669,14670],{},"    note as GSI_NOTE\n",[3416,14672,14673],{"class":3418,"line":3626},[3416,14674,14675],{},"      PK: IpAddress (S) ← будь-який атрибут!\n",[3416,14677,14678],{"class":3418,"line":3631},[3416,14679,14680],{},"      SK: CreatedAt (S) ← будь-який атрибут!\n",[3416,14682,14683],{"class":3418,"line":3636},[3416,14684,14558],{},[3416,14686,14687],{"class":3418,"line":3641},[3416,14688,14689],{},"      ProjectionType: KEYS_ONLY\n",[3416,14691,14692],{"class":3418,"line":3647},[3416,14693,14558],{},[3416,14695,14696],{"class":3418,"line":3653},[3416,14697,14628],{},[3416,14699,14700],{"class":3418,"line":3659},[3416,14701,14702],{},"      - Окрема пропускна здатність\n",[3416,14704,14705],{"class":3418,"line":3665},[3416,14706,14707],{},"      - Eventual consistency лише\n",[3416,14709,14710],{"class":3418,"line":3671},[3416,14711,14712],{},"      - Додається в будь-який момент\n",[3416,14714,14715],{"class":3418,"line":3677},[3416,14716,14717],{},"      - Max 20 GSI на таблицю\n",[3416,14719,14720],{"class":3418,"line":3683},[3416,14721,3501],{},[3416,14723,14724],{"class":3418,"line":3688},[3416,14725,3507],{},[3416,14727,14728],{"class":3418,"line":3693},[3416,14729,3441],{"emptyLinePlaceholder":3440},[3416,14731,14732],{"class":3418,"line":3698},[3416,14733,14734],{},"MAIN -right-> LSI : \"автоматично синхронізується\"\n",[3416,14736,14737],{"class":3418,"line":3704},[3416,14738,14739],{},"MAIN -down-> GSI  : \"автоматично синхронізується\"\n",[3416,14741,14742],{"class":3418,"line":3710},[3416,14743,3441],{"emptyLinePlaceholder":3440},[3416,14745,14746],{"class":3418,"line":3715},[3416,14747,3718],{},[3720,14749],{},[3348,14751,14753],{"id":14752},"local-secondary-index-lsi","Local Secondary Index (LSI)",[3353,14755,14756,14758,14759,14762],{},[3363,14757,14753],{}," представляє собою альтернативний індекс доступу, який створюється в межах однієї логічної партиції. Ключовою архітектурною особливістю LSI є те, що він ",[3363,14760,14761],{},"зобов'язаний використовувати той самий Partition Key (HASH)",", що й основна таблиця, але дозволяє визначити інший атрибут як Sort Key (RANGE).",[3353,14764,14765],{},"Термін «локальний» вказує на фізичну локалізацію даних: всі проектовані елементи індексу, що відповідають певному Partition Key, зберігаються на тому самому фізичному вузлі (storage node) і в межах тієї ж групи партицій, що й відповідні оригінальні елементи основної таблиці. Це забезпечує сувору гарантію транзакційної узгодженості та мінімальних затримок при зверненні.",[3727,14767,14769],{"id":14768},"архітектурна-доцільність-та-патерни-застосування-lsi","Архітектурна доцільність та патерни застосування LSI",[3353,14771,14772],{},"Необхідність використання LSI виникає у сценаріях, коли для однієї сутності (ідентифікованої за Partition Key) потрібно виконувати складні запити з різними критеріями сортування або фільтрації.",[3353,14774,14775,14776,14778,14779,14781,14782,14784,14785,14787,14788,13590],{},"Розглянемо практичний сценарій проектування таблиці сесій користувачів ",[3413,14777,10457],{},", де первинний ключ побудований як composite: Partition Key = ",[3413,14780,4494],{},", Sort Key = ",[3413,14783,8903],{},". Ця схема дозволяє виконувати ефективні операції точкового читання (",[3413,14786,4873],{},") конкретної сесії або отримувати перелік усіх сесій користувача (",[3413,14789,4887],{},[3353,14791,14792,14793,14796,14797,4874,14799,14801,14802,14804,14805,14808],{},"Проте, якщо виникає патерн доступу виду ",[4091,14794,14795],{},"«отримати всі сесії конкретного користувача, термін дії яких закінчується до заданого моменту»"," (наприклад, для інвалідації сесій або виведення попереджень користувачу), стандартна схема вимагатиме виконання запиту ",[3413,14798,4887],{},[3413,14800,4494],{}," з подальшою фільтрацією за полем ",[3413,14803,14370],{}," на стороні додатка або через ",[3413,14806,14807],{},"FilterExpression",". Це призведе до зайвого споживання RCU, оскільки DynamoDB зчитує всі сесії користувача, перш ніж застосувати фільтр.",[3353,14810,14811,14812,14815,14816,14818,14819,14821,14822,14824,14825,14827],{},"Створення LSI з назвою ",[3413,14813,14814],{},"SessionsByExpiry",", де Sort Key визначено як ",[3413,14817,14370],{},", дозволяє виконувати прямі сортувальні запити (",[3413,14820,4887],{},") в межах одного ",[3413,14823,4494],{}," з накладанням умов на ",[3413,14826,14370],{}," безпосередньо на рівні бази даних.",[3403,14829,14830],{},[3406,14831,14833],{"className":3408,"code":14832,"language":3410,"meta":3411,"style":3411},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\ntitle \"LSI SessionsByExpiry: Query за ExpiresAt в межах UserId\"\n\npackage \"Основна таблиця: UserSessions\" as MAIN #fef3c7 {\n    card \"PK:usr-001 | SK:sess-A\\nExpiresAt: 2025-06-01T22:00\\nIsActive: true\" as I1 #bbf7d0\n    card \"PK:usr-001 | SK:sess-B\\nExpiresAt: 2025-06-02T10:00\\nIsActive: true\" as I2 #bbf7d0\n    card \"PK:usr-001 | SK:sess-C\\nExpiresAt: 2025-05-31T08:00\\nIsActive: false\" as I3 #fde68a\n    card \"PK:usr-002 | SK:sess-D\\nExpiresAt: 2025-06-03T14:00\\nIsActive: true\" as I4 #bbf7d0\n}\n\npackage \"LSI: SessionsByExpiry\" as LSI #dbeafe {\n    note as LSI_NOTE\n      PK: UserId (той самий!)\n      SK: ExpiresAt (новий!)\n      ─────────────────────────────\n      usr-001 | 2025-05-31T08:00 → sess-C\n      usr-001 | 2025-06-01T22:00 → sess-A\n      usr-001 | 2025-06-02T10:00 → sess-B\n      usr-002 | 2025-06-03T14:00 → sess-D\n      ─────────────────────────────\n      Відсортовано по ExpiresAt\n      всередині кожного UserId!\n    end note\n}\n\nMAIN -right-> LSI : \"автоматична реплікація\"\n\nnote bottom of LSI\n  Query: UserId=\"usr-001\" AND ExpiresAt \u003C \"2025-06-02T00:00\"\n  → повертає: sess-C (вже протермінована), sess-A (закінчується сьогодні)\n  → БЕЗ сканування sess-B, sess-D\nend note\n\n@enduml\n",[3413,14834,14835,14839,14843,14847,14851,14856,14860,14865,14870,14875,14880,14885,14889,14893,14897,14901,14906,14911,14916,14921,14926,14931,14936,14940,14945,14950,14954,14958,14962,14967,14971,14976,14981,14986,14991,14995,14999],{"__ignoreMap":3411},[3416,14836,14837],{"class":3418,"line":3419},[3416,14838,3422],{},[3416,14840,14841],{"class":3418,"line":3425},[3416,14842,3428],{},[3416,14844,14845],{"class":3418,"line":3431},[3416,14846,3434],{},[3416,14848,14849],{"class":3418,"line":3437},[3416,14850,3441],{"emptyLinePlaceholder":3440},[3416,14852,14853],{"class":3418,"line":3444},[3416,14854,14855],{},"title \"LSI SessionsByExpiry: Query за ExpiresAt в межах UserId\"\n",[3416,14857,14858],{"class":3418,"line":3450},[3416,14859,3441],{"emptyLinePlaceholder":3440},[3416,14861,14862],{"class":3418,"line":3456},[3416,14863,14864],{},"package \"Основна таблиця: UserSessions\" as MAIN #fef3c7 {\n",[3416,14866,14867],{"class":3418,"line":3462},[3416,14868,14869],{},"    card \"PK:usr-001 | SK:sess-A\\nExpiresAt: 2025-06-01T22:00\\nIsActive: true\" as I1 #bbf7d0\n",[3416,14871,14872],{"class":3418,"line":3468},[3416,14873,14874],{},"    card \"PK:usr-001 | SK:sess-B\\nExpiresAt: 2025-06-02T10:00\\nIsActive: true\" as I2 #bbf7d0\n",[3416,14876,14877],{"class":3418,"line":3474},[3416,14878,14879],{},"    card \"PK:usr-001 | SK:sess-C\\nExpiresAt: 2025-05-31T08:00\\nIsActive: false\" as I3 #fde68a\n",[3416,14881,14882],{"class":3418,"line":3480},[3416,14883,14884],{},"    card \"PK:usr-002 | SK:sess-D\\nExpiresAt: 2025-06-03T14:00\\nIsActive: true\" as I4 #bbf7d0\n",[3416,14886,14887],{"class":3418,"line":3486},[3416,14888,3507],{},[3416,14890,14891],{"class":3418,"line":3492},[3416,14892,3441],{"emptyLinePlaceholder":3440},[3416,14894,14895],{"class":3418,"line":3498},[3416,14896,14595],{},[3416,14898,14899],{"class":3418,"line":3504},[3416,14900,14600],{},[3416,14902,14903],{"class":3418,"line":3510},[3416,14904,14905],{},"      PK: UserId (той самий!)\n",[3416,14907,14908],{"class":3418,"line":3515},[3416,14909,14910],{},"      SK: ExpiresAt (новий!)\n",[3416,14912,14913],{"class":3418,"line":3521},[3416,14914,14915],{},"      ─────────────────────────────\n",[3416,14917,14918],{"class":3418,"line":3527},[3416,14919,14920],{},"      usr-001 | 2025-05-31T08:00 → sess-C\n",[3416,14922,14923],{"class":3418,"line":3533},[3416,14924,14925],{},"      usr-001 | 2025-06-01T22:00 → sess-A\n",[3416,14927,14928],{"class":3418,"line":3539},[3416,14929,14930],{},"      usr-001 | 2025-06-02T10:00 → sess-B\n",[3416,14932,14933],{"class":3418,"line":3545},[3416,14934,14935],{},"      usr-002 | 2025-06-03T14:00 → sess-D\n",[3416,14937,14938],{"class":3418,"line":3551},[3416,14939,14915],{},[3416,14941,14942],{"class":3418,"line":3557},[3416,14943,14944],{},"      Відсортовано по ExpiresAt\n",[3416,14946,14947],{"class":3418,"line":3563},[3416,14948,14949],{},"      всередині кожного UserId!\n",[3416,14951,14952],{"class":3418,"line":3569},[3416,14953,3501],{},[3416,14955,14956],{"class":3418,"line":3574},[3416,14957,3507],{},[3416,14959,14960],{"class":3418,"line":3579},[3416,14961,3441],{"emptyLinePlaceholder":3440},[3416,14963,14964],{"class":3418,"line":3584},[3416,14965,14966],{},"MAIN -right-> LSI : \"автоматична реплікація\"\n",[3416,14968,14969],{"class":3418,"line":3590},[3416,14970,3441],{"emptyLinePlaceholder":3440},[3416,14972,14973],{"class":3418,"line":3596},[3416,14974,14975],{},"note bottom of LSI\n",[3416,14977,14978],{"class":3418,"line":3602},[3416,14979,14980],{},"  Query: UserId=\"usr-001\" AND ExpiresAt \u003C \"2025-06-02T00:00\"\n",[3416,14982,14983],{"class":3418,"line":3608},[3416,14984,14985],{},"  → повертає: sess-C (вже протермінована), sess-A (закінчується сьогодні)\n",[3416,14987,14988],{"class":3418,"line":3614},[3416,14989,14990],{},"  → БЕЗ сканування sess-B, sess-D\n",[3416,14992,14993],{"class":3418,"line":3620},[3416,14994,5088],{},[3416,14996,14997],{"class":3418,"line":3626},[3416,14998,3441],{"emptyLinePlaceholder":3440},[3416,15000,15001],{"class":3418,"line":3631},[3416,15002,3718],{},[3727,15004,15006],{"id":15005},"системні-обмеження-та-архітектурні-компроміси-lsi","Системні обмеження та архітектурні компроміси LSI",[3353,15008,15009],{},"Хоча LSI надає перевагу у вигляді сильної узгодженості та атомарності, його використання супроводжується жорсткими обмеженнями, які необхідно враховувати на етапі проектування.",[4584,15011,15013],{"id":15012},"_1-обмеження-розміру-колекції-елементів-10-gb-item-collection-limit","1. Обмеження розміру колекції елементів (10 GB Item Collection Limit)",[3353,15015,15016,15017,15020],{},"Найбільш критичним обмеженням LSI є ліміт на розмір ",[3363,15018,15019],{},"колекції елементів (Item Collection)",". Колекція елементів — це сукупність усіх елементів у таблиці та в усіх її локальних вторинних індексах, які мають однакове значення Partition Key.",[3353,15022,15023,15024,15027,15028,4043],{},"Фізично, для забезпечення низьких затримок, DynamoDB зберігає всю колекцію елементів на одному фізичному вузлі партиції. Через це сумарний розмір колекції елементів для одного значення Partition Key не може перевищувати ",[3363,15025,15026],{},"10 GB",". Якщо обсяг даних одного ключа (наприклад, сесій одного активного користувача) перевищить цей ліміт, будь-які подальші операції запису або оновлення для цього Partition Key завершаться помилкою ",[3413,15029,15030],{},"ValidationException",[3353,15032,15033,15036],{},[4091,15034,15035],{},"Практичний висновок:"," LSI абсолютно не підходить для сутностей з необмеженим зростанням даних (наприклад, логування подій IoT-пристроїв за ідентифікатором пристрою, де обсяг логів на один пристрій гарантовано перевищить 10 GB).",[4584,15038,15040],{"id":15039},"_2-неможливість-динамічного-керування","2. Неможливість динамічного керування",[3353,15042,15043,15044,11431,15047,15050],{},"Локальний вторинний індекс може бути створений ",[3363,15045,15046],{},"виключно в момент ініціалізації таблиці",[3413,15048,15049],{},"CreateTable","). Додати LSI до існуючої таблиці або видалити його пізніше неможливо. Якщо в процесі експлуатації виявиться потреба в новому LSI, єдиним виходом буде створення нової таблиці, налаштування нової схеми індексів та міграція всіх історичних даних, що є тривалим та дорогим процесом.",[3720,15052],{},[3727,15054,15056],{"id":15055},"стратегії-проектування-індексів-типи-проекцій-projection-types","Стратегії проектування індексів: Типи проекцій (Projection Types)",[3353,15058,15059,15060,15063],{},"При створенні вторинного індексу розробник повинен визначити, які саме атрибути з основної таблиці будуть копіюватися (проектувалися) в індекс. Це визначається параметром ",[3363,15061,15062],{},"Projection",". Вибір типу проекції є компромісом між обсягом збережених даних (витрати на Storage та WCU) та продуктивністю запитів (витрати на RCU).",[4001,15065,15066,15079,15100],{},[4004,15067,15070,15073],{"icon":15068,"title":15069},"i-heroicons-key","KEYS_ONLY",[3353,15071,15072],{},"Індекс зберігає лише ключові атрибути: PK та SK основної таблиці + PK та SK індексу. Мінімальний розмір → мінімальні витрати. Якщо потрібні інші атрибути — DynamoDB автоматично виконує додаткове читання основної таблиці.",[3353,15074,15075,15078],{},[3363,15076,15077],{},"Коли:"," часто використовується як «існування» (перевірити чи є такий запис), або якщо майже завжди потрібно також читати основну таблицю для деталей.",[4004,15080,15083,15090],{"icon":15081,"title":15082},"i-heroicons-list-bullet","INCLUDE",[3353,15084,15085,15086,15089],{},"Зберігає ключові атрибути + явно вказаний список атрибутів (",[3413,15087,15088],{},"NonKeyAttributes","). Дозволяє точно контролювати, які поля дублюються в індексі.",[3353,15091,15092,15094,15095,14345,15097,15099],{},[3363,15093,15077],{}," коли відомий фіксований набір атрибутів, що потрібні при Query через індекс. Наприклад, ",[3413,15096,14370],{},[3413,15098,4518],{}," — достатньо для перевірки статусу сесії без читання повного елемента.",[4004,15101,15104,15107],{"icon":15102,"title":15103},"i-heroicons-square-3-stack-3d","ALL",[3353,15105,15106],{},"Зберігає всі атрибути елемента. Максимальний розмір індексу — фактично дублювання всієї таблиці. Але Query через індекс повертає повний елемент без додаткових читань.",[3353,15108,15109,15111],{},[3363,15110,15077],{}," якщо при Query через індекс завжди потрібні всі атрибути, і витрати на зберігання прийнятні.",[8456,15113,15114,15117,15118,4039,15120,15122,15123,15125],{},[3363,15115,15116],{},"Практичне правило для Projection:"," починайте з ",[3413,15119,15069],{},[3413,15121,15082],{}," (мінімально необхідний набір атрибутів для вашого Query). ",[3413,15124,15103],{}," зручний, але подвоює або потроює витрати на зберігання. DynamoDB не дозволяє змінити Projection після створення індексу — треба перестворювати.",[3727,15127,15129],{"id":15128},"вплив-lsi-на-споживання-rcu-та-wcu","Вплив LSI на споживання RCU та WCU",[3353,15131,15132],{},"Використання локальних індексів суттєво оновлює можливості запитів, проте створює додаткове навантаження на пропускну здатність таблиці:",[3374,15134,15135,15177],{},[3377,15136,15137,15140,15141,15143,15144,15146,15147,15149,15150,15172,15174],{},[3363,15138,15139],{},"Витрати на запис (Write Cost Dynamics):","\nПри додаванні (",[3413,15142,6619],{},"), оновленні (",[3413,15145,6964],{},") або видаленні (",[3413,15148,7408],{},") елемента в основній таблиці DynamoDB автоматично оновлює дані у всіх LSI.",[4488,15151,15152,15155,15165],{},[3377,15153,15154],{},"Якщо записується новий елемент, споживається 1 WCU (або 2 WCU для транзакцій) за кожен 1 KB розміру елемента як для основної таблиці, так і для кожного LSI, куди проектується цей елемент.",[3377,15156,15157,15158,15161,15162,4043],{},"Якщо оновлюється атрибут елемента, який ",[3363,15159,15160],{},"не входить"," у проекцію LSI, додаткові WCU для цього індексу ",[3363,15163,15164],{},"не споживаються",[3377,15166,15167,15168,15171],{},"Якщо оновлюється атрибут, що ",[3363,15169,15170],{},"входить"," до проекції індексу (або змінюється сам ключ індексу Sort Key), DynamoDB виконує дві операції в індексі (видалення старого запису та запис нового), що споживає додаткові WCU.",[4628,15173],{},[4091,15175,15176],{},"Усі витрати WCU на обслуговування LSI списуються з пулу пропускної здатності основної таблиці.",[3377,15178,15179,15182,15183,15185,15186,15219,15221,15224,15225,15228,15229,15231,15234],{},[3363,15180,15181],{},"Витрати на читання та явище Main Table Fetch (Read Cost Dynamics):","\nПри виконанні запиту ",[3413,15184,4887],{}," через LSI вартість у RCU залежить від вибраного типу проекції:",[4488,15187,15188,15199],{},[3377,15189,15190,15193,15194,4039,15196,15198],{},[3363,15191,15192],{},"Покритий запит (Covered Query):"," Якщо запит запитує лише ті атрибути, які були спроектовані в індекс (",[3413,15195,15069],{},[3413,15197,15082],{},"), DynamoDB зчитує дані виключно з LSI. Розрахунок RCU відбувається стандартно: 1 RCU на 4 KB спроектованих даних (Strongly Consistent).",[3377,15200,15201,15204,15205,15208,15209,15211,15212,15214,15215,15218],{},[3363,15202,15203],{},"Непокритий запит та Main Table Fetch:"," Якщо запит звертається до атрибутів, які ",[3363,15206,15207],{},"відсутні"," в проекції індексу (наприклад, у проекції ",[3413,15210,15069],{}," запитується поле ",[3413,15213,14373],{},"), DynamoDB змушена виконати внутрішню операцію вибірки з основної таблиці (",[3363,15216,15217],{},"Main Table Fetch \u002F Lookup",") для кожного знайденого елемента.",[4628,15220],{},[3363,15222,15223],{},"Штраф за Fetch:"," Кожна така вибірка з основної таблиці виконується як окреме Strongly Consistent читання і споживає ",[3363,15226,15227],{},"щонайменше 1 RCU на кожен елемент"," (навіть якщо розмір елемента менший за 4 KB) та додає затримку (latency) на мережеве коло всередині бази даних.",[4628,15230],{},[4091,15232,15233],{},"Формула розрахунку RCU для непокритого запиту:",[13667,15235,15236,15237,15240],{},"\\text{RCU}",[4091,15238,15239],{},"{\\text{Total}} = \\text{RCU}","{\\text{Index Query}} + \\text{Кількість знайдених елементів} \\times 1\\text{ RCU}",[3720,15242],{},[3727,15244,15246],{"id":15245},"створення-таблиці-з-lsi","Створення таблиці з LSI",[6308,15248,15249,15401,15858],{},[6311,15250,15251],{"label":6313},[3406,15252,15254],{"className":6316,"code":15253,"language":6318,"meta":3411,"style":3411},"# Таблиця UserSessions з LSI SessionsByExpiry\naws dynamodb create-table \\\n    --table-name UserSessions \\\n    --attribute-definitions \\\n        AttributeName=UserId,AttributeType=S \\\n        AttributeName=SessionId,AttributeType=S \\\n        AttributeName=ExpiresAt,AttributeType=S \\\n    --key-schema \\\n        AttributeName=UserId,KeyType=HASH \\\n        AttributeName=SessionId,KeyType=RANGE \\\n    --local-secondary-indexes '[\n        {\n            \"IndexName\": \"SessionsByExpiry\",\n            \"KeySchema\": [\n                {\"AttributeName\": \"UserId\",    \"KeyType\": \"HASH\"},\n                {\"AttributeName\": \"ExpiresAt\", \"KeyType\": \"RANGE\"}\n            ],\n            \"Projection\": {\n                \"ProjectionType\": \"INCLUDE\",\n                \"NonKeyAttributes\": [\"IsActive\", \"IpAddress\"]\n            }\n        }\n    ]' \\\n    --billing-mode PAY_PER_REQUEST \\\n    --region eu-central-1\n",[3413,15255,15256,15261,15271,15279,15285,15291,15297,15304,15310,15316,15322,15329,15333,15338,15343,15348,15353,15358,15363,15368,15373,15377,15381,15387,15395],{"__ignoreMap":3411},[3416,15257,15258],{"class":3418,"line":3419},[3416,15259,15260],{"class":3789},"# Таблиця UserSessions з LSI SessionsByExpiry\n",[3416,15262,15263,15265,15267,15269],{"class":3418,"line":3425},[3416,15264,6331],{"class":6330},[3416,15266,6334],{"class":3808},[3416,15268,10696],{"class":3808},[3416,15270,6341],{"class":6340},[3416,15272,15273,15275,15277],{"class":3418,"line":3431},[3416,15274,6346],{"class":4368},[3416,15276,6349],{"class":3808},[3416,15278,6341],{"class":6340},[3416,15280,15281,15283],{"class":3418,"line":3437},[3416,15282,10711],{"class":4368},[3416,15284,6341],{"class":6340},[3416,15286,15287,15289],{"class":3418,"line":3444},[3416,15288,10718],{"class":3808},[3416,15290,6341],{"class":6340},[3416,15292,15293,15295],{"class":3418,"line":3450},[3416,15294,10725],{"class":3808},[3416,15296,6341],{"class":6340},[3416,15298,15299,15302],{"class":3418,"line":3456},[3416,15300,15301],{"class":3808},"        AttributeName=ExpiresAt,AttributeType=S",[3416,15303,6341],{"class":6340},[3416,15305,15306,15308],{"class":3418,"line":3462},[3416,15307,10732],{"class":4368},[3416,15309,6341],{"class":6340},[3416,15311,15312,15314],{"class":3418,"line":3468},[3416,15313,10739],{"class":3808},[3416,15315,6341],{"class":6340},[3416,15317,15318,15320],{"class":3418,"line":3474},[3416,15319,10746],{"class":3808},[3416,15321,6341],{"class":6340},[3416,15323,15324,15327],{"class":3418,"line":3480},[3416,15325,15326],{"class":4368},"    --local-secondary-indexes",[3416,15328,9727],{"class":3808},[3416,15330,15331],{"class":3418,"line":3486},[3416,15332,8611],{"class":3808},[3416,15334,15335],{"class":3418,"line":3492},[3416,15336,15337],{"class":3808},"            \"IndexName\": \"SessionsByExpiry\",\n",[3416,15339,15340],{"class":3418,"line":3498},[3416,15341,15342],{"class":3808},"            \"KeySchema\": [\n",[3416,15344,15345],{"class":3418,"line":3504},[3416,15346,15347],{"class":3808},"                {\"AttributeName\": \"UserId\",    \"KeyType\": \"HASH\"},\n",[3416,15349,15350],{"class":3418,"line":3510},[3416,15351,15352],{"class":3808},"                {\"AttributeName\": \"ExpiresAt\", \"KeyType\": \"RANGE\"}\n",[3416,15354,15355],{"class":3418,"line":3515},[3416,15356,15357],{"class":3808},"            ],\n",[3416,15359,15360],{"class":3418,"line":3521},[3416,15361,15362],{"class":3808},"            \"Projection\": {\n",[3416,15364,15365],{"class":3418,"line":3527},[3416,15366,15367],{"class":3808},"                \"ProjectionType\": \"INCLUDE\",\n",[3416,15369,15370],{"class":3418,"line":3533},[3416,15371,15372],{"class":3808},"                \"NonKeyAttributes\": [\"IsActive\", \"IpAddress\"]\n",[3416,15374,15375],{"class":3418,"line":3539},[3416,15376,8815],{"class":3808},[3416,15378,15379],{"class":3418,"line":3545},[3416,15380,8533],{"class":3808},[3416,15382,15383,15385],{"class":3418,"line":3551},[3416,15384,9816],{"class":3808},[3416,15386,6341],{"class":6340},[3416,15388,15389,15391,15393],{"class":3418,"line":3557},[3416,15390,10753],{"class":4368},[3416,15392,10756],{"class":3808},[3416,15394,6341],{"class":6340},[3416,15396,15397,15399],{"class":3418,"line":3563},[3416,15398,6366],{"class":4368},[3416,15400,6369],{"class":3808},[6311,15402,15403],{"label":6372},[3406,15404,15406],{"className":6375,"code":15405,"language":6377,"meta":3411,"style":3411},"var client = new AmazonDynamoDBClient();\nvar response = await client.CreateTableAsync(new CreateTableRequest\n{\n    TableName = \"UserSessions\",\n    AttributeDefinitions = new List\u003CAttributeDefinition>\n    {\n        new AttributeDefinition { AttributeName = \"UserId\", AttributeType = ScalarAttributeType.S },\n        new AttributeDefinition { AttributeName = \"SessionId\", AttributeType = ScalarAttributeType.S },\n        new AttributeDefinition { AttributeName = \"ExpiresAt\", AttributeType = ScalarAttributeType.S }\n    },\n    KeySchema = new List\u003CKeySchemaElement>\n    {\n        new KeySchemaElement { AttributeName = \"UserId\", KeyType = KeyType.HASH },\n        new KeySchemaElement { AttributeName = \"SessionId\", KeyType = KeyType.RANGE }\n    },\n    LocalSecondaryIndexes = new List\u003CLocalSecondaryIndex>\n    {\n        new LocalSecondaryIndex\n        {\n            IndexName = \"SessionsByExpiry\",\n            KeySchema = new List\u003CKeySchemaElement>\n            {\n                new KeySchemaElement { AttributeName = \"UserId\", KeyType = KeyType.HASH },\n                new KeySchemaElement { AttributeName = \"ExpiresAt\", KeyType = KeyType.RANGE }\n            },\n            Projection = new Projection\n            {\n                ProjectionType = ProjectionType.INCLUDE,\n                NonKeyAttributes = new List\u003Cstring> { \"IsActive\", \"IpAddress\" }\n            }\n        }\n    },\n    BillingMode = BillingMode.PAY_PER_REQUEST\n});\n",[3413,15407,15408,15422,15444,15448,15458,15474,15478,15506,15534,15562,15566,15582,15586,15614,15642,15646,15664,15668,15675,15679,15691,15708,15712,15740,15768,15772,15784,15788,15804,15830,15834,15838,15842,15854],{"__ignoreMap":3411},[3416,15409,15410,15412,15414,15416,15418,15420],{"class":3418,"line":3419},[3416,15411,6384],{"class":4368},[3416,15413,6388],{"class":6387},[3416,15415,6391],{"class":3795},[3416,15417,6394],{"class":4368},[3416,15419,6398],{"class":6397},[3416,15421,6401],{"class":3795},[3416,15423,15424,15426,15428,15430,15432,15434,15436,15438,15440,15442],{"class":3418,"line":3425},[3416,15425,6384],{"class":4368},[3416,15427,6408],{"class":6387},[3416,15429,6391],{"class":3795},[3416,15431,6413],{"class":4368},[3416,15433,6388],{"class":6387},[3416,15435,4043],{"class":3795},[3416,15437,10802],{"class":6330},[3416,15439,6423],{"class":3795},[3416,15441,6394],{"class":4368},[3416,15443,10809],{"class":6397},[3416,15445,15446],{"class":3418,"line":3431},[3416,15447,3796],{"class":3795},[3416,15449,15450,15452,15454,15456],{"class":3418,"line":3437},[3416,15451,6437],{"class":6387},[3416,15453,6391],{"class":3795},[3416,15455,6442],{"class":3808},[3416,15457,3812],{"class":3795},[3416,15459,15460,15462,15464,15466,15468,15470,15472],{"class":3418,"line":3444},[3416,15461,10828],{"class":6387},[3416,15463,6391],{"class":3795},[3416,15465,6394],{"class":4368},[3416,15467,8640],{"class":6397},[3416,15469,5861],{"class":3795},[3416,15471,10839],{"class":6397},[3416,15473,6469],{"class":3795},[3416,15475,15476],{"class":3418,"line":3450},[3416,15477,6474],{"class":3795},[3416,15479,15480,15482,15484,15486,15488,15490,15492,15494,15496,15498,15500,15502,15504],{"class":3418,"line":3456},[3416,15481,9886],{"class":4368},[3416,15483,10852],{"class":6397},[3416,15485,6492],{"class":3795},[3416,15487,10857],{"class":6387},[3416,15489,6391],{"class":3795},[3416,15491,6482],{"class":3808},[3416,15493,4384],{"class":3795},[3416,15495,10866],{"class":6387},[3416,15497,6391],{"class":3795},[3416,15499,10871],{"class":6387},[3416,15501,4043],{"class":3795},[3416,15503,6495],{"class":6387},[3416,15505,8915],{"class":3795},[3416,15507,15508,15510,15512,15514,15516,15518,15520,15522,15524,15526,15528,15530,15532],{"class":3418,"line":3462},[3416,15509,9886],{"class":4368},[3416,15511,10852],{"class":6397},[3416,15513,6492],{"class":3795},[3416,15515,10857],{"class":6387},[3416,15517,6391],{"class":3795},[3416,15519,6510],{"class":3808},[3416,15521,4384],{"class":3795},[3416,15523,10866],{"class":6387},[3416,15525,6391],{"class":3795},[3416,15527,10871],{"class":6387},[3416,15529,4043],{"class":3795},[3416,15531,6495],{"class":6387},[3416,15533,8915],{"class":3795},[3416,15535,15536,15538,15540,15542,15544,15546,15548,15550,15552,15554,15556,15558,15560],{"class":3418,"line":3468},[3416,15537,9886],{"class":4368},[3416,15539,10852],{"class":6397},[3416,15541,6492],{"class":3795},[3416,15543,10857],{"class":6387},[3416,15545,6391],{"class":3795},[3416,15547,12322],{"class":3808},[3416,15549,4384],{"class":3795},[3416,15551,10866],{"class":6387},[3416,15553,6391],{"class":3795},[3416,15555,10871],{"class":6387},[3416,15557,4043],{"class":3795},[3416,15559,6495],{"class":6387},[3416,15561,8948],{"class":3795},[3416,15563,15564],{"class":3418,"line":3474},[3416,15565,4442],{"class":3795},[3416,15567,15568,15570,15572,15574,15576,15578,15580],{"class":3418,"line":3480},[3416,15569,10914],{"class":6387},[3416,15571,6391],{"class":3795},[3416,15573,6394],{"class":4368},[3416,15575,8640],{"class":6397},[3416,15577,5861],{"class":3795},[3416,15579,10925],{"class":6397},[3416,15581,6469],{"class":3795},[3416,15583,15584],{"class":3418,"line":3486},[3416,15585,6474],{"class":3795},[3416,15587,15588,15590,15592,15594,15596,15598,15600,15602,15604,15606,15608,15610,15612],{"class":3418,"line":3492},[3416,15589,9886],{"class":4368},[3416,15591,10938],{"class":6397},[3416,15593,6492],{"class":3795},[3416,15595,10857],{"class":6387},[3416,15597,6391],{"class":3795},[3416,15599,6482],{"class":3808},[3416,15601,4384],{"class":3795},[3416,15603,10951],{"class":6387},[3416,15605,6391],{"class":3795},[3416,15607,10951],{"class":6387},[3416,15609,4043],{"class":3795},[3416,15611,10960],{"class":6387},[3416,15613,8915],{"class":3795},[3416,15615,15616,15618,15620,15622,15624,15626,15628,15630,15632,15634,15636,15638,15640],{"class":3418,"line":3498},[3416,15617,9886],{"class":4368},[3416,15619,10938],{"class":6397},[3416,15621,6492],{"class":3795},[3416,15623,10857],{"class":6387},[3416,15625,6391],{"class":3795},[3416,15627,6510],{"class":3808},[3416,15629,4384],{"class":3795},[3416,15631,10951],{"class":6387},[3416,15633,6391],{"class":3795},[3416,15635,10951],{"class":6387},[3416,15637,4043],{"class":3795},[3416,15639,10989],{"class":6387},[3416,15641,8948],{"class":3795},[3416,15643,15644],{"class":3418,"line":3504},[3416,15645,4442],{"class":3795},[3416,15647,15648,15651,15653,15655,15657,15659,15662],{"class":3418,"line":3510},[3416,15649,15650],{"class":6387},"    LocalSecondaryIndexes",[3416,15652,6391],{"class":3795},[3416,15654,6394],{"class":4368},[3416,15656,8640],{"class":6397},[3416,15658,5861],{"class":3795},[3416,15660,15661],{"class":6397},"LocalSecondaryIndex",[3416,15663,6469],{"class":3795},[3416,15665,15666],{"class":3418,"line":3515},[3416,15667,6474],{"class":3795},[3416,15669,15670,15672],{"class":3418,"line":3521},[3416,15671,9886],{"class":4368},[3416,15673,15674],{"class":6397}," LocalSecondaryIndex\n",[3416,15676,15677],{"class":3418,"line":3527},[3416,15678,8611],{"class":3795},[3416,15680,15681,15684,15686,15689],{"class":3418,"line":3533},[3416,15682,15683],{"class":6387},"            IndexName",[3416,15685,6391],{"class":3795},[3416,15687,15688],{"class":3808},"\"SessionsByExpiry\"",[3416,15690,3812],{"class":3795},[3416,15692,15693,15696,15698,15700,15702,15704,15706],{"class":3418,"line":3539},[3416,15694,15695],{"class":6387},"            KeySchema",[3416,15697,6391],{"class":3795},[3416,15699,6394],{"class":4368},[3416,15701,8640],{"class":6397},[3416,15703,5861],{"class":3795},[3416,15705,10925],{"class":6397},[3416,15707,6469],{"class":3795},[3416,15709,15710],{"class":3418,"line":3545},[3416,15711,8628],{"class":3795},[3416,15713,15714,15716,15718,15720,15722,15724,15726,15728,15730,15732,15734,15736,15738],{"class":3418,"line":3551},[3416,15715,9213],{"class":4368},[3416,15717,10938],{"class":6397},[3416,15719,6492],{"class":3795},[3416,15721,10857],{"class":6387},[3416,15723,6391],{"class":3795},[3416,15725,6482],{"class":3808},[3416,15727,4384],{"class":3795},[3416,15729,10951],{"class":6387},[3416,15731,6391],{"class":3795},[3416,15733,10951],{"class":6387},[3416,15735,4043],{"class":3795},[3416,15737,10960],{"class":6387},[3416,15739,8915],{"class":3795},[3416,15741,15742,15744,15746,15748,15750,15752,15754,15756,15758,15760,15762,15764,15766],{"class":3418,"line":3557},[3416,15743,9213],{"class":4368},[3416,15745,10938],{"class":6397},[3416,15747,6492],{"class":3795},[3416,15749,10857],{"class":6387},[3416,15751,6391],{"class":3795},[3416,15753,12322],{"class":3808},[3416,15755,4384],{"class":3795},[3416,15757,10951],{"class":6387},[3416,15759,6391],{"class":3795},[3416,15761,10951],{"class":6387},[3416,15763,4043],{"class":3795},[3416,15765,10989],{"class":6387},[3416,15767,8948],{"class":3795},[3416,15769,15770],{"class":3418,"line":3563},[3416,15771,9066],{"class":3795},[3416,15773,15774,15777,15779,15781],{"class":3418,"line":3569},[3416,15775,15776],{"class":6387},"            Projection",[3416,15778,6391],{"class":3795},[3416,15780,6394],{"class":4368},[3416,15782,15783],{"class":6397}," Projection\n",[3416,15785,15786],{"class":3418,"line":3574},[3416,15787,8628],{"class":3795},[3416,15789,15790,15793,15795,15798,15800,15802],{"class":3418,"line":3579},[3416,15791,15792],{"class":6387},"                ProjectionType",[3416,15794,6391],{"class":3795},[3416,15796,15797],{"class":6387},"ProjectionType",[3416,15799,4043],{"class":3795},[3416,15801,15082],{"class":6387},[3416,15803,3812],{"class":3795},[3416,15805,15806,15809,15811,15813,15815,15817,15819,15822,15824,15826,15828],{"class":3418,"line":3584},[3416,15807,15808],{"class":6387},"                NonKeyAttributes",[3416,15810,6391],{"class":3795},[3416,15812,6394],{"class":4368},[3416,15814,8640],{"class":6397},[3416,15816,5861],{"class":3795},[3416,15818,6461],{"class":4368},[3416,15820,15821],{"class":3795},"> { ",[3416,15823,6839],{"class":3808},[3416,15825,4384],{"class":3795},[3416,15827,12346],{"class":3808},[3416,15829,8948],{"class":3795},[3416,15831,15832],{"class":3418,"line":3590},[3416,15833,8815],{"class":3795},[3416,15835,15836],{"class":3418,"line":3596},[3416,15837,8533],{"class":3795},[3416,15839,15840],{"class":3418,"line":3602},[3416,15841,4442],{"class":3795},[3416,15843,15844,15846,15848,15850,15852],{"class":3418,"line":3608},[3416,15845,11000],{"class":6387},[3416,15847,6391],{"class":3795},[3416,15849,11005],{"class":6387},[3416,15851,4043],{"class":3795},[3416,15853,11010],{"class":6387},[3416,15855,15856],{"class":3418,"line":3614},[3416,15857,6537],{"class":3795},[6311,15859,15860],{"label":6540},[3406,15861,15863],{"className":6543,"code":15862,"language":6545,"meta":3411,"style":3411},"$attrUserId    = New-DDBAttributeDefinition -AttributeName UserId    -AttributeType S\n$attrSessionId = New-DDBAttributeDefinition -AttributeName SessionId -AttributeType S\n$attrExpiresAt = New-DDBAttributeDefinition -AttributeName ExpiresAt -AttributeType S\n\n$keyUserId    = New-DDBKeySchemaElement -AttributeName UserId    -KeyType HASH\n$keySessionId = New-DDBKeySchemaElement -AttributeName SessionId -KeyType RANGE\n\n# LSI: той самий PK (UserId), новий SK (ExpiresAt)\n$lsiKey1 = New-DDBKeySchemaElement -AttributeName UserId    -KeyType HASH\n$lsiKey2 = New-DDBKeySchemaElement -AttributeName ExpiresAt -KeyType RANGE\n\n$lsiProjection = [Amazon.DynamoDBv2.Model.Projection]@{\n    ProjectionType   = 'INCLUDE'\n    NonKeyAttributes = @('IsActive', 'IpAddress')\n}\n\n$lsi = [Amazon.DynamoDBv2.Model.LocalSecondaryIndex]@{\n    IndexName  = 'SessionsByExpiry'\n    KeySchema  = @($lsiKey1, $lsiKey2)\n    Projection = $lsiProjection\n}\n\nNew-DDBTable `\n    -TableName            UserSessions `\n    -AttributeDefinition  @($attrUserId, $attrSessionId, $attrExpiresAt) `\n    -KeySchema            @($keyUserId, $keySessionId) `\n    -LocalSecondaryIndex  @($lsi) `\n    -BillingMode          PAY_PER_REQUEST `\n    -Region               eu-central-1\n",[3413,15864,15865,15875,15885,15897,15901,15911,15921,15925,15930,15941,15953,15957,15973,15983,16004,16008,16012,16028,16038,16056,16066,16070,16074,16080,16085,16106,16123,16136,16141],{"__ignoreMap":3411},[3416,15866,15867,15869,15871,15873],{"class":3418,"line":3419},[3416,15868,11044],{"class":6387},[3416,15870,6571],{"class":3795},[3416,15872,11049],{"class":6330},[3416,15874,11052],{"class":3795},[3416,15876,15877,15879,15881,15883],{"class":3418,"line":3425},[3416,15878,11057],{"class":6387},[3416,15880,6391],{"class":3795},[3416,15882,11049],{"class":6330},[3416,15884,11064],{"class":3795},[3416,15886,15887,15890,15892,15894],{"class":3418,"line":3431},[3416,15888,15889],{"class":6387},"$attrExpiresAt",[3416,15891,6391],{"class":3795},[3416,15893,11049],{"class":6330},[3416,15895,15896],{"class":3795}," -AttributeName ExpiresAt -AttributeType S\n",[3416,15898,15899],{"class":3418,"line":3437},[3416,15900,3441],{"emptyLinePlaceholder":3440},[3416,15902,15903,15905,15907,15909],{"class":3418,"line":3444},[3416,15904,11073],{"class":6387},[3416,15906,6571],{"class":3795},[3416,15908,11078],{"class":6330},[3416,15910,11081],{"class":3795},[3416,15912,15913,15915,15917,15919],{"class":3418,"line":3450},[3416,15914,11086],{"class":6387},[3416,15916,6391],{"class":3795},[3416,15918,11078],{"class":6330},[3416,15920,11093],{"class":3795},[3416,15922,15923],{"class":3418,"line":3456},[3416,15924,3441],{"emptyLinePlaceholder":3440},[3416,15926,15927],{"class":3418,"line":3462},[3416,15928,15929],{"class":3789},"# LSI: той самий PK (UserId), новий SK (ExpiresAt)\n",[3416,15931,15932,15935,15937,15939],{"class":3418,"line":3468},[3416,15933,15934],{"class":6387},"$lsiKey1",[3416,15936,6391],{"class":3795},[3416,15938,11078],{"class":6330},[3416,15940,11081],{"class":3795},[3416,15942,15943,15946,15948,15950],{"class":3418,"line":3474},[3416,15944,15945],{"class":6387},"$lsiKey2",[3416,15947,6391],{"class":3795},[3416,15949,11078],{"class":6330},[3416,15951,15952],{"class":3795}," -AttributeName ExpiresAt -KeyType RANGE\n",[3416,15954,15955],{"class":3418,"line":3480},[3416,15956,3441],{"emptyLinePlaceholder":3440},[3416,15958,15959,15962,15964,15967,15969,15971],{"class":3418,"line":3486},[3416,15960,15961],{"class":6387},"$lsiProjection",[3416,15963,7274],{"class":3795},[3416,15965,15966],{"class":4368},"Amazon.DynamoDBv2.Model.Projection",[3416,15968,7280],{"class":3795},[3416,15970,6561],{"class":4368},[3416,15972,3796],{"class":3795},[3416,15974,15975,15978,15980],{"class":3418,"line":3492},[3416,15976,15977],{"class":6387},"    ProjectionType",[3416,15979,7374],{"class":3795},[3416,15981,15982],{"class":3808},"'INCLUDE'\n",[3416,15984,15985,15988,15990,15992,15994,15997,15999,16002],{"class":3418,"line":3498},[3416,15986,15987],{"class":6387},"    NonKeyAttributes",[3416,15989,6391],{"class":3795},[3416,15991,6561],{"class":4368},[3416,15993,6423],{"class":3795},[3416,15995,15996],{"class":3808},"'IsActive'",[3416,15998,4384],{"class":3795},[3416,16000,16001],{"class":3808},"'IpAddress'",[3416,16003,9656],{"class":3795},[3416,16005,16006],{"class":3418,"line":3504},[3416,16007,3507],{"class":3795},[3416,16009,16010],{"class":3418,"line":3510},[3416,16011,3441],{"emptyLinePlaceholder":3440},[3416,16013,16014,16017,16019,16022,16024,16026],{"class":3418,"line":3515},[3416,16015,16016],{"class":6387},"$lsi",[3416,16018,7274],{"class":3795},[3416,16020,16021],{"class":4368},"Amazon.DynamoDBv2.Model.LocalSecondaryIndex",[3416,16023,7280],{"class":3795},[3416,16025,6561],{"class":4368},[3416,16027,3796],{"class":3795},[3416,16029,16030,16033,16035],{"class":3418,"line":3521},[3416,16031,16032],{"class":6387},"    IndexName",[3416,16034,6933],{"class":3795},[3416,16036,16037],{"class":3808},"'SessionsByExpiry'\n",[3416,16039,16040,16042,16044,16046,16048,16050,16052,16054],{"class":3418,"line":3527},[3416,16041,10914],{"class":6387},[3416,16043,6933],{"class":3795},[3416,16045,6561],{"class":4368},[3416,16047,6423],{"class":3795},[3416,16049,15934],{"class":6387},[3416,16051,4384],{"class":3795},[3416,16053,15945],{"class":6387},[3416,16055,9656],{"class":3795},[3416,16057,16058,16061,16063],{"class":3418,"line":3533},[3416,16059,16060],{"class":6387},"    Projection",[3416,16062,6391],{"class":3795},[3416,16064,16065],{"class":6387},"$lsiProjection\n",[3416,16067,16068],{"class":3418,"line":3539},[3416,16069,3507],{"class":3795},[3416,16071,16072],{"class":3418,"line":3545},[3416,16073,3441],{"emptyLinePlaceholder":3440},[3416,16075,16076,16078],{"class":3418,"line":3551},[3416,16077,11102],{"class":6330},[3416,16079,11105],{"class":3795},[3416,16081,16082],{"class":3418,"line":3557},[3416,16083,16084],{"class":3795},"    -TableName            UserSessions `\n",[3416,16086,16087,16090,16092,16094,16096,16098,16100,16102,16104],{"class":3418,"line":3563},[3416,16088,16089],{"class":3795},"    -AttributeDefinition  ",[3416,16091,6561],{"class":4368},[3416,16093,6423],{"class":3795},[3416,16095,11044],{"class":6387},[3416,16097,4384],{"class":3795},[3416,16099,11057],{"class":6387},[3416,16101,4384],{"class":3795},[3416,16103,15889],{"class":6387},[3416,16105,11128],{"class":3795},[3416,16107,16108,16111,16113,16115,16117,16119,16121],{"class":3418,"line":3569},[3416,16109,16110],{"class":3795},"    -KeySchema            ",[3416,16112,6561],{"class":4368},[3416,16114,6423],{"class":3795},[3416,16116,11073],{"class":6387},[3416,16118,4384],{"class":3795},[3416,16120,11086],{"class":6387},[3416,16122,11128],{"class":3795},[3416,16124,16125,16128,16130,16132,16134],{"class":3418,"line":3574},[3416,16126,16127],{"class":3795},"    -LocalSecondaryIndex  ",[3416,16129,6561],{"class":4368},[3416,16131,6423],{"class":3795},[3416,16133,16016],{"class":6387},[3416,16135,11128],{"class":3795},[3416,16137,16138],{"class":3418,"line":3579},[3416,16139,16140],{"class":3795},"    -BillingMode          PAY_PER_REQUEST `\n",[3416,16142,16143,16146],{"class":3418,"line":3584},[3416,16144,16145],{"class":3795},"    -Region               eu-central-",[3416,16147,6614],{"class":3870},[3727,16149,16151],{"id":16150},"query-через-lsi","Query через LSI",[6308,16153,16154,16231,16387],{},[6311,16155,16156],{"label":6313},[3406,16157,16159],{"className":6316,"code":16158,"language":6318,"meta":3411,"style":3411},"# Знайти сесії usr-001, що закінчаться до 2025-06-02T00:00:00Z\naws dynamodb query \\\n    --table-name UserSessions \\\n    --index-name SessionsByExpiry \\\n    --key-condition-expression \"UserId = :uid AND ExpiresAt \u003C :exp\" \\\n    --expression-attribute-values '{\n        \":uid\": {\"S\": \"usr-001\"},\n        \":exp\": {\"S\": \"2025-06-02T00:00:00Z\"}\n    }' \\\n    --region eu-central-1\n",[3413,16160,16161,16166,16176,16184,16194,16203,16209,16214,16219,16225],{"__ignoreMap":3411},[3416,16162,16163],{"class":3418,"line":3419},[3416,16164,16165],{"class":3789},"# Знайти сесії usr-001, що закінчаться до 2025-06-02T00:00:00Z\n",[3416,16167,16168,16170,16172,16174],{"class":3418,"line":3425},[3416,16169,6331],{"class":6330},[3416,16171,6334],{"class":3808},[3416,16173,7676],{"class":3808},[3416,16175,6341],{"class":6340},[3416,16177,16178,16180,16182],{"class":3418,"line":3431},[3416,16179,6346],{"class":4368},[3416,16181,6349],{"class":3808},[3416,16183,6341],{"class":6340},[3416,16185,16186,16189,16192],{"class":3418,"line":3437},[3416,16187,16188],{"class":4368},"    --index-name",[3416,16190,16191],{"class":3808}," SessionsByExpiry",[3416,16193,6341],{"class":6340},[3416,16195,16196,16198,16201],{"class":3418,"line":3444},[3416,16197,7691],{"class":4368},[3416,16199,16200],{"class":3808}," \"UserId = :uid AND ExpiresAt \u003C :exp\"",[3416,16202,6341],{"class":6340},[3416,16204,16205,16207],{"class":3418,"line":3450},[3416,16206,7021],{"class":4368},[3416,16208,6661],{"class":3808},[3416,16210,16211],{"class":3418,"line":3456},[3416,16212,16213],{"class":3808},"        \":uid\": {\"S\": \"usr-001\"},\n",[3416,16215,16216],{"class":3418,"line":3462},[3416,16217,16218],{"class":3808},"        \":exp\": {\"S\": \"2025-06-02T00:00:00Z\"}\n",[3416,16220,16221,16223],{"class":3418,"line":3468},[3416,16222,6686],{"class":3808},[3416,16224,6341],{"class":6340},[3416,16226,16227,16229],{"class":3418,"line":3474},[3416,16228,6366],{"class":4368},[3416,16230,6369],{"class":3808},[6311,16232,16233],{"label":6372},[3406,16234,16236],{"className":6375,"code":16235,"language":6377,"meta":3411,"style":3411},"var client = new AmazonDynamoDBClient();\nvar response = await client.QueryAsync(new QueryRequest\n{\n    TableName = \"UserSessions\",\n    IndexName = \"SessionsByExpiry\",\n    KeyConditionExpression = \"UserId = :uid AND ExpiresAt \u003C :exp\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":uid\", new AttributeValue { S = \"usr-001\" } },\n        { \":exp\", new AttributeValue { S = \"2025-06-02T00:00:00Z\" } }\n    }\n});\n",[3413,16237,16238,16252,16274,16278,16288,16298,16309,16329,16333,16355,16379,16383],{"__ignoreMap":3411},[3416,16239,16240,16242,16244,16246,16248,16250],{"class":3418,"line":3419},[3416,16241,6384],{"class":4368},[3416,16243,6388],{"class":6387},[3416,16245,6391],{"class":3795},[3416,16247,6394],{"class":4368},[3416,16249,6398],{"class":6397},[3416,16251,6401],{"class":3795},[3416,16253,16254,16256,16258,16260,16262,16264,16266,16268,16270,16272],{"class":3418,"line":3425},[3416,16255,6384],{"class":4368},[3416,16257,6408],{"class":6387},[3416,16259,6391],{"class":3795},[3416,16261,6413],{"class":4368},[3416,16263,6388],{"class":6387},[3416,16265,4043],{"class":3795},[3416,16267,7748],{"class":6330},[3416,16269,6423],{"class":3795},[3416,16271,6394],{"class":4368},[3416,16273,7755],{"class":6397},[3416,16275,16276],{"class":3418,"line":3431},[3416,16277,3796],{"class":3795},[3416,16279,16280,16282,16284,16286],{"class":3418,"line":3437},[3416,16281,6437],{"class":6387},[3416,16283,6391],{"class":3795},[3416,16285,6442],{"class":3808},[3416,16287,3812],{"class":3795},[3416,16289,16290,16292,16294,16296],{"class":3418,"line":3444},[3416,16291,16032],{"class":6387},[3416,16293,6391],{"class":3795},[3416,16295,15688],{"class":3808},[3416,16297,3812],{"class":3795},[3416,16299,16300,16302,16304,16307],{"class":3418,"line":3450},[3416,16301,7774],{"class":6387},[3416,16303,6391],{"class":3795},[3416,16305,16306],{"class":3808},"\"UserId = :uid AND ExpiresAt \u003C :exp\"",[3416,16308,3812],{"class":3795},[3416,16310,16311,16313,16315,16317,16319,16321,16323,16325,16327],{"class":3418,"line":3456},[3416,16312,7179],{"class":6387},[3416,16314,6391],{"class":3795},[3416,16316,6394],{"class":4368},[3416,16318,6456],{"class":6397},[3416,16320,5861],{"class":3795},[3416,16322,6461],{"class":4368},[3416,16324,4384],{"class":3795},[3416,16326,6466],{"class":6397},[3416,16328,6469],{"class":3795},[3416,16330,16331],{"class":3418,"line":3462},[3416,16332,6474],{"class":3795},[3416,16334,16335,16337,16339,16341,16343,16345,16347,16349,16351,16353],{"class":3418,"line":3468},[3416,16336,6479],{"class":3795},[3416,16338,7812],{"class":3808},[3416,16340,4384],{"class":3795},[3416,16342,6394],{"class":4368},[3416,16344,6489],{"class":6397},[3416,16346,6492],{"class":3795},[3416,16348,6495],{"class":6387},[3416,16350,6391],{"class":3795},[3416,16352,6500],{"class":3808},[3416,16354,6503],{"class":3795},[3416,16356,16357,16359,16362,16364,16366,16368,16370,16372,16374,16377],{"class":3418,"line":3474},[3416,16358,6479],{"class":3795},[3416,16360,16361],{"class":3808},"\":exp\"",[3416,16363,4384],{"class":3795},[3416,16365,6394],{"class":4368},[3416,16367,6489],{"class":6397},[3416,16369,6492],{"class":3795},[3416,16371,6495],{"class":6387},[3416,16373,6391],{"class":3795},[3416,16375,16376],{"class":3808},"\"2025-06-02T00:00:00Z\"",[3416,16378,6528],{"class":3795},[3416,16380,16381],{"class":3418,"line":3480},[3416,16382,4167],{"class":3795},[3416,16384,16385],{"class":3418,"line":3486},[3416,16386,6537],{"class":3795},[6311,16388,16389],{"label":6540},[3406,16390,16392],{"className":6543,"code":16391,"language":6545,"meta":3411,"style":3411},"$queryRequest = [Amazon.DynamoDBv2.Model.QueryRequest]@{\n    TableName              = 'UserSessions'\n    IndexName              = 'SessionsByExpiry'\n    KeyConditionExpression = 'UserId = :uid AND ExpiresAt \u003C :exp'\n    ExpressionAttributeValues = @{\n        ':uid' = New-DDBEntry -S 'usr-001'\n        ':exp' = New-DDBEntry -S '2025-06-02T00:00:00Z'\n    }\n}\nInvoke-DDBQuery -QueryRequest $queryRequest -Region eu-central-1\n",[3413,16393,16394,16408,16416,16424,16433,16443,16455,16469,16473,16477],{"__ignoreMap":3411},[3416,16395,16396,16398,16400,16402,16404,16406],{"class":3418,"line":3419},[3416,16397,7877],{"class":6387},[3416,16399,7274],{"class":3795},[3416,16401,7882],{"class":4368},[3416,16403,7280],{"class":3795},[3416,16405,6561],{"class":4368},[3416,16407,3796],{"class":3795},[3416,16409,16410,16412,16414],{"class":3418,"line":3425},[3416,16411,6437],{"class":6387},[3416,16413,13271],{"class":3795},[3416,16415,7293],{"class":3808},[3416,16417,16418,16420,16422],{"class":3418,"line":3431},[3416,16419,16032],{"class":6387},[3416,16421,13271],{"class":3795},[3416,16423,16037],{"class":3808},[3416,16425,16426,16428,16430],{"class":3418,"line":3437},[3416,16427,7774],{"class":6387},[3416,16429,6391],{"class":3795},[3416,16431,16432],{"class":3808},"'UserId = :uid AND ExpiresAt \u003C :exp'\n",[3416,16434,16435,16437,16439,16441],{"class":3418,"line":3444},[3416,16436,7179],{"class":6387},[3416,16438,6391],{"class":3795},[3416,16440,6561],{"class":4368},[3416,16442,3796],{"class":3795},[3416,16444,16445,16447,16449,16451,16453],{"class":3418,"line":3450},[3416,16446,7920],{"class":3808},[3416,16448,6391],{"class":3795},[3416,16450,6574],{"class":6330},[3416,16452,6577],{"class":3795},[3416,16454,6580],{"class":3808},[3416,16456,16457,16460,16462,16464,16466],{"class":3418,"line":3456},[3416,16458,16459],{"class":3808},"        ':exp'",[3416,16461,6391],{"class":3795},[3416,16463,6574],{"class":6330},[3416,16465,6577],{"class":3795},[3416,16467,16468],{"class":3808},"'2025-06-02T00:00:00Z'\n",[3416,16470,16471],{"class":3418,"line":3462},[3416,16472,4167],{"class":3795},[3416,16474,16475],{"class":3418,"line":3468},[3416,16476,3507],{"class":3795},[3416,16478,16479,16481,16483,16485,16487],{"class":3418,"line":3474},[3416,16480,7956],{"class":6330},[3416,16482,7959],{"class":3795},[3416,16484,7877],{"class":6387},[3416,16486,6611],{"class":3795},[3416,16488,6614],{"class":3870},[11159,16490,16492,16501,16504,16510,16513,16525,16538,16551,16563,16575,16579,16582,16594,16607,16619,16631,16644,16647,16650,16659,16668],{"title":16491},"Query через LSI SessionsByExpiry",[11163,16493,16495,10466,16498],{"className":16494},[3418],[3416,16496,11170],{"className":16497},[11169],[3363,16499,16500],{},"aws dynamodb query --index-name SessionsByExpiry --key-condition-expression \"UserId = :uid AND ExpiresAt \u003C :exp\" ...",[11163,16502,11177],{"className":16503},[3418],[11163,16505,11181,16507,4378],{"className":16506},[3418],[3416,16508,13435],{"className":16509},[11185],[11163,16511,13439],{"className":16512},[3418],[11163,16514,11282,16516,13446,16519,3805,16522,11250],{"className":16515},[3418],[3416,16517,6482],{"className":16518},[11185],[3416,16520,13450],{"className":16521},[11185],[3416,16523,6500],{"className":16524},[11199],[11163,16526,11282,16528,13460,16531,3805,16534,11250],{"className":16527},[3418],[3416,16529,6510],{"className":16530},[11185],[3416,16532,13450],{"className":16533},[11185],[3416,16535,16537],{"className":16536},[11199],"\"sess-C\"",[11163,16539,11282,16541,13460,16544,3805,16547,11250],{"className":16540},[3418],[3416,16542,12322],{"className":16543},[11185],[3416,16545,13450],{"className":16546},[11185],[3416,16548,16550],{"className":16549},[11199],"\"2025-05-31T08:00:00Z\"",[11163,16552,11282,16554,13473,16557,3805,16560,11250],{"className":16553},[3418],[3416,16555,6839],{"className":16556},[11185],[3416,16558,13477],{"className":16559},[11185],[3416,16561,4042],{"className":16562},[11211],[11163,16564,11282,16566,13460,16569,3805,16572,11267],{"className":16565},[3418],[3416,16567,12346],{"className":16568},[11185],[3416,16570,13450],{"className":16571},[11185],[3416,16573,12361],{"className":16574},[11199],[11163,16576,16578],{"className":16577},[3418],"        },",[11163,16580,13439],{"className":16581},[3418],[11163,16583,11282,16585,13446,16588,3805,16591,11250],{"className":16584},[3418],[3416,16586,6482],{"className":16587},[11185],[3416,16589,13450],{"className":16590},[11185],[3416,16592,6500],{"className":16593},[11199],[11163,16595,11282,16597,13460,16600,3805,16603,11250],{"className":16596},[3418],[3416,16598,6510],{"className":16599},[11185],[3416,16601,13450],{"className":16602},[11185],[3416,16604,16606],{"className":16605},[11199],"\"sess-A\"",[11163,16608,11282,16610,13460,16613,3805,16616,11250],{"className":16609},[3418],[3416,16611,12322],{"className":16612},[11185],[3416,16614,13450],{"className":16615},[11185],[3416,16617,12337],{"className":16618},[11199],[11163,16620,11282,16622,13473,16625,3805,16628,11250],{"className":16621},[3418],[3416,16623,6839],{"className":16624},[11185],[3416,16626,13477],{"className":16627},[11185],[3416,16629,4038],{"className":16630},[11211],[11163,16632,11282,16634,13460,16637,3805,16640,11267],{"className":16633},[3418],[3416,16635,12346],{"className":16636},[11185],[3416,16638,13450],{"className":16639},[11185],[3416,16641,16643],{"className":16642},[11199],"\"198.51.100.7\"",[11163,16645,11294],{"className":16646},[3418],[11163,16648,13499],{"className":16649},[3418],[11163,16651,11181,16653,3805,16656,11200],{"className":16652},[3418],[3416,16654,13506],{"className":16655},[11185],[3416,16657,3955],{"className":16658},[11211],[11163,16660,11181,16662,3805,16665],{"className":16661},[3418],[3416,16663,13517],{"className":16664},[11185],[3416,16666,3955],{"className":16667},[11211],[11163,16669,11302],{"className":16670},[3418],[3720,16672],{},[3348,16674,16676],{"id":16675},"global-secondary-index-gsi","Global Secondary Index (GSI)",[3353,16678,16679,16681,16682,16685],{},[3363,16680,16676],{}," представляє собою найбільш гнучкий та потужний інструмент побудови вторинних ключів доступу в Amazon DynamoDB. На відміну від LSI, GSI дозволяє обрати ",[3363,16683,16684],{},"абсолютно довільні атрибути"," таблиці як в якості Partition Key (HASH), так і Sort Key (RANGE), повністю ігноруючи схему первинного ключа основної таблиці. Слово «Global» у назві вказує на те, що запити через цей індекс можуть охоплювати дані на всіх фізичних партиціях основної таблиці.",[3727,16687,16689],{"id":16688},"архітектурні-особливості-та-фізична-реалізація-gsi","Архітектурні особливості та фізична реалізація GSI",[3353,16691,16692,16693,16696],{},"Під капом Amazon DynamoDB реалізує GSI як ",[3363,16694,16695],{},"повністю автономну внутрішню таблицю",", яка автоматично синхронізується з основною таблицею. Ця внутрішня таблиця має власну схему розділення на фізичні партиції, власні вузли зберігання (storage nodes) і, що найважливіше, — свій власний незалежний пул пропускної здатності (RCU та WCU) у випадку використання режиму Provisioned.",[3353,16698,16699],{},"Така фізична автономність зумовлює три фундаментальні архітектурні наслідки:",[3374,16701,16702,16715,16721],{},[3377,16703,16704,16707,16708,16710,16711,16714],{},[3363,16705,16706],{},"Гарантована кінцева узгодженість (Eventually Consistent Reads):","\nСинхронізація даних між основною таблицею та GSI виконується асинхронно за допомогою внутрішнього механізму реплікації. Через це запити (",[3413,16709,4887],{},") через GSI підтримують ",[3363,16712,16713],{},"виключно Eventually Consistent reads",". Зчитування з Strongly Consistent або в межах транзакцій безпосередньо через GSI є неможливим, оскільки реплікація в індекс відбувається з мінімальною затримкою (зазвичай до кількох десятків мілісекунд, але за умови перевантаження індексу затримка може зростати).",[3377,16716,16717,16720],{},[3363,16718,16719],{},"Автономне керування ємністю (Independent Throughput):","\nУ режимі Provisioned для GSI необхідно окремо налаштовувати ліміти RCU та WCU. Вони ніяк не пов'язані з лімітами основної таблиці та оплачуються окремо.",[3377,16722,16723,16726,16727,4043,16730,16732,16735,16736,16739],{},[3363,16724,16725],{},"Ефект \"зворотного тиску\" при перевантаженні індексу (GSI Throttling Backpressure):","\nОскільки реплікація в GSI відбувається асинхронно, при високій інтенсивності записів на основну таблицю індекс може не встигати оновлюватися, якщо його ліміт WCU занижений. Щоб запобігти безконтрольному відставанню реплікації та переповненню черг оновлень, DynamoDB застосовує зворотний тиск: ",[3363,16728,16729],{},"помилки недостатньої ємності (throttling) на GSI будуть каскадно блокувати операції запису в основній таблиці",[4628,16731],{},[4091,16733,16734],{},"Критичне правило:"," навіть якщо основна таблиця має надлишок WCU, запис до неї завершиться помилкою ",[3413,16737,16738],{},"ProvisionedThroughputExceededException",", якщо асоційований GSI вичерпає власні WCU.",[3403,16741,16742],{},[3406,16743,16745],{"className":3408,"code":16744,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle GSI SessionsByIp: Запити за IpAddress без прив'язки до UserId\n\npackage \"Основна таблиця: UserSessions\" as MAIN #E8F4FD {\n    note as MAIN_DATA\n      PK:usr-001 | SK:sess-A | IP:203.0.113.42 | CreatedAt:2025-06-01T10:00\n      PK:usr-001 | SK:sess-B | IP:198.51.100.7 | CreatedAt:2025-06-01T11:00\n      PK:usr-002 | SK:sess-C | IP:203.0.113.42 | CreatedAt:2025-06-01T12:00\n      PK:usr-003 | SK:sess-D | IP:10.0.0.5     | CreatedAt:2025-06-01T13:00\n    end note\n}\n\npackage \"GSI індекс: SessionsByIp\" as GSI #D5E8D4 {\n    note as GSI_DATA\n      GSI-PK: IpAddress (HASH) | GSI-SK: CreatedAt (RANGE)\n      ────────────────────────────────────────────────────\n      10.0.0.5     | 2025-06-01T13:00 → usr-003\u002Fsess-D\n      198.51.100.7 | 2025-06-01T11:00 → usr-001\u002Fsess-B\n      203.0.113.42 | 2025-06-01T10:00 → usr-001\u002Fsess-A\n      203.0.113.42 | 2025-06-01T12:00 → usr-002\u002Fsess-C\n      ────────────────────────────────────────────────────\n      Сортування: HASH (IpAddress) -> RANGE (CreatedAt)\n    end note\n}\n\nMAIN -right-> GSI : \"Асинхронна реплікація\\n(Eventual Consistency)\"\n\nnote bottom of GSI\n  Запит (Query): IpAddress = \"203.0.113.42\"\n  * Повертає: usr-001\u002Fsess-A + usr-002\u002Fsess-C\n  * Поєднує дані різних користувачів!\n  * Не вимагає дорогого Scan основної таблиці\nend note\n@enduml\n",[3413,16746,16747,16751,16756,16761,16766,16770,16775,16779,16784,16789,16794,16799,16804,16809,16813,16817,16821,16826,16831,16836,16841,16846,16851,16856,16861,16865,16870,16874,16878,16882,16887,16891,16896,16901,16906,16911,16916,16920],{"__ignoreMap":3411},[3416,16748,16749],{"class":3418,"line":3419},[3416,16750,3422],{},[3416,16752,16753],{"class":3418,"line":3425},[3416,16754,16755],{},"!theme plain\n",[3416,16757,16758],{"class":3418,"line":3431},[3416,16759,16760],{},"skinparam backgroundColor #FAFAFA\n",[3416,16762,16763],{"class":3418,"line":3437},[3416,16764,16765],{},"skinparam defaultFontName \"DejaVu Sans\"\n",[3416,16767,16768],{"class":3418,"line":3444},[3416,16769,3441],{"emptyLinePlaceholder":3440},[3416,16771,16772],{"class":3418,"line":3450},[3416,16773,16774],{},"title GSI SessionsByIp: Запити за IpAddress без прив'язки до UserId\n",[3416,16776,16777],{"class":3418,"line":3456},[3416,16778,3441],{"emptyLinePlaceholder":3440},[3416,16780,16781],{"class":3418,"line":3462},[3416,16782,16783],{},"package \"Основна таблиця: UserSessions\" as MAIN #E8F4FD {\n",[3416,16785,16786],{"class":3418,"line":3468},[3416,16787,16788],{},"    note as MAIN_DATA\n",[3416,16790,16791],{"class":3418,"line":3474},[3416,16792,16793],{},"      PK:usr-001 | SK:sess-A | IP:203.0.113.42 | CreatedAt:2025-06-01T10:00\n",[3416,16795,16796],{"class":3418,"line":3480},[3416,16797,16798],{},"      PK:usr-001 | SK:sess-B | IP:198.51.100.7 | CreatedAt:2025-06-01T11:00\n",[3416,16800,16801],{"class":3418,"line":3486},[3416,16802,16803],{},"      PK:usr-002 | SK:sess-C | IP:203.0.113.42 | CreatedAt:2025-06-01T12:00\n",[3416,16805,16806],{"class":3418,"line":3492},[3416,16807,16808],{},"      PK:usr-003 | SK:sess-D | IP:10.0.0.5     | CreatedAt:2025-06-01T13:00\n",[3416,16810,16811],{"class":3418,"line":3498},[3416,16812,3501],{},[3416,16814,16815],{"class":3418,"line":3504},[3416,16816,3507],{},[3416,16818,16819],{"class":3418,"line":3510},[3416,16820,3441],{"emptyLinePlaceholder":3440},[3416,16822,16823],{"class":3418,"line":3515},[3416,16824,16825],{},"package \"GSI індекс: SessionsByIp\" as GSI #D5E8D4 {\n",[3416,16827,16828],{"class":3418,"line":3521},[3416,16829,16830],{},"    note as GSI_DATA\n",[3416,16832,16833],{"class":3418,"line":3527},[3416,16834,16835],{},"      GSI-PK: IpAddress (HASH) | GSI-SK: CreatedAt (RANGE)\n",[3416,16837,16838],{"class":3418,"line":3533},[3416,16839,16840],{},"      ────────────────────────────────────────────────────\n",[3416,16842,16843],{"class":3418,"line":3539},[3416,16844,16845],{},"      10.0.0.5     | 2025-06-01T13:00 → usr-003\u002Fsess-D\n",[3416,16847,16848],{"class":3418,"line":3545},[3416,16849,16850],{},"      198.51.100.7 | 2025-06-01T11:00 → usr-001\u002Fsess-B\n",[3416,16852,16853],{"class":3418,"line":3551},[3416,16854,16855],{},"      203.0.113.42 | 2025-06-01T10:00 → usr-001\u002Fsess-A\n",[3416,16857,16858],{"class":3418,"line":3557},[3416,16859,16860],{},"      203.0.113.42 | 2025-06-01T12:00 → usr-002\u002Fsess-C\n",[3416,16862,16863],{"class":3418,"line":3563},[3416,16864,16840],{},[3416,16866,16867],{"class":3418,"line":3569},[3416,16868,16869],{},"      Сортування: HASH (IpAddress) -> RANGE (CreatedAt)\n",[3416,16871,16872],{"class":3418,"line":3574},[3416,16873,3501],{},[3416,16875,16876],{"class":3418,"line":3579},[3416,16877,3507],{},[3416,16879,16880],{"class":3418,"line":3584},[3416,16881,3441],{"emptyLinePlaceholder":3440},[3416,16883,16884],{"class":3418,"line":3590},[3416,16885,16886],{},"MAIN -right-> GSI : \"Асинхронна реплікація\\n(Eventual Consistency)\"\n",[3416,16888,16889],{"class":3418,"line":3596},[3416,16890,3441],{"emptyLinePlaceholder":3440},[3416,16892,16893],{"class":3418,"line":3602},[3416,16894,16895],{},"note bottom of GSI\n",[3416,16897,16898],{"class":3418,"line":3608},[3416,16899,16900],{},"  Запит (Query): IpAddress = \"203.0.113.42\"\n",[3416,16902,16903],{"class":3418,"line":3614},[3416,16904,16905],{},"  * Повертає: usr-001\u002Fsess-A + usr-002\u002Fsess-C\n",[3416,16907,16908],{"class":3418,"line":3620},[3416,16909,16910],{},"  * Поєднує дані різних користувачів!\n",[3416,16912,16913],{"class":3418,"line":3626},[3416,16914,16915],{},"  * Не вимагає дорогого Scan основної таблиці\n",[3416,16917,16918],{"class":3418,"line":3631},[3416,16919,5088],{},[3416,16921,16922],{"class":3418,"line":3636},[3416,16923,3718],{},[3727,16925,16927],{"id":16926},"sparse-index-розріджені-індекси-паттерн-оптимізації-обсягу-та-витрат","Sparse Index (Розріджені індекси) — паттерн оптимізації обсягу та витрат",[3353,16929,16930,16933],{},[3363,16931,16932],{},"Sparse Index (розріджений індекс)"," — це фундаментальний патерн проектування вторинних індексів у DynamoDB, який використовує вибіркову поведінку оновлення індексів.",[3353,16935,16936,16937,16940],{},"За замовчуванням вторинний індекс у DynamoDB вважається розрідженим, якщо будь-який елемент основної таблиці не містить атрибутів, визначених як Partition Key або Sort Key цього індексу. DynamoDB ",[3363,16938,16939],{},"не створює запис в індексі",", якщо у вихідному елементі відсутній хоча б один із ключів індексу.",[4584,16942,16944],{"id":16943},"переваги-та-архітектурна-цінність-розріджених-індексів","Переваги та архітектурна цінність розріджених індексів:",[3374,16946,16947,16953,16959],{},[3377,16948,16949,16952],{},[3363,16950,16951],{},"Скорочення витрат на зберігання (Storage Savings):","\nЗамість копіювання мільярдів записів, індекс містить лише ту вибіркову підмножину даних, яка відповідає певній умові бізнес-логіки.",[3377,16954,16955,16958],{},[3363,16956,16957],{},"Мінімізація WCU (Write Savings):","\nDynamoDB оновлює GSI лише тоді, коли створюється або змінюється елемент, що містить ключові атрибути індексу. Зміна будь-яких інших елементів таблиці не витрачає пропускну здатність GSI.",[3377,16960,16961,16964,16965,16967],{},[3363,16962,16963],{},"Висока швидкість виконання запитів (Query Efficiency):","\nОскільки індекс компактний, операції ",[3413,16966,4887],{}," виконуються за мінімальну кількість звернень, без потреби сканувати зайві дані.",[4584,16969,16971],{"id":16970},"сценарій-застосування-обробка-незавершених-замовлень-pending-orders","Сценарій застосування: Обробка незавершених замовлень (Pending Orders)",[3353,16973,16974,16975,4384,16977,16980,16981,13590],{},"Уявімо велику e-commerce систему з мільярдами замовлень, де 99% замовлень знаходяться у кінцевих статусах (",[3413,16976,5264],{},[3413,16978,16979],{},"CANCELLED","), і лише 1% замовлень перебуває в процесі обробки (",[3413,16982,5298],{},[3353,16984,16985,16986,16989,16990,16992,16993,16996,16997,16999,17000,17002],{},"Операторам потрібно постійно отримувати список замовлень для обробки. Сканування всієї таблиці є неприпустимо дорогим. Якщо ми створимо GSI з ключем сортування, який заповнюється значенням дати ",[4091,16987,16988],{},"виключно"," для замовлень зі статусом ",[3413,16991,5298],{}," (наприклад, атрибут ",[3413,16994,16995],{},"PendingStatus"," заповнюється лише тоді, коли статус дорівнює ",[3413,16998,5298],{},"), індекс міститиме лише цей 1% активних замовлень. Як тільки замовлення доставляється, атрибут ",[3413,17001,16995],{}," видаляється з елемента, і DynamoDB автоматично прибирає цей запис із розрідженого GSI.",[3403,17004,17005],{},[3406,17006,17008],{"className":3408,"code":17007,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Sparse GSI: Індексуються лише елементи з атрибутом NeedsProcessing\n\npackage \"Основна таблиця: Orders (1 млн елементів)\" as MAIN #E8F4FD {\n    card \"ord-001\\nStatus: DELIVERED\\n(NeedsProcessing відсутній)\" as O1 #D5E8D4\n    card \"ord-002\\nStatus: PENDING\\nNeedsProcessing: 'true'\" as O2 #FFF2CC\n    card \"ord-003\\nStatus: DELIVERED\\n(NeedsProcessing відсутній)\" as O3 #D5E8D4\n    card \"ord-004\\nStatus: PENDING\\nNeedsProcessing: 'true'\" as O4 #FFF2CC\n}\n\npackage \"Sparse GSI: PendingOrders\\nGSI-PK: NeedsProcessing\" as GSI #F0E6FF {\n    note as GSI_NOTE\n      Індекс містить лише 2 елементи!\n      ───────────────────────────\n      NeedsProcessing='true' → ord-002\n      NeedsProcessing='true' → ord-004\n      ───────────────────────────\n      Елементи ord-001 та ord-003\n      повністю ігноруються індексом\n    end note\n}\n\nO2 -right-> GSI : \"Проектується (атрибут наявний)\"\nO4 -right-> GSI : \"Проектується (атрибут наявний)\"\nO1 ..> GSI : \"Не проектується\"\nO3 ..> GSI : \"Не проектується\"\n\nnote bottom of GSI\n  Запит (Query): NeedsProcessing = 'true'\n  * Отримує 2 елементи замість сканування 1 млн\n  * При оновленні статусу видаляємо NeedsProcessing\n  * Елемент автоматично видаляється з GSI\nend note\n@enduml\n",[3413,17009,17010,17014,17018,17022,17026,17030,17035,17039,17044,17049,17054,17059,17064,17068,17072,17077,17081,17086,17091,17096,17101,17105,17110,17115,17119,17123,17127,17132,17137,17142,17147,17151,17155,17160,17165,17170,17175,17179],{"__ignoreMap":3411},[3416,17011,17012],{"class":3418,"line":3419},[3416,17013,3422],{},[3416,17015,17016],{"class":3418,"line":3425},[3416,17017,16755],{},[3416,17019,17020],{"class":3418,"line":3431},[3416,17021,16760],{},[3416,17023,17024],{"class":3418,"line":3437},[3416,17025,16765],{},[3416,17027,17028],{"class":3418,"line":3444},[3416,17029,3441],{"emptyLinePlaceholder":3440},[3416,17031,17032],{"class":3418,"line":3450},[3416,17033,17034],{},"title Sparse GSI: Індексуються лише елементи з атрибутом NeedsProcessing\n",[3416,17036,17037],{"class":3418,"line":3456},[3416,17038,3441],{"emptyLinePlaceholder":3440},[3416,17040,17041],{"class":3418,"line":3462},[3416,17042,17043],{},"package \"Основна таблиця: Orders (1 млн елементів)\" as MAIN #E8F4FD {\n",[3416,17045,17046],{"class":3418,"line":3468},[3416,17047,17048],{},"    card \"ord-001\\nStatus: DELIVERED\\n(NeedsProcessing відсутній)\" as O1 #D5E8D4\n",[3416,17050,17051],{"class":3418,"line":3474},[3416,17052,17053],{},"    card \"ord-002\\nStatus: PENDING\\nNeedsProcessing: 'true'\" as O2 #FFF2CC\n",[3416,17055,17056],{"class":3418,"line":3480},[3416,17057,17058],{},"    card \"ord-003\\nStatus: DELIVERED\\n(NeedsProcessing відсутній)\" as O3 #D5E8D4\n",[3416,17060,17061],{"class":3418,"line":3486},[3416,17062,17063],{},"    card \"ord-004\\nStatus: PENDING\\nNeedsProcessing: 'true'\" as O4 #FFF2CC\n",[3416,17065,17066],{"class":3418,"line":3492},[3416,17067,3507],{},[3416,17069,17070],{"class":3418,"line":3498},[3416,17071,3441],{"emptyLinePlaceholder":3440},[3416,17073,17074],{"class":3418,"line":3504},[3416,17075,17076],{},"package \"Sparse GSI: PendingOrders\\nGSI-PK: NeedsProcessing\" as GSI #F0E6FF {\n",[3416,17078,17079],{"class":3418,"line":3510},[3416,17080,14670],{},[3416,17082,17083],{"class":3418,"line":3515},[3416,17084,17085],{},"      Індекс містить лише 2 елементи!\n",[3416,17087,17088],{"class":3418,"line":3521},[3416,17089,17090],{},"      ───────────────────────────\n",[3416,17092,17093],{"class":3418,"line":3527},[3416,17094,17095],{},"      NeedsProcessing='true' → ord-002\n",[3416,17097,17098],{"class":3418,"line":3533},[3416,17099,17100],{},"      NeedsProcessing='true' → ord-004\n",[3416,17102,17103],{"class":3418,"line":3539},[3416,17104,17090],{},[3416,17106,17107],{"class":3418,"line":3545},[3416,17108,17109],{},"      Елементи ord-001 та ord-003\n",[3416,17111,17112],{"class":3418,"line":3551},[3416,17113,17114],{},"      повністю ігноруються індексом\n",[3416,17116,17117],{"class":3418,"line":3557},[3416,17118,3501],{},[3416,17120,17121],{"class":3418,"line":3563},[3416,17122,3507],{},[3416,17124,17125],{"class":3418,"line":3569},[3416,17126,3441],{"emptyLinePlaceholder":3440},[3416,17128,17129],{"class":3418,"line":3574},[3416,17130,17131],{},"O2 -right-> GSI : \"Проектується (атрибут наявний)\"\n",[3416,17133,17134],{"class":3418,"line":3579},[3416,17135,17136],{},"O4 -right-> GSI : \"Проектується (атрибут наявний)\"\n",[3416,17138,17139],{"class":3418,"line":3584},[3416,17140,17141],{},"O1 ..> GSI : \"Не проектується\"\n",[3416,17143,17144],{"class":3418,"line":3590},[3416,17145,17146],{},"O3 ..> GSI : \"Не проектується\"\n",[3416,17148,17149],{"class":3418,"line":3596},[3416,17150,3441],{"emptyLinePlaceholder":3440},[3416,17152,17153],{"class":3418,"line":3602},[3416,17154,16895],{},[3416,17156,17157],{"class":3418,"line":3608},[3416,17158,17159],{},"  Запит (Query): NeedsProcessing = 'true'\n",[3416,17161,17162],{"class":3418,"line":3614},[3416,17163,17164],{},"  * Отримує 2 елементи замість сканування 1 млн\n",[3416,17166,17167],{"class":3418,"line":3620},[3416,17168,17169],{},"  * При оновленні статусу видаляємо NeedsProcessing\n",[3416,17171,17172],{"class":3418,"line":3626},[3416,17173,17174],{},"  * Елемент автоматично видаляється з GSI\n",[3416,17176,17177],{"class":3418,"line":3631},[3416,17178,5088],{},[3416,17180,17181],{"class":3418,"line":3636},[3416,17182,3718],{},[3727,17184,17186],{"id":17185},"додавання-gsi-до-існуючої-таблиці-та-фонове-заповнення-backfilling","Додавання GSI до існуючої таблиці та фонове заповнення (Backfilling)",[3353,17188,17189],{},"На відміну від локальних індексів (LSI), глобальні індекси (GSI) є динамічними сутностями. Їх можна створювати, оновлювати або видаляти на будь-му етапі життєвого циклу таблиці, навіть якщо вона містить мільярди записів.",[4584,17191,17193],{"id":17192},"процес-онлайн-індексації-та-фонового-заповнення-backfilling","Процес онлайн-індексації та фонового заповнення (Backfilling)",[3353,17195,17196],{},"Створення GSI на існуючій таблиці є складною розподіленою операцією, яка виконується повністю у фоновому режимі:",[3374,17198,17199,17213,17219,17225],{},[3377,17200,17201,17204,17205,17208,17209,17212],{},[3363,17202,17203],{},"Створення метаданих (State: CREATING):"," Після виклику ",[3413,17206,17207],{},"UpdateTable"," статус індексу переходить у ",[3413,17210,17211],{},"CREATING",". DynamoDB виділяє фізичні ресурси (storage nodes) для нової партиційної структури індексу.",[3377,17214,17215,17218],{},[3363,17216,17217],{},"Фаза фонового сканування та заповнення (Backfilling phase):"," DynamoDB автоматично запускає фоновий процес сканування основної таблиці. Кожен знайдений елемент, що містить ключові атрибути GSI, проектується та записується в індекс.",[3377,17220,17221,17224],{},[3363,17222,17223],{},"Синхронізація дельти (Catch-up phase):"," Одночасно з заповненням історичними даними, всі нові операції запису, які виконуються клієнтами в цей момент до основної таблиці, автоматично буферизуються та реплікуються в новий індекс.",[3377,17226,17227,17230,17231,17233],{},[3363,17228,17229],{},"Активація (State: ACTIVE):"," Після завершення реплікації дельти статус індексу змінюється на ",[3413,17232,4795],{},", і він стає доступним для виконання запитів читання.",[4584,17235,17237],{"id":17236},"розрахунок-rcuwcu-під-час-backfilling","Розрахунок RCU\u002FWCU під час Backfilling",[3353,17239,17240],{},"Процес створення індексу створює додаткове навантаження на пропускну здатність:",[4488,17242,17243,17250],{},[3377,17244,17245,17246,17249],{},"Фонове сканування основної таблиці споживає її ",[3363,17247,17248],{},"власні RCU"," (AWS намагається виконувати це з мінімальним пріоритетом, щоб не заважати основному бізнес-трафіку).",[3377,17251,17252,17253,17256],{},"Запис даних у новий індекс споживає ",[3363,17254,17255],{},"WCU новоствореного GSI",". Якщо для GSI встановлено занижене значення WCU, процес заповнення триватиме значно довше або взагалі тимчасово призупиниться.",[6308,17258,17259,17422,17852],{},[6311,17260,17261],{"label":6313},[3406,17262,17264],{"className":6316,"code":17263,"language":6318,"meta":3411,"style":3411},"# ── Додавання GSI SessionsByIp до існуючої таблиці UserSessions ──────────────\naws dynamodb update-table \\\n    --table-name UserSessions \\\n    --attribute-definitions \\\n        AttributeName=IpAddress,AttributeType=S \\\n        AttributeName=CreatedAt,AttributeType=S \\\n    --global-secondary-index-updates '[{\n        \"Create\": {\n            \"IndexName\": \"SessionsByIp\",\n            \"KeySchema\": [\n                {\"AttributeName\": \"IpAddress\", \"KeyType\": \"HASH\"},\n                {\"AttributeName\": \"CreatedAt\", \"KeyType\": \"RANGE\"}\n            ],\n            \"Projection\": {\n                \"ProjectionType\": \"INCLUDE\",\n                \"NonKeyAttributes\": [\"UserId\", \"IsActive\"]\n            }\n        }\n    }]' \\\n    --region eu-central-1\n\n# ── Моніторинг статусу створення індексу ─────────────────────────────────────\naws dynamodb describe-table \\\n    --table-name UserSessions \\\n    --region eu-central-1 \\\n    --query \"Table.GlobalSecondaryIndexes[*].{Name:IndexName, Status:IndexStatus}\"\n",[3413,17265,17266,17271,17282,17290,17296,17303,17310,17318,17323,17328,17332,17337,17342,17346,17350,17354,17359,17363,17367,17374,17380,17384,17389,17399,17407,17415],{"__ignoreMap":3411},[3416,17267,17268],{"class":3418,"line":3419},[3416,17269,17270],{"class":3789},"# ── Додавання GSI SessionsByIp до існуючої таблиці UserSessions ──────────────\n",[3416,17272,17273,17275,17277,17280],{"class":3418,"line":3425},[3416,17274,6331],{"class":6330},[3416,17276,6334],{"class":3808},[3416,17278,17279],{"class":3808}," update-table",[3416,17281,6341],{"class":6340},[3416,17283,17284,17286,17288],{"class":3418,"line":3431},[3416,17285,6346],{"class":4368},[3416,17287,6349],{"class":3808},[3416,17289,6341],{"class":6340},[3416,17291,17292,17294],{"class":3418,"line":3437},[3416,17293,10711],{"class":4368},[3416,17295,6341],{"class":6340},[3416,17297,17298,17301],{"class":3418,"line":3444},[3416,17299,17300],{"class":3808},"        AttributeName=IpAddress,AttributeType=S",[3416,17302,6341],{"class":6340},[3416,17304,17305,17308],{"class":3418,"line":3450},[3416,17306,17307],{"class":3808},"        AttributeName=CreatedAt,AttributeType=S",[3416,17309,6341],{"class":6340},[3416,17311,17312,17315],{"class":3418,"line":3456},[3416,17313,17314],{"class":4368},"    --global-secondary-index-updates",[3416,17316,17317],{"class":3808}," '[{\n",[3416,17319,17320],{"class":3418,"line":3462},[3416,17321,17322],{"class":3808},"        \"Create\": {\n",[3416,17324,17325],{"class":3418,"line":3468},[3416,17326,17327],{"class":3808},"            \"IndexName\": \"SessionsByIp\",\n",[3416,17329,17330],{"class":3418,"line":3474},[3416,17331,15342],{"class":3808},[3416,17333,17334],{"class":3418,"line":3480},[3416,17335,17336],{"class":3808},"                {\"AttributeName\": \"IpAddress\", \"KeyType\": \"HASH\"},\n",[3416,17338,17339],{"class":3418,"line":3486},[3416,17340,17341],{"class":3808},"                {\"AttributeName\": \"CreatedAt\", \"KeyType\": \"RANGE\"}\n",[3416,17343,17344],{"class":3418,"line":3492},[3416,17345,15357],{"class":3808},[3416,17347,17348],{"class":3418,"line":3498},[3416,17349,15362],{"class":3808},[3416,17351,17352],{"class":3418,"line":3504},[3416,17353,15367],{"class":3808},[3416,17355,17356],{"class":3418,"line":3510},[3416,17357,17358],{"class":3808},"                \"NonKeyAttributes\": [\"UserId\", \"IsActive\"]\n",[3416,17360,17361],{"class":3418,"line":3515},[3416,17362,8815],{"class":3808},[3416,17364,17365],{"class":3418,"line":3521},[3416,17366,8533],{"class":3808},[3416,17368,17369,17372],{"class":3418,"line":3527},[3416,17370,17371],{"class":3808},"    }]'",[3416,17373,6341],{"class":6340},[3416,17375,17376,17378],{"class":3418,"line":3533},[3416,17377,6366],{"class":4368},[3416,17379,6369],{"class":3808},[3416,17381,17382],{"class":3418,"line":3539},[3416,17383,3441],{"emptyLinePlaceholder":3440},[3416,17385,17386],{"class":3418,"line":3545},[3416,17387,17388],{"class":3789},"# ── Моніторинг статусу створення індексу ─────────────────────────────────────\n",[3416,17390,17391,17393,17395,17397],{"class":3418,"line":3551},[3416,17392,6331],{"class":6330},[3416,17394,6334],{"class":3808},[3416,17396,11374],{"class":3808},[3416,17398,6341],{"class":6340},[3416,17400,17401,17403,17405],{"class":3418,"line":3557},[3416,17402,6346],{"class":4368},[3416,17404,6349],{"class":3808},[3416,17406,6341],{"class":6340},[3416,17408,17409,17411,17413],{"class":3418,"line":3563},[3416,17410,6366],{"class":4368},[3416,17412,11391],{"class":3808},[3416,17414,6341],{"class":6340},[3416,17416,17417,17419],{"class":3418,"line":3569},[3416,17418,11398],{"class":4368},[3416,17420,17421],{"class":3808}," \"Table.GlobalSecondaryIndexes[*].{Name:IndexName, Status:IndexStatus}\"\n",[6311,17423,17424],{"label":6372},[3406,17425,17427],{"className":6375,"code":17426,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nvar client = new AmazonDynamoDBClient();\n\n\u002F\u002F ── Додавання GSI (SessionsByIp) до існуючої таблиці (UserSessions) ──────────\nawait client.UpdateTableAsync(new UpdateTableRequest\n{\n    TableName = \"UserSessions\",\n    AttributeDefinitions = new List\u003CAttributeDefinition>\n    {\n        new() { AttributeName = \"IpAddress\", AttributeType = ScalarAttributeType.S },\n        new() { AttributeName = \"CreatedAt\", AttributeType = ScalarAttributeType.S }\n    },\n    GlobalSecondaryIndexUpdates = new List\u003CGlobalSecondaryIndexUpdate>\n    {\n        new()\n        {\n            Create = new CreateGlobalSecondaryIndexAction\n            {\n                IndexName = \"SessionsByIp\",\n                KeySchema = new List\u003CKeySchemaElement>\n                {\n                    new() { AttributeName = \"IpAddress\", KeyType = KeyType.HASH },\n                    new() { AttributeName = \"CreatedAt\", KeyType = KeyType.RANGE }\n                },\n                Projection = new Projection\n                {\n                    ProjectionType = ProjectionType.INCLUDE,\n                    NonKeyAttributes = new List\u003Cstring> { \"UserId\", \"IsActive\" }\n                },\n                ProvisionedThroughput = new ProvisionedThroughput\n                {\n                    ReadCapacityUnits = 50,\n                    WriteCapacityUnits = 50\n                }\n            }\n        }\n    }\n});\n",[3413,17428,17429,17444,17461,17465,17479,17483,17488,17506,17510,17520,17536,17540,17567,17593,17597,17615,17619,17626,17630,17642,17646,17658,17675,17679,17705,17731,17735,17746,17750,17765,17790,17794,17806,17810,17822,17832,17836,17840,17844,17848],{"__ignoreMap":3411},[3416,17430,17431,17434,17437,17439,17442],{"class":3418,"line":3419},[3416,17432,17433],{"class":11427},"using",[3416,17435,17436],{"class":6397}," Amazon",[3416,17438,4043],{"class":3795},[3416,17440,17441],{"class":6397},"DynamoDBv2",[3416,17443,11594],{"class":3795},[3416,17445,17446,17448,17450,17452,17454,17456,17459],{"class":3418,"line":3425},[3416,17447,17433],{"class":11427},[3416,17449,17436],{"class":6397},[3416,17451,4043],{"class":3795},[3416,17453,17441],{"class":6397},[3416,17455,4043],{"class":3795},[3416,17457,17458],{"class":6397},"Model",[3416,17460,11594],{"class":3795},[3416,17462,17463],{"class":3418,"line":3431},[3416,17464,3441],{"emptyLinePlaceholder":3440},[3416,17466,17467,17469,17471,17473,17475,17477],{"class":3418,"line":3437},[3416,17468,6384],{"class":4368},[3416,17470,6388],{"class":6387},[3416,17472,6391],{"class":3795},[3416,17474,6394],{"class":4368},[3416,17476,6398],{"class":6397},[3416,17478,6401],{"class":3795},[3416,17480,17481],{"class":3418,"line":3444},[3416,17482,3441],{"emptyLinePlaceholder":3440},[3416,17484,17485],{"class":3418,"line":3450},[3416,17486,17487],{"class":3789},"\u002F\u002F ── Додавання GSI (SessionsByIp) до існуючої таблиці (UserSessions) ──────────\n",[3416,17489,17490,17492,17494,17496,17499,17501,17503],{"class":3418,"line":3456},[3416,17491,6413],{"class":4368},[3416,17493,6388],{"class":6387},[3416,17495,4043],{"class":3795},[3416,17497,17498],{"class":6330},"UpdateTableAsync",[3416,17500,6423],{"class":3795},[3416,17502,6394],{"class":4368},[3416,17504,17505],{"class":6397}," UpdateTableRequest\n",[3416,17507,17508],{"class":3418,"line":3462},[3416,17509,3796],{"class":3795},[3416,17511,17512,17514,17516,17518],{"class":3418,"line":3468},[3416,17513,6437],{"class":6387},[3416,17515,6391],{"class":3795},[3416,17517,6442],{"class":3808},[3416,17519,3812],{"class":3795},[3416,17521,17522,17524,17526,17528,17530,17532,17534],{"class":3418,"line":3474},[3416,17523,10828],{"class":6387},[3416,17525,6391],{"class":3795},[3416,17527,6394],{"class":4368},[3416,17529,8640],{"class":6397},[3416,17531,5861],{"class":3795},[3416,17533,10839],{"class":6397},[3416,17535,6469],{"class":3795},[3416,17537,17538],{"class":3418,"line":3480},[3416,17539,6474],{"class":3795},[3416,17541,17542,17544,17547,17549,17551,17553,17555,17557,17559,17561,17563,17565],{"class":3418,"line":3486},[3416,17543,9886],{"class":4368},[3416,17545,17546],{"class":3795},"() { ",[3416,17548,10857],{"class":6387},[3416,17550,6391],{"class":3795},[3416,17552,12346],{"class":3808},[3416,17554,4384],{"class":3795},[3416,17556,10866],{"class":6387},[3416,17558,6391],{"class":3795},[3416,17560,10871],{"class":6387},[3416,17562,4043],{"class":3795},[3416,17564,6495],{"class":6387},[3416,17566,8915],{"class":3795},[3416,17568,17569,17571,17573,17575,17577,17579,17581,17583,17585,17587,17589,17591],{"class":3418,"line":3492},[3416,17570,9886],{"class":4368},[3416,17572,17546],{"class":3795},[3416,17574,10857],{"class":6387},[3416,17576,6391],{"class":3795},[3416,17578,6815],{"class":3808},[3416,17580,4384],{"class":3795},[3416,17582,10866],{"class":6387},[3416,17584,6391],{"class":3795},[3416,17586,10871],{"class":6387},[3416,17588,4043],{"class":3795},[3416,17590,6495],{"class":6387},[3416,17592,8948],{"class":3795},[3416,17594,17595],{"class":3418,"line":3498},[3416,17596,4442],{"class":3795},[3416,17598,17599,17602,17604,17606,17608,17610,17613],{"class":3418,"line":3504},[3416,17600,17601],{"class":6387},"    GlobalSecondaryIndexUpdates",[3416,17603,6391],{"class":3795},[3416,17605,6394],{"class":4368},[3416,17607,8640],{"class":6397},[3416,17609,5861],{"class":3795},[3416,17611,17612],{"class":6397},"GlobalSecondaryIndexUpdate",[3416,17614,6469],{"class":3795},[3416,17616,17617],{"class":3418,"line":3510},[3416,17618,6474],{"class":3795},[3416,17620,17621,17623],{"class":3418,"line":3515},[3416,17622,9886],{"class":4368},[3416,17624,17625],{"class":3795},"()\n",[3416,17627,17628],{"class":3418,"line":3521},[3416,17629,8611],{"class":3795},[3416,17631,17632,17635,17637,17639],{"class":3418,"line":3527},[3416,17633,17634],{"class":6387},"            Create",[3416,17636,6391],{"class":3795},[3416,17638,6394],{"class":4368},[3416,17640,17641],{"class":6397}," CreateGlobalSecondaryIndexAction\n",[3416,17643,17644],{"class":3418,"line":3533},[3416,17645,8628],{"class":3795},[3416,17647,17648,17651,17653,17656],{"class":3418,"line":3539},[3416,17649,17650],{"class":6387},"                IndexName",[3416,17652,6391],{"class":3795},[3416,17654,17655],{"class":3808},"\"SessionsByIp\"",[3416,17657,3812],{"class":3795},[3416,17659,17660,17663,17665,17667,17669,17671,17673],{"class":3418,"line":3545},[3416,17661,17662],{"class":6387},"                KeySchema",[3416,17664,6391],{"class":3795},[3416,17666,6394],{"class":4368},[3416,17668,8640],{"class":6397},[3416,17670,5861],{"class":3795},[3416,17672,10925],{"class":6397},[3416,17674,6469],{"class":3795},[3416,17676,17677],{"class":3418,"line":3551},[3416,17678,8661],{"class":3795},[3416,17680,17681,17683,17685,17687,17689,17691,17693,17695,17697,17699,17701,17703],{"class":3418,"line":3557},[3416,17682,8666],{"class":4368},[3416,17684,17546],{"class":3795},[3416,17686,10857],{"class":6387},[3416,17688,6391],{"class":3795},[3416,17690,12346],{"class":3808},[3416,17692,4384],{"class":3795},[3416,17694,10951],{"class":6387},[3416,17696,6391],{"class":3795},[3416,17698,10951],{"class":6387},[3416,17700,4043],{"class":3795},[3416,17702,10960],{"class":6387},[3416,17704,8915],{"class":3795},[3416,17706,17707,17709,17711,17713,17715,17717,17719,17721,17723,17725,17727,17729],{"class":3418,"line":3563},[3416,17708,8666],{"class":4368},[3416,17710,17546],{"class":3795},[3416,17712,10857],{"class":6387},[3416,17714,6391],{"class":3795},[3416,17716,6815],{"class":3808},[3416,17718,4384],{"class":3795},[3416,17720,10951],{"class":6387},[3416,17722,6391],{"class":3795},[3416,17724,10951],{"class":6387},[3416,17726,4043],{"class":3795},[3416,17728,10989],{"class":6387},[3416,17730,8948],{"class":3795},[3416,17732,17733],{"class":3418,"line":3569},[3416,17734,9344],{"class":3795},[3416,17736,17737,17740,17742,17744],{"class":3418,"line":3574},[3416,17738,17739],{"class":6387},"                Projection",[3416,17741,6391],{"class":3795},[3416,17743,6394],{"class":4368},[3416,17745,15783],{"class":6397},[3416,17747,17748],{"class":3418,"line":3579},[3416,17749,8661],{"class":3795},[3416,17751,17752,17755,17757,17759,17761,17763],{"class":3418,"line":3584},[3416,17753,17754],{"class":6387},"                    ProjectionType",[3416,17756,6391],{"class":3795},[3416,17758,15797],{"class":6387},[3416,17760,4043],{"class":3795},[3416,17762,15082],{"class":6387},[3416,17764,3812],{"class":3795},[3416,17766,17767,17770,17772,17774,17776,17778,17780,17782,17784,17786,17788],{"class":3418,"line":3590},[3416,17768,17769],{"class":6387},"                    NonKeyAttributes",[3416,17771,6391],{"class":3795},[3416,17773,6394],{"class":4368},[3416,17775,8640],{"class":6397},[3416,17777,5861],{"class":3795},[3416,17779,6461],{"class":4368},[3416,17781,15821],{"class":3795},[3416,17783,6482],{"class":3808},[3416,17785,4384],{"class":3795},[3416,17787,6839],{"class":3808},[3416,17789,8948],{"class":3795},[3416,17791,17792],{"class":3418,"line":3596},[3416,17793,9344],{"class":3795},[3416,17795,17796,17799,17801,17803],{"class":3418,"line":3602},[3416,17797,17798],{"class":6387},"                ProvisionedThroughput",[3416,17800,6391],{"class":3795},[3416,17802,6394],{"class":4368},[3416,17804,17805],{"class":6397}," ProvisionedThroughput\n",[3416,17807,17808],{"class":3418,"line":3608},[3416,17809,8661],{"class":3795},[3416,17811,17812,17815,17817,17820],{"class":3418,"line":3614},[3416,17813,17814],{"class":6387},"                    ReadCapacityUnits",[3416,17816,6391],{"class":3795},[3416,17818,17819],{"class":3870},"50",[3416,17821,3812],{"class":3795},[3416,17823,17824,17827,17829],{"class":3418,"line":3620},[3416,17825,17826],{"class":6387},"                    WriteCapacityUnits",[3416,17828,6391],{"class":3795},[3416,17830,17831],{"class":3870},"50\n",[3416,17833,17834],{"class":3418,"line":3626},[3416,17835,8810],{"class":3795},[3416,17837,17838],{"class":3418,"line":3631},[3416,17839,8815],{"class":3795},[3416,17841,17842],{"class":3418,"line":3636},[3416,17843,8533],{"class":3795},[3416,17845,17846],{"class":3418,"line":3641},[3416,17847,4167],{"class":3795},[3416,17849,17850],{"class":3418,"line":3647},[3416,17851,6537],{"class":3795},[6311,17853,17854],{"label":6540},[3406,17855,17857],{"className":6543,"code":17856,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n$attrIp        = New-DDBAttributeDefinition -AttributeName IpAddress -AttributeType S\n$attrCreatedAt = New-DDBAttributeDefinition -AttributeName CreatedAt -AttributeType S\n\n$gsiKeyIp        = New-DDBKeySchemaElement -AttributeName IpAddress -KeyType HASH\n$gsiKeyCreatedAt = New-DDBKeySchemaElement -AttributeName CreatedAt -KeyType RANGE\n\n$gsiProjection = [Amazon.DynamoDBv2.Model.Projection]@{\n    ProjectionType   = 'INCLUDE'\n    NonKeyAttributes = @('UserId', 'IsActive')\n}\n\n$gsiCreate = [Amazon.DynamoDBv2.Model.GlobalSecondaryIndexUpdate]@{\n    Create = [Amazon.DynamoDBv2.Model.CreateGlobalSecondaryIndexAction]@{\n        IndexName  = 'SessionsByIp'\n        KeySchema  = @($gsiKeyIp, $gsiKeyCreatedAt)\n        Projection = $gsiProjection\n    }\n}\n\nUpdate-DDBTable `\n    -TableName                     UserSessions `\n    -AttributeDefinition           @($attrIp, $attrCreatedAt) `\n    -GlobalSecondaryIndexUpdate    @($gsiCreate) `\n    -Region                        eu-central-1\n\n# ── Перевірка статусу створення індексу ──────────────────────────────────────\n(Get-DDBTable -TableName UserSessions -Region eu-central-1).GlobalSecondaryIndexes |\n    Select-Object IndexName, IndexStatus\n",[3413,17858,17859,17865,17869,17881,17893,17897,17909,17921,17925,17940,17948,17967,17971,17975,17991,18007,18017,18036,18046,18050,18054,18058,18065,18070,18087,18100,18107,18111,18116,18129],{"__ignoreMap":3411},[3416,17860,17861,17863],{"class":3418,"line":3419},[3416,17862,12967],{"class":6330},[3416,17864,12970],{"class":3795},[3416,17866,17867],{"class":3418,"line":3425},[3416,17868,3441],{"emptyLinePlaceholder":3440},[3416,17870,17871,17874,17876,17878],{"class":3418,"line":3431},[3416,17872,17873],{"class":6387},"$attrIp",[3416,17875,7923],{"class":3795},[3416,17877,11049],{"class":6330},[3416,17879,17880],{"class":3795}," -AttributeName IpAddress -AttributeType S\n",[3416,17882,17883,17886,17888,17890],{"class":3418,"line":3437},[3416,17884,17885],{"class":6387},"$attrCreatedAt",[3416,17887,6391],{"class":3795},[3416,17889,11049],{"class":6330},[3416,17891,17892],{"class":3795}," -AttributeName CreatedAt -AttributeType S\n",[3416,17894,17895],{"class":3418,"line":3444},[3416,17896,3441],{"emptyLinePlaceholder":3440},[3416,17898,17899,17902,17904,17906],{"class":3418,"line":3450},[3416,17900,17901],{"class":6387},"$gsiKeyIp",[3416,17903,7923],{"class":3795},[3416,17905,11078],{"class":6330},[3416,17907,17908],{"class":3795}," -AttributeName IpAddress -KeyType HASH\n",[3416,17910,17911,17914,17916,17918],{"class":3418,"line":3456},[3416,17912,17913],{"class":6387},"$gsiKeyCreatedAt",[3416,17915,6391],{"class":3795},[3416,17917,11078],{"class":6330},[3416,17919,17920],{"class":3795}," -AttributeName CreatedAt -KeyType RANGE\n",[3416,17922,17923],{"class":3418,"line":3462},[3416,17924,3441],{"emptyLinePlaceholder":3440},[3416,17926,17927,17930,17932,17934,17936,17938],{"class":3418,"line":3468},[3416,17928,17929],{"class":6387},"$gsiProjection",[3416,17931,7274],{"class":3795},[3416,17933,15966],{"class":4368},[3416,17935,7280],{"class":3795},[3416,17937,6561],{"class":4368},[3416,17939,3796],{"class":3795},[3416,17941,17942,17944,17946],{"class":3418,"line":3474},[3416,17943,15977],{"class":6387},[3416,17945,7374],{"class":3795},[3416,17947,15982],{"class":3808},[3416,17949,17950,17952,17954,17956,17958,17961,17963,17965],{"class":3418,"line":3480},[3416,17951,15987],{"class":6387},[3416,17953,6391],{"class":3795},[3416,17955,6561],{"class":4368},[3416,17957,6423],{"class":3795},[3416,17959,17960],{"class":3808},"'UserId'",[3416,17962,4384],{"class":3795},[3416,17964,15996],{"class":3808},[3416,17966,9656],{"class":3795},[3416,17968,17969],{"class":3418,"line":3486},[3416,17970,3507],{"class":3795},[3416,17972,17973],{"class":3418,"line":3492},[3416,17974,3441],{"emptyLinePlaceholder":3440},[3416,17976,17977,17980,17982,17985,17987,17989],{"class":3418,"line":3498},[3416,17978,17979],{"class":6387},"$gsiCreate",[3416,17981,7274],{"class":3795},[3416,17983,17984],{"class":4368},"Amazon.DynamoDBv2.Model.GlobalSecondaryIndexUpdate",[3416,17986,7280],{"class":3795},[3416,17988,6561],{"class":4368},[3416,17990,3796],{"class":3795},[3416,17992,17993,17996,17998,18001,18003,18005],{"class":3418,"line":3504},[3416,17994,17995],{"class":6387},"    Create",[3416,17997,7274],{"class":3795},[3416,17999,18000],{"class":4368},"Amazon.DynamoDBv2.Model.CreateGlobalSecondaryIndexAction",[3416,18002,7280],{"class":3795},[3416,18004,6561],{"class":4368},[3416,18006,3796],{"class":3795},[3416,18008,18009,18012,18014],{"class":3418,"line":3510},[3416,18010,18011],{"class":6387},"        IndexName",[3416,18013,6933],{"class":3795},[3416,18015,18016],{"class":3808},"'SessionsByIp'\n",[3416,18018,18019,18022,18024,18026,18028,18030,18032,18034],{"class":3418,"line":3515},[3416,18020,18021],{"class":6387},"        KeySchema",[3416,18023,6933],{"class":3795},[3416,18025,6561],{"class":4368},[3416,18027,6423],{"class":3795},[3416,18029,17901],{"class":6387},[3416,18031,4384],{"class":3795},[3416,18033,17913],{"class":6387},[3416,18035,9656],{"class":3795},[3416,18037,18038,18041,18043],{"class":3418,"line":3521},[3416,18039,18040],{"class":6387},"        Projection",[3416,18042,6391],{"class":3795},[3416,18044,18045],{"class":6387},"$gsiProjection\n",[3416,18047,18048],{"class":3418,"line":3527},[3416,18049,4167],{"class":3795},[3416,18051,18052],{"class":3418,"line":3533},[3416,18053,3507],{"class":3795},[3416,18055,18056],{"class":3418,"line":3539},[3416,18057,3441],{"emptyLinePlaceholder":3440},[3416,18059,18060,18063],{"class":3418,"line":3545},[3416,18061,18062],{"class":6330},"Update-DDBTable",[3416,18064,11105],{"class":3795},[3416,18066,18067],{"class":3418,"line":3551},[3416,18068,18069],{"class":3795},"    -TableName                     UserSessions `\n",[3416,18071,18072,18075,18077,18079,18081,18083,18085],{"class":3418,"line":3557},[3416,18073,18074],{"class":3795},"    -AttributeDefinition           ",[3416,18076,6561],{"class":4368},[3416,18078,6423],{"class":3795},[3416,18080,17873],{"class":6387},[3416,18082,4384],{"class":3795},[3416,18084,17885],{"class":6387},[3416,18086,11128],{"class":3795},[3416,18088,18089,18092,18094,18096,18098],{"class":3418,"line":3563},[3416,18090,18091],{"class":3795},"    -GlobalSecondaryIndexUpdate    ",[3416,18093,6561],{"class":4368},[3416,18095,6423],{"class":3795},[3416,18097,17979],{"class":6387},[3416,18099,11128],{"class":3795},[3416,18101,18102,18105],{"class":3418,"line":3569},[3416,18103,18104],{"class":3795},"    -Region                        eu-central-",[3416,18106,6614],{"class":3870},[3416,18108,18109],{"class":3418,"line":3574},[3416,18110,3441],{"emptyLinePlaceholder":3440},[3416,18112,18113],{"class":3418,"line":3579},[3416,18114,18115],{"class":3789},"# ── Перевірка статусу створення індексу ──────────────────────────────────────\n",[3416,18117,18118,18120,18122,18124,18126],{"class":3418,"line":3584},[3416,18119,6423],{"class":3795},[3416,18121,11670],{"class":6330},[3416,18123,11673],{"class":3795},[3416,18125,13510],{"class":3870},[3416,18127,18128],{"class":3795},").GlobalSecondaryIndexes |\n",[3416,18130,18131,18134],{"class":3418,"line":3590},[3416,18132,18133],{"class":6330},"    Select-Object",[3416,18135,18136],{"class":3795}," IndexName, IndexStatus\n",[11159,18138,18140],{"title":18139},"Вихідні дані опису таблиці при ініціалізації GSI",[3406,18141,18143],{"className":3780,"code":18142,"language":3782,"meta":3411,"style":3411},"[\n    {\n        \"Name\": \"SessionsByIp\",\n        \"Status\": \"CREATING\"\n    }\n]\n",[3413,18144,18145,18150,18154,18165,18175,18179],{"__ignoreMap":3411},[3416,18146,18147],{"class":3418,"line":3419},[3416,18148,18149],{"class":3795},"[\n",[3416,18151,18152],{"class":3418,"line":3425},[3416,18153,6474],{"class":3795},[3416,18155,18156,18159,18161,18163],{"class":3418,"line":3431},[3416,18157,18158],{"class":3801},"        \"Name\"",[3416,18160,3805],{"class":3795},[3416,18162,17655],{"class":3808},[3416,18164,3812],{"class":3795},[3416,18166,18167,18170,18172],{"class":3418,"line":3437},[3416,18168,18169],{"class":3801},"        \"Status\"",[3416,18171,3805],{"class":3795},[3416,18173,18174],{"class":3808},"\"CREATING\"\n",[3416,18176,18177],{"class":3418,"line":3444},[3416,18178,4167],{"class":3795},[3416,18180,18181],{"class":3418,"line":3450},[3416,18182,18183],{"class":3795},"]\n",[3727,18185,18187],{"id":18186},"виконання-запитів-query-через-gsi","Виконання запитів (Query) через GSI",[6308,18189,18190,18316,18533],{},[6311,18191,18192],{"label":6313},[3406,18193,18195],{"className":6316,"code":18194,"language":6318,"meta":3411,"style":3411},"# ── Пошук сесій за IP та часом створення ──────────────────────────────────────\naws dynamodb query \\\n    --table-name UserSessions \\\n    --index-name SessionsByIp \\\n    --key-condition-expression \"IpAddress = :ip AND CreatedAt >= :since\" \\\n    --expression-attribute-values '{\n        \":ip\":    {\"S\": \"203.0.113.42\"},\n        \":since\": {\"S\": \"2025-05-25T00:00:00Z\"}\n    }' \\\n    --region eu-central-1\n\n# ── Видалення глобального індексу GSI ─────────────────────────────────────────\naws dynamodb update-table \\\n    --table-name UserSessions \\\n    --global-secondary-index-updates '[{\n        \"Delete\": {\"IndexName\": \"SessionsByIp\"}\n    }]' \\\n    --region eu-central-1\n",[3413,18196,18197,18202,18212,18220,18229,18238,18244,18249,18254,18260,18266,18270,18275,18285,18293,18299,18304,18310],{"__ignoreMap":3411},[3416,18198,18199],{"class":3418,"line":3419},[3416,18200,18201],{"class":3789},"# ── Пошук сесій за IP та часом створення ──────────────────────────────────────\n",[3416,18203,18204,18206,18208,18210],{"class":3418,"line":3425},[3416,18205,6331],{"class":6330},[3416,18207,6334],{"class":3808},[3416,18209,7676],{"class":3808},[3416,18211,6341],{"class":6340},[3416,18213,18214,18216,18218],{"class":3418,"line":3431},[3416,18215,6346],{"class":4368},[3416,18217,6349],{"class":3808},[3416,18219,6341],{"class":6340},[3416,18221,18222,18224,18227],{"class":3418,"line":3437},[3416,18223,16188],{"class":4368},[3416,18225,18226],{"class":3808}," SessionsByIp",[3416,18228,6341],{"class":6340},[3416,18230,18231,18233,18236],{"class":3418,"line":3444},[3416,18232,7691],{"class":4368},[3416,18234,18235],{"class":3808}," \"IpAddress = :ip AND CreatedAt >= :since\"",[3416,18237,6341],{"class":6340},[3416,18239,18240,18242],{"class":3418,"line":3450},[3416,18241,7021],{"class":4368},[3416,18243,6661],{"class":3808},[3416,18245,18246],{"class":3418,"line":3456},[3416,18247,18248],{"class":3808},"        \":ip\":    {\"S\": \"203.0.113.42\"},\n",[3416,18250,18251],{"class":3418,"line":3462},[3416,18252,18253],{"class":3808},"        \":since\": {\"S\": \"2025-05-25T00:00:00Z\"}\n",[3416,18255,18256,18258],{"class":3418,"line":3468},[3416,18257,6686],{"class":3808},[3416,18259,6341],{"class":6340},[3416,18261,18262,18264],{"class":3418,"line":3474},[3416,18263,6366],{"class":4368},[3416,18265,6369],{"class":3808},[3416,18267,18268],{"class":3418,"line":3480},[3416,18269,3441],{"emptyLinePlaceholder":3440},[3416,18271,18272],{"class":3418,"line":3486},[3416,18273,18274],{"class":3789},"# ── Видалення глобального індексу GSI ─────────────────────────────────────────\n",[3416,18276,18277,18279,18281,18283],{"class":3418,"line":3492},[3416,18278,6331],{"class":6330},[3416,18280,6334],{"class":3808},[3416,18282,17279],{"class":3808},[3416,18284,6341],{"class":6340},[3416,18286,18287,18289,18291],{"class":3418,"line":3498},[3416,18288,6346],{"class":4368},[3416,18290,6349],{"class":3808},[3416,18292,6341],{"class":6340},[3416,18294,18295,18297],{"class":3418,"line":3504},[3416,18296,17314],{"class":4368},[3416,18298,17317],{"class":3808},[3416,18300,18301],{"class":3418,"line":3510},[3416,18302,18303],{"class":3808},"        \"Delete\": {\"IndexName\": \"SessionsByIp\"}\n",[3416,18305,18306,18308],{"class":3418,"line":3515},[3416,18307,17371],{"class":3808},[3416,18309,6341],{"class":6340},[3416,18311,18312,18314],{"class":3418,"line":3521},[3416,18313,6366],{"class":4368},[3416,18315,6369],{"class":3808},[6311,18317,18318],{"label":6372},[3406,18319,18321],{"className":6375,"code":18320,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nvar client = new AmazonDynamoDBClient();\n\n\u002F\u002F ── Пошук сесій за IP та датою через GSI ─────────────────────────────────────\nvar queryRequest = new QueryRequest\n{\n    TableName = \"UserSessions\",\n    IndexName = \"SessionsByIp\",\n    KeyConditionExpression = \"IpAddress = :ip AND CreatedAt >= :since\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":ip\", new AttributeValue { S = \"203.0.113.42\" } },\n        { \":since\", new AttributeValue { S = \"2025-05-25T00:00:00Z\" } }\n    }\n};\n\nvar response = await client.QueryAsync(queryRequest);\n",[3413,18322,18323,18335,18351,18355,18369,18373,18378,18391,18395,18405,18415,18426,18446,18450,18473,18497,18501,18506,18510],{"__ignoreMap":3411},[3416,18324,18325,18327,18329,18331,18333],{"class":3418,"line":3419},[3416,18326,17433],{"class":11427},[3416,18328,17436],{"class":6397},[3416,18330,4043],{"class":3795},[3416,18332,17441],{"class":6397},[3416,18334,11594],{"class":3795},[3416,18336,18337,18339,18341,18343,18345,18347,18349],{"class":3418,"line":3425},[3416,18338,17433],{"class":11427},[3416,18340,17436],{"class":6397},[3416,18342,4043],{"class":3795},[3416,18344,17441],{"class":6397},[3416,18346,4043],{"class":3795},[3416,18348,17458],{"class":6397},[3416,18350,11594],{"class":3795},[3416,18352,18353],{"class":3418,"line":3431},[3416,18354,3441],{"emptyLinePlaceholder":3440},[3416,18356,18357,18359,18361,18363,18365,18367],{"class":3418,"line":3437},[3416,18358,6384],{"class":4368},[3416,18360,6388],{"class":6387},[3416,18362,6391],{"class":3795},[3416,18364,6394],{"class":4368},[3416,18366,6398],{"class":6397},[3416,18368,6401],{"class":3795},[3416,18370,18371],{"class":3418,"line":3444},[3416,18372,3441],{"emptyLinePlaceholder":3440},[3416,18374,18375],{"class":3418,"line":3450},[3416,18376,18377],{"class":3789},"\u002F\u002F ── Пошук сесій за IP та датою через GSI ─────────────────────────────────────\n",[3416,18379,18380,18382,18385,18387,18389],{"class":3418,"line":3456},[3416,18381,6384],{"class":4368},[3416,18383,18384],{"class":6387}," queryRequest",[3416,18386,6391],{"class":3795},[3416,18388,6394],{"class":4368},[3416,18390,7755],{"class":6397},[3416,18392,18393],{"class":3418,"line":3462},[3416,18394,3796],{"class":3795},[3416,18396,18397,18399,18401,18403],{"class":3418,"line":3468},[3416,18398,6437],{"class":6387},[3416,18400,6391],{"class":3795},[3416,18402,6442],{"class":3808},[3416,18404,3812],{"class":3795},[3416,18406,18407,18409,18411,18413],{"class":3418,"line":3474},[3416,18408,16032],{"class":6387},[3416,18410,6391],{"class":3795},[3416,18412,17655],{"class":3808},[3416,18414,3812],{"class":3795},[3416,18416,18417,18419,18421,18424],{"class":3418,"line":3480},[3416,18418,7774],{"class":6387},[3416,18420,6391],{"class":3795},[3416,18422,18423],{"class":3808},"\"IpAddress = :ip AND CreatedAt >= :since\"",[3416,18425,3812],{"class":3795},[3416,18427,18428,18430,18432,18434,18436,18438,18440,18442,18444],{"class":3418,"line":3486},[3416,18429,7179],{"class":6387},[3416,18431,6391],{"class":3795},[3416,18433,6394],{"class":4368},[3416,18435,6456],{"class":6397},[3416,18437,5861],{"class":3795},[3416,18439,6461],{"class":4368},[3416,18441,4384],{"class":3795},[3416,18443,6466],{"class":6397},[3416,18445,6469],{"class":3795},[3416,18447,18448],{"class":3418,"line":3492},[3416,18449,6474],{"class":3795},[3416,18451,18452,18454,18457,18459,18461,18463,18465,18467,18469,18471],{"class":3418,"line":3498},[3416,18453,6479],{"class":3795},[3416,18455,18456],{"class":3808},"\":ip\"",[3416,18458,4384],{"class":3795},[3416,18460,6394],{"class":4368},[3416,18462,6489],{"class":6397},[3416,18464,6492],{"class":3795},[3416,18466,6495],{"class":6387},[3416,18468,6391],{"class":3795},[3416,18470,12361],{"class":3808},[3416,18472,6503],{"class":3795},[3416,18474,18475,18477,18480,18482,18484,18486,18488,18490,18492,18495],{"class":3418,"line":3504},[3416,18476,6479],{"class":3795},[3416,18478,18479],{"class":3808},"\":since\"",[3416,18481,4384],{"class":3795},[3416,18483,6394],{"class":4368},[3416,18485,6489],{"class":6397},[3416,18487,6492],{"class":3795},[3416,18489,6495],{"class":6387},[3416,18491,6391],{"class":3795},[3416,18493,18494],{"class":3808},"\"2025-05-25T00:00:00Z\"",[3416,18496,6528],{"class":3795},[3416,18498,18499],{"class":3418,"line":3510},[3416,18500,4167],{"class":3795},[3416,18502,18503],{"class":3418,"line":3515},[3416,18504,18505],{"class":3795},"};\n",[3416,18507,18508],{"class":3418,"line":3521},[3416,18509,3441],{"emptyLinePlaceholder":3440},[3416,18511,18512,18514,18516,18518,18520,18522,18524,18526,18528,18531],{"class":3418,"line":3527},[3416,18513,6384],{"class":4368},[3416,18515,6408],{"class":6387},[3416,18517,6391],{"class":3795},[3416,18519,6413],{"class":4368},[3416,18521,6388],{"class":6387},[3416,18523,4043],{"class":3795},[3416,18525,7748],{"class":6330},[3416,18527,6423],{"class":3795},[3416,18529,18530],{"class":6387},"queryRequest",[3416,18532,11465],{"class":3795},[6311,18534,18535],{"label":6540},[3406,18536,18538],{"className":6543,"code":18537,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n# ── Пошук сесій за IP та часом створення ──────────────────────────────────────\n$queryRequest = [Amazon.DynamoDBv2.Model.QueryRequest]@{\n    TableName              = 'UserSessions'\n    IndexName              = 'SessionsByIp'\n    KeyConditionExpression = 'IpAddress = :ip AND CreatedAt >= :since'\n    ExpressionAttributeValues = @{\n        ':ip'    = New-DDBEntry -S '203.0.113.42'\n        ':since' = New-DDBEntry -S '2025-05-25T00:00:00Z'\n    }\n}\n$result = Invoke-DDBQuery -QueryRequest $queryRequest -Region eu-central-1\n$result.Items\n\n# ── Видалення глобального індексу GSI ─────────────────────────────────────────\n$gsiDelete = [Amazon.DynamoDBv2.Model.GlobalSecondaryIndexUpdate]@{\n    Delete = [Amazon.DynamoDBv2.Model.DeleteGlobalSecondaryIndexAction]@{\n        IndexName = 'SessionsByIp'\n    }\n}\nUpdate-DDBTable -TableName UserSessions -GlobalSecondaryIndexUpdate @($gsiDelete) -Region eu-central-1\n",[3413,18539,18540,18546,18550,18554,18568,18576,18584,18593,18603,18616,18630,18634,18638,18655,18662,18666,18670,18685,18701,18709,18713,18717],{"__ignoreMap":3411},[3416,18541,18542,18544],{"class":3418,"line":3419},[3416,18543,12967],{"class":6330},[3416,18545,12970],{"class":3795},[3416,18547,18548],{"class":3418,"line":3425},[3416,18549,3441],{"emptyLinePlaceholder":3440},[3416,18551,18552],{"class":3418,"line":3431},[3416,18553,18201],{"class":3789},[3416,18555,18556,18558,18560,18562,18564,18566],{"class":3418,"line":3437},[3416,18557,7877],{"class":6387},[3416,18559,7274],{"class":3795},[3416,18561,7882],{"class":4368},[3416,18563,7280],{"class":3795},[3416,18565,6561],{"class":4368},[3416,18567,3796],{"class":3795},[3416,18569,18570,18572,18574],{"class":3418,"line":3444},[3416,18571,6437],{"class":6387},[3416,18573,13271],{"class":3795},[3416,18575,7293],{"class":3808},[3416,18577,18578,18580,18582],{"class":3418,"line":3450},[3416,18579,16032],{"class":6387},[3416,18581,13271],{"class":3795},[3416,18583,18016],{"class":3808},[3416,18585,18586,18588,18590],{"class":3418,"line":3456},[3416,18587,7774],{"class":6387},[3416,18589,6391],{"class":3795},[3416,18591,18592],{"class":3808},"'IpAddress = :ip AND CreatedAt >= :since'\n",[3416,18594,18595,18597,18599,18601],{"class":3418,"line":3462},[3416,18596,7179],{"class":6387},[3416,18598,6391],{"class":3795},[3416,18600,6561],{"class":4368},[3416,18602,3796],{"class":3795},[3416,18604,18605,18608,18610,18612,18614],{"class":3418,"line":3468},[3416,18606,18607],{"class":3808},"        ':ip'",[3416,18609,6571],{"class":3795},[3416,18611,6574],{"class":6330},[3416,18613,6577],{"class":3795},[3416,18615,13052],{"class":3808},[3416,18617,18618,18621,18623,18625,18627],{"class":3418,"line":3474},[3416,18619,18620],{"class":3808},"        ':since'",[3416,18622,6391],{"class":3795},[3416,18624,6574],{"class":6330},[3416,18626,6577],{"class":3795},[3416,18628,18629],{"class":3808},"'2025-05-25T00:00:00Z'\n",[3416,18631,18632],{"class":3418,"line":3480},[3416,18633,4167],{"class":3795},[3416,18635,18636],{"class":3418,"line":3486},[3416,18637,3507],{"class":3795},[3416,18639,18640,18643,18645,18647,18649,18651,18653],{"class":3418,"line":3492},[3416,18641,18642],{"class":6387},"$result",[3416,18644,6391],{"class":3795},[3416,18646,7956],{"class":6330},[3416,18648,7959],{"class":3795},[3416,18650,7877],{"class":6387},[3416,18652,6611],{"class":3795},[3416,18654,6614],{"class":3870},[3416,18656,18657,18659],{"class":3418,"line":3498},[3416,18658,18642],{"class":6387},[3416,18660,18661],{"class":6330},".Items\n",[3416,18663,18664],{"class":3418,"line":3504},[3416,18665,3441],{"emptyLinePlaceholder":3440},[3416,18667,18668],{"class":3418,"line":3510},[3416,18669,18274],{"class":3789},[3416,18671,18672,18675,18677,18679,18681,18683],{"class":3418,"line":3515},[3416,18673,18674],{"class":6387},"$gsiDelete",[3416,18676,7274],{"class":3795},[3416,18678,17984],{"class":4368},[3416,18680,7280],{"class":3795},[3416,18682,6561],{"class":4368},[3416,18684,3796],{"class":3795},[3416,18686,18687,18690,18692,18695,18697,18699],{"class":3418,"line":3521},[3416,18688,18689],{"class":6387},"    Delete",[3416,18691,7274],{"class":3795},[3416,18693,18694],{"class":4368},"Amazon.DynamoDBv2.Model.DeleteGlobalSecondaryIndexAction",[3416,18696,7280],{"class":3795},[3416,18698,6561],{"class":4368},[3416,18700,3796],{"class":3795},[3416,18702,18703,18705,18707],{"class":3418,"line":3527},[3416,18704,18011],{"class":6387},[3416,18706,6391],{"class":3795},[3416,18708,18016],{"class":3808},[3416,18710,18711],{"class":3418,"line":3533},[3416,18712,4167],{"class":3795},[3416,18714,18715],{"class":3418,"line":3539},[3416,18716,3507],{"class":3795},[3416,18718,18719,18721,18724,18726,18728,18730,18733],{"class":3418,"line":3545},[3416,18720,18062],{"class":6330},[3416,18722,18723],{"class":3795}," -TableName UserSessions -GlobalSecondaryIndexUpdate ",[3416,18725,6561],{"class":4368},[3416,18727,6423],{"class":3795},[3416,18729,18674],{"class":6387},[3416,18731,18732],{"class":3795},") -Region eu-central-",[3416,18734,6614],{"class":3870},[3720,18736],{},[3727,18738,18740],{"id":18739},"порівняльний-аналіз-local-secondary-index-та-global-secondary-index","Порівняльний аналіз Local Secondary Index та Global Secondary Index",[3353,18742,18743],{},"Для оптимального вибору індексу під конкретний сценарій використання зверніться до порівняльної таблиці:",[3756,18745,18746,18756],{},[4617,18747,18748],{},[4620,18749,18750,18752,18754],{},[4623,18751,6186],{"align":4625},[4623,18753,14753],{"align":4625},[4623,18755,16676],{"align":4625},[4657,18757,18758,18771,18783,18796,18809,18822,18835],{},[4620,18759,18760,18765,18768],{},[4662,18761,18762],{"align":4625},[3363,18763,18764],{},"Partition Key (HASH)",[4662,18766,18767],{"align":4625},"Має бути ідентичним Partition Key основної таблиці",[4662,18769,18770],{"align":4625},"Може бути будь-яким атрибутом таблиці",[4620,18772,18773,18778,18781],{},[4662,18774,18775],{"align":4625},[3363,18776,18777],{},"Sort Key (RANGE)",[4662,18779,18780],{"align":4625},"Будь-який атрибут основної таблиці",[4662,18782,18780],{"align":4625},[4620,18784,18785,18790,18793],{},[4662,18786,18787],{"align":4625},[3363,18788,18789],{},"Момент створення",[4662,18791,18792],{"align":4625},"Виключно під час створення таблиці",[4662,18794,18795],{"align":4625},"Будь-коли протягом життєвого циклу таблиці",[4620,18797,18798,18803,18806],{},[4662,18799,18800],{"align":4625},[3363,18801,18802],{},"Обмеження розміру",[4662,18804,18805],{"align":4625},"Ліміт у 10 GB на колекцію елементів (Item Collection)",[4662,18807,18808],{"align":4625},"Без лімітів (горизонтальне масштабування)",[4620,18810,18811,18816,18819],{},[4662,18812,18813],{"align":4625},[3363,18814,18815],{},"Пропускна здатність",[4662,18817,18818],{"align":4625},"Використовує RCU\u002FWCU основної таблиці",[4662,18820,18821],{"align":4625},"Вимагає окремого виділення RCU\u002FWCU для індексу",[4620,18823,18824,18829,18832],{},[4662,18825,18826],{"align":4625},[3363,18827,18828],{},"Модель консистентності",[4662,18830,18831],{"align":4625},"Strongly Consistent або Eventually Consistent читання",[4662,18833,18834],{"align":4625},"Виключно Eventually Consistent читання",[4620,18836,18837,18842,18845],{},[4662,18838,18839],{"align":4625},[3363,18840,18841],{},"Штраф вибірки (Fetch Penalty)",[4662,18843,18844],{"align":4625},"Дозволяє запитувати непроектовані атрибути (+1 RCU з основної таблиці)",[4662,18846,18847],{"align":4625},"Не підтримує автоматичне довантаження (запит провалюється)",[3720,18849],{},[3727,18851,18853],{"id":18852},"вибір-типу-індексу-decision-tree","Вибір типу індексу (Decision Tree)",[3403,18855,18856],{},[3406,18857,18859],{"className":3408,"code":18858,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Алгоритм вибору типу вторинного індексу\n\nstart\n\nif (Потрібен додатковий ключ для нового патерну запиту?) then (так)\n  if ( Partition Key має збігатися з основною таблицею?) then (так)\n    if (Загальний обсяг даних на один Partition Key перевищує 10 GB?) then (так)\n      :Використовувати GSI з тим самим Partition Key;\n      note right : Обхід ліміту розміру Item Collection\n      stop\n    else (ні)\n      if (Таблиця вже створена і знаходиться в експлуатації?) then (так)\n        :Використовувати GSI;\n        note right : LSI неможливо додати до наявної таблиці\n        stop\n      else (ні)\n        :Використовувати LSI\\n(Економія на окремій пропускній здатності + Strongly Consistent читання);\n        stop\n      endif\n    endif\n  else (ні)\n    :Використовувати GSI з новим Partition Key;\n    stop\n  endif\nelse (ні)\n  :Запит покривається основним ключем;\n  stop\nendif\n\n@enduml\n",[3413,18860,18861,18865,18869,18873,18877,18881,18886,18890,18895,18899,18904,18909,18914,18919,18924,18929,18934,18939,18944,18949,18954,18959,18964,18968,18973,18978,18983,18988,18993,18998,19003,19008,19013,19018,19022],{"__ignoreMap":3411},[3416,18862,18863],{"class":3418,"line":3419},[3416,18864,3422],{},[3416,18866,18867],{"class":3418,"line":3425},[3416,18868,16755],{},[3416,18870,18871],{"class":3418,"line":3431},[3416,18872,16760],{},[3416,18874,18875],{"class":3418,"line":3437},[3416,18876,16765],{},[3416,18878,18879],{"class":3418,"line":3444},[3416,18880,3441],{"emptyLinePlaceholder":3440},[3416,18882,18883],{"class":3418,"line":3450},[3416,18884,18885],{},"title Алгоритм вибору типу вторинного індексу\n",[3416,18887,18888],{"class":3418,"line":3456},[3416,18889,3441],{"emptyLinePlaceholder":3440},[3416,18891,18892],{"class":3418,"line":3462},[3416,18893,18894],{},"start\n",[3416,18896,18897],{"class":3418,"line":3468},[3416,18898,3441],{"emptyLinePlaceholder":3440},[3416,18900,18901],{"class":3418,"line":3474},[3416,18902,18903],{},"if (Потрібен додатковий ключ для нового патерну запиту?) then (так)\n",[3416,18905,18906],{"class":3418,"line":3480},[3416,18907,18908],{},"  if ( Partition Key має збігатися з основною таблицею?) then (так)\n",[3416,18910,18911],{"class":3418,"line":3486},[3416,18912,18913],{},"    if (Загальний обсяг даних на один Partition Key перевищує 10 GB?) then (так)\n",[3416,18915,18916],{"class":3418,"line":3492},[3416,18917,18918],{},"      :Використовувати GSI з тим самим Partition Key;\n",[3416,18920,18921],{"class":3418,"line":3498},[3416,18922,18923],{},"      note right : Обхід ліміту розміру Item Collection\n",[3416,18925,18926],{"class":3418,"line":3504},[3416,18927,18928],{},"      stop\n",[3416,18930,18931],{"class":3418,"line":3510},[3416,18932,18933],{},"    else (ні)\n",[3416,18935,18936],{"class":3418,"line":3515},[3416,18937,18938],{},"      if (Таблиця вже створена і знаходиться в експлуатації?) then (так)\n",[3416,18940,18941],{"class":3418,"line":3521},[3416,18942,18943],{},"        :Використовувати GSI;\n",[3416,18945,18946],{"class":3418,"line":3527},[3416,18947,18948],{},"        note right : LSI неможливо додати до наявної таблиці\n",[3416,18950,18951],{"class":3418,"line":3533},[3416,18952,18953],{},"        stop\n",[3416,18955,18956],{"class":3418,"line":3539},[3416,18957,18958],{},"      else (ні)\n",[3416,18960,18961],{"class":3418,"line":3545},[3416,18962,18963],{},"        :Використовувати LSI\\n(Економія на окремій пропускній здатності + Strongly Consistent читання);\n",[3416,18965,18966],{"class":3418,"line":3551},[3416,18967,18953],{},[3416,18969,18970],{"class":3418,"line":3557},[3416,18971,18972],{},"      endif\n",[3416,18974,18975],{"class":3418,"line":3563},[3416,18976,18977],{},"    endif\n",[3416,18979,18980],{"class":3418,"line":3569},[3416,18981,18982],{},"  else (ні)\n",[3416,18984,18985],{"class":3418,"line":3574},[3416,18986,18987],{},"    :Використовувати GSI з новим Partition Key;\n",[3416,18989,18990],{"class":3418,"line":3579},[3416,18991,18992],{},"    stop\n",[3416,18994,18995],{"class":3418,"line":3584},[3416,18996,18997],{},"  endif\n",[3416,18999,19000],{"class":3418,"line":3590},[3416,19001,19002],{},"else (ні)\n",[3416,19004,19005],{"class":3418,"line":3596},[3416,19006,19007],{},"  :Запит покривається основним ключем;\n",[3416,19009,19010],{"class":3418,"line":3602},[3416,19011,19012],{},"  stop\n",[3416,19014,19015],{"class":3418,"line":3608},[3416,19016,19017],{},"endif\n",[3416,19019,19020],{"class":3418,"line":3614},[3416,19021,3441],{"emptyLinePlaceholder":3440},[3416,19023,19024],{"class":3418,"line":3620},[3416,19025,3718],{},[3720,19027],{},[3348,19029,19031],{"id":19030},"практичний-приклад-проектування-індексів-для-e-commerce","Практичний приклад: проектування індексів для E-commerce",[3353,19033,19034,19035,19038],{},"У системах електронної комерції Single-Table Design є промисловим стандартом. Розглянемо проектування таблиці ",[3413,19036,19037],{},"Orders",", яка повинна ефективно обслуговувати чотири типи запитів.",[4584,19040,19042],{"id":19041},"вимоги-додатку-до-доступу-до-даних-access-patterns","Вимоги додатку до доступу до даних (Access Patterns):",[3374,19044,19045,19051,19060,19066],{},[3377,19046,19047,19050],{},[3363,19048,19049],{},"Запит 1:"," Отримання всіх замовлень конкретного клієнта, відсортованих за часом оформлення.",[3377,19052,19053,19056,19057,19059],{},[3363,19054,19055],{},"Запит 2:"," Отримання всіх замовлень у статусі ",[3413,19058,5298],{}," (очікують на обробку), відсортованих за часом оформлення.",[3377,19061,19062,19065],{},[3363,19063,19064],{},"Запит 3:"," Отримання всіх замовлень, що містять конкретний продукт.",[3377,19067,19068,19071],{},[3363,19069,19070],{},"Запит 4:"," Пошук замовлення клієнта у визначеному часовому діапазоні.",[4584,19073,19075],{"id":19074},"схема-проектування-ключів-та-індексів","Схема проектування ключів та індексів:",[4488,19077,19078,19096,19119],{},[3377,19079,19080,19083,19084,19087,19088,19090,19091,5167,19093,4043],{},[3363,19081,19082],{},"Основний ключ (Composite PK):"," Partition Key — ",[3413,19085,19086],{},"CustomerId",", Sort Key — ",[3413,19089,5206],{},". Це повністю покриває Запит 1 та Запит 4 за допомогою оператора ",[3413,19092,5911],{},[3413,19094,19095],{},"between",[3377,19097,19098,19101,19102,19104,19105,19107,19108,19111,19112,19115,19116,19118],{},[3363,19099,19100],{},"Індекс 1 (PendingOrdersByDate - Sparse GSI):"," Для Запиту 2 створюється розріджений індекс. ",[3413,19103,16995],{}," використовується як HASH (заповнюється значенням ",[3413,19106,5298],{}," лише для незавершених замовлень), а ",[3413,19109,19110],{},"OrderDateId"," — як RANGE. При зміні статусу на ",[3413,19113,19114],{},"PAID"," атрибут ",[3413,19117,16995],{}," видаляється, і замовлення зникає з індексу.",[3377,19120,19121,19124,19125,19128,19129,19131,19132,4043],{},[3363,19122,19123],{},"Індекс 2 (OrdersByProduct - GSI):"," Для Запиту 3 створюється індекс, де Partition Key — ",[3413,19126,19127],{},"ProductId_0"," (ідентифікатор першого продукту у кошику), а Sort Key — ",[3413,19130,19110],{}," з проекцією ",[3413,19133,15069],{},[3403,19135,19136],{},[3406,19137,19139],{"className":3408,"code":19138,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Проектування таблиці Orders та її індексів\n\nclass \"Таблиця Orders\" as T #E8F4FD {\n  .. Первинний ключ ..\n  + **CustomerId** (S) [PK]\n  + **OrderDate#OrderId** (S) [SK]\n  .. Атрибути ..\n  - OrderId (S)\n  - Status (S)\n  - TotalAmount (N)\n  - PendingStatus (S)  \u003C\u003Cлише для PENDING>>\n  - ProductId_0 (S) \u003C\u003Cперший продукт>>\n}\n\nnote right of T\n  **GSI 1: PendingOrdersByDate (Sparse)**\n  * HASH: PendingStatus\n  * RANGE: OrderDateId\n  * Projection: INCLUDE [CustomerId, TotalAmount]\n\n  **GSI 2: OrdersByProduct**\n  * HASH: ProductId_0\n  * RANGE: OrderDateId\n  * Projection: KEYS_ONLY\nend note\n@enduml\n",[3413,19140,19141,19145,19149,19153,19157,19161,19166,19170,19175,19180,19185,19190,19195,19200,19205,19210,19215,19220,19224,19228,19232,19237,19242,19247,19252,19256,19261,19266,19270,19275,19279],{"__ignoreMap":3411},[3416,19142,19143],{"class":3418,"line":3419},[3416,19144,3422],{},[3416,19146,19147],{"class":3418,"line":3425},[3416,19148,16755],{},[3416,19150,19151],{"class":3418,"line":3431},[3416,19152,16760],{},[3416,19154,19155],{"class":3418,"line":3437},[3416,19156,16765],{},[3416,19158,19159],{"class":3418,"line":3444},[3416,19160,3441],{"emptyLinePlaceholder":3440},[3416,19162,19163],{"class":3418,"line":3450},[3416,19164,19165],{},"title Проектування таблиці Orders та її індексів\n",[3416,19167,19168],{"class":3418,"line":3456},[3416,19169,3441],{"emptyLinePlaceholder":3440},[3416,19171,19172],{"class":3418,"line":3462},[3416,19173,19174],{},"class \"Таблиця Orders\" as T #E8F4FD {\n",[3416,19176,19177],{"class":3418,"line":3468},[3416,19178,19179],{},"  .. Первинний ключ ..\n",[3416,19181,19182],{"class":3418,"line":3474},[3416,19183,19184],{},"  + **CustomerId** (S) [PK]\n",[3416,19186,19187],{"class":3418,"line":3480},[3416,19188,19189],{},"  + **OrderDate#OrderId** (S) [SK]\n",[3416,19191,19192],{"class":3418,"line":3486},[3416,19193,19194],{},"  .. Атрибути ..\n",[3416,19196,19197],{"class":3418,"line":3492},[3416,19198,19199],{},"  - OrderId (S)\n",[3416,19201,19202],{"class":3418,"line":3498},[3416,19203,19204],{},"  - Status (S)\n",[3416,19206,19207],{"class":3418,"line":3504},[3416,19208,19209],{},"  - TotalAmount (N)\n",[3416,19211,19212],{"class":3418,"line":3510},[3416,19213,19214],{},"  - PendingStatus (S)  \u003C\u003Cлише для PENDING>>\n",[3416,19216,19217],{"class":3418,"line":3515},[3416,19218,19219],{},"  - ProductId_0 (S) \u003C\u003Cперший продукт>>\n",[3416,19221,19222],{"class":3418,"line":3521},[3416,19223,3507],{},[3416,19225,19226],{"class":3418,"line":3527},[3416,19227,3441],{"emptyLinePlaceholder":3440},[3416,19229,19230],{"class":3418,"line":3533},[3416,19231,10601],{},[3416,19233,19234],{"class":3418,"line":3539},[3416,19235,19236],{},"  **GSI 1: PendingOrdersByDate (Sparse)**\n",[3416,19238,19239],{"class":3418,"line":3545},[3416,19240,19241],{},"  * HASH: PendingStatus\n",[3416,19243,19244],{"class":3418,"line":3551},[3416,19245,19246],{},"  * RANGE: OrderDateId\n",[3416,19248,19249],{"class":3418,"line":3557},[3416,19250,19251],{},"  * Projection: INCLUDE [CustomerId, TotalAmount]\n",[3416,19253,19254],{"class":3418,"line":3563},[3416,19255,3441],{"emptyLinePlaceholder":3440},[3416,19257,19258],{"class":3418,"line":3569},[3416,19259,19260],{},"  **GSI 2: OrdersByProduct**\n",[3416,19262,19263],{"class":3418,"line":3574},[3416,19264,19265],{},"  * HASH: ProductId_0\n",[3416,19267,19268],{"class":3418,"line":3579},[3416,19269,19246],{},[3416,19271,19272],{"class":3418,"line":3584},[3416,19273,19274],{},"  * Projection: KEYS_ONLY\n",[3416,19276,19277],{"class":3418,"line":3590},[3416,19278,5088],{},[3416,19280,19281],{"class":3418,"line":3596},[3416,19282,3718],{},[3727,19284,19286],{"id":19285},"практична-реалізація-e-commerce-таблиці","Практична реалізація E-commerce таблиці",[6308,19288,19289,19695,20978],{},[6311,19290,19291],{"label":6313},[3406,19292,19294],{"className":6316,"code":19293,"language":6318,"meta":3411,"style":3411},"# ── Створення таблиці Orders з двома GSI ──────────────────────────────────────\naws dynamodb create-table \\\n    --table-name Orders \\\n    --attribute-definitions \\\n        AttributeName=CustomerId,AttributeType=S \\\n        AttributeName=OrderDateId,AttributeType=S \\\n        AttributeName=PendingStatus,AttributeType=S \\\n        AttributeName=ProductId_0,AttributeType=S \\\n    --key-schema \\\n        AttributeName=CustomerId,KeyType=HASH \\\n        AttributeName=OrderDateId,KeyType=RANGE \\\n    --global-secondary-indexes '[\n        {\n            \"IndexName\": \"PendingOrdersByDate\",\n            \"KeySchema\": [\n                {\"AttributeName\": \"PendingStatus\", \"KeyType\": \"HASH\"},\n                {\"AttributeName\": \"OrderDateId\",   \"KeyType\": \"RANGE\"}\n            ],\n            \"Projection\": {\n                \"ProjectionType\": \"INCLUDE\",\n                \"NonKeyAttributes\": [\"CustomerId\", \"TotalAmount\"]\n            }\n        },\n        {\n            \"IndexName\": \"OrdersByProduct\",\n            \"KeySchema\": [\n                {\"AttributeName\": \"ProductId_0\", \"KeyType\": \"HASH\"},\n                {\"AttributeName\": \"OrderDateId\", \"KeyType\": \"RANGE\"}\n            ],\n            \"Projection\": {\"ProjectionType\": \"KEYS_ONLY\"}\n        }\n    ]' \\\n    --billing-mode PAY_PER_REQUEST \\\n    --region eu-central-1\n\n# ── Запис нового PENDING замовлення (потрапляє в Sparse GSI) ──────────────────\naws dynamodb put-item \\\n    --table-name Orders \\\n    --item '{\n        \"CustomerId\":    {\"S\": \"cust-001\"},\n        \"OrderDateId\":   {\"S\": \"2025-06-01T10:00#ord-XYZ\"},\n        \"OrderId\":       {\"S\": \"ord-XYZ\"},\n        \"Status\":        {\"S\": \"PENDING\"},\n        \"PendingStatus\": {\"S\": \"PENDING\"},\n        \"TotalAmount\":   {\"N\": \"149.99\"},\n        \"ProductId_0\":   {\"S\": \"prod-laptop\"}\n    }' \\\n    --region eu-central-1\n\n# ── Оплата замовлення (видалення PendingStatus -> автоматично зникає з GSI) ────\naws dynamodb update-item \\\n    --table-name Orders \\\n    --key '{\"CustomerId\": {\"S\": \"cust-001\"}, \"OrderDateId\": {\"S\": \"2025-06-01T10:00#ord-XYZ\"}}' \\\n    --update-expression \"SET #s = :paid REMOVE PendingStatus\" \\\n    --expression-attribute-names '{\"#s\": \"Status\"}' \\\n    --expression-attribute-values '{\":paid\": {\"S\": \"PAID\"}}' \\\n    --region eu-central-1\n\n# ── Отримання активних PENDING замовлень через Sparse GSI ───────────────────────\naws dynamodb query \\\n    --table-name Orders \\\n    --index-name PendingOrdersByDate \\\n    --key-condition-expression \"PendingStatus = :p\" \\\n    --expression-attribute-values '{\":p\": {\"S\": \"PENDING\"}}' \\\n    --region eu-central-1\n",[3413,19295,19296,19301,19311,19320,19326,19333,19340,19347,19354,19360,19367,19374,19381,19385,19390,19394,19399,19404,19408,19412,19416,19421,19425,19429,19433,19438,19442,19447,19452,19456,19461,19465,19471,19479,19485,19489,19494,19504,19512,19518,19523,19528,19533,19538,19543,19548,19553,19559,19565,19569,19574,19584,19592,19601,19610,19620,19629,19635,19639,19644,19654,19662,19671,19680,19689],{"__ignoreMap":3411},[3416,19297,19298],{"class":3418,"line":3419},[3416,19299,19300],{"class":3789},"# ── Створення таблиці Orders з двома GSI ──────────────────────────────────────\n",[3416,19302,19303,19305,19307,19309],{"class":3418,"line":3425},[3416,19304,6331],{"class":6330},[3416,19306,6334],{"class":3808},[3416,19308,10696],{"class":3808},[3416,19310,6341],{"class":6340},[3416,19312,19313,19315,19318],{"class":3418,"line":3431},[3416,19314,6346],{"class":4368},[3416,19316,19317],{"class":3808}," Orders",[3416,19319,6341],{"class":6340},[3416,19321,19322,19324],{"class":3418,"line":3437},[3416,19323,10711],{"class":4368},[3416,19325,6341],{"class":6340},[3416,19327,19328,19331],{"class":3418,"line":3444},[3416,19329,19330],{"class":3808},"        AttributeName=CustomerId,AttributeType=S",[3416,19332,6341],{"class":6340},[3416,19334,19335,19338],{"class":3418,"line":3450},[3416,19336,19337],{"class":3808},"        AttributeName=OrderDateId,AttributeType=S",[3416,19339,6341],{"class":6340},[3416,19341,19342,19345],{"class":3418,"line":3456},[3416,19343,19344],{"class":3808},"        AttributeName=PendingStatus,AttributeType=S",[3416,19346,6341],{"class":6340},[3416,19348,19349,19352],{"class":3418,"line":3462},[3416,19350,19351],{"class":3808},"        AttributeName=ProductId_0,AttributeType=S",[3416,19353,6341],{"class":6340},[3416,19355,19356,19358],{"class":3418,"line":3468},[3416,19357,10732],{"class":4368},[3416,19359,6341],{"class":6340},[3416,19361,19362,19365],{"class":3418,"line":3474},[3416,19363,19364],{"class":3808},"        AttributeName=CustomerId,KeyType=HASH",[3416,19366,6341],{"class":6340},[3416,19368,19369,19372],{"class":3418,"line":3480},[3416,19370,19371],{"class":3808},"        AttributeName=OrderDateId,KeyType=RANGE",[3416,19373,6341],{"class":6340},[3416,19375,19376,19379],{"class":3418,"line":3486},[3416,19377,19378],{"class":4368},"    --global-secondary-indexes",[3416,19380,9727],{"class":3808},[3416,19382,19383],{"class":3418,"line":3492},[3416,19384,8611],{"class":3808},[3416,19386,19387],{"class":3418,"line":3498},[3416,19388,19389],{"class":3808},"            \"IndexName\": \"PendingOrdersByDate\",\n",[3416,19391,19392],{"class":3418,"line":3504},[3416,19393,15342],{"class":3808},[3416,19395,19396],{"class":3418,"line":3510},[3416,19397,19398],{"class":3808},"                {\"AttributeName\": \"PendingStatus\", \"KeyType\": \"HASH\"},\n",[3416,19400,19401],{"class":3418,"line":3515},[3416,19402,19403],{"class":3808},"                {\"AttributeName\": \"OrderDateId\",   \"KeyType\": \"RANGE\"}\n",[3416,19405,19406],{"class":3418,"line":3521},[3416,19407,15357],{"class":3808},[3416,19409,19410],{"class":3418,"line":3527},[3416,19411,15362],{"class":3808},[3416,19413,19414],{"class":3418,"line":3533},[3416,19415,15367],{"class":3808},[3416,19417,19418],{"class":3418,"line":3539},[3416,19419,19420],{"class":3808},"                \"NonKeyAttributes\": [\"CustomerId\", \"TotalAmount\"]\n",[3416,19422,19423],{"class":3418,"line":3545},[3416,19424,8815],{"class":3808},[3416,19426,19427],{"class":3418,"line":3551},[3416,19428,9774],{"class":3808},[3416,19430,19431],{"class":3418,"line":3557},[3416,19432,8611],{"class":3808},[3416,19434,19435],{"class":3418,"line":3563},[3416,19436,19437],{"class":3808},"            \"IndexName\": \"OrdersByProduct\",\n",[3416,19439,19440],{"class":3418,"line":3569},[3416,19441,15342],{"class":3808},[3416,19443,19444],{"class":3418,"line":3574},[3416,19445,19446],{"class":3808},"                {\"AttributeName\": \"ProductId_0\", \"KeyType\": \"HASH\"},\n",[3416,19448,19449],{"class":3418,"line":3579},[3416,19450,19451],{"class":3808},"                {\"AttributeName\": \"OrderDateId\", \"KeyType\": \"RANGE\"}\n",[3416,19453,19454],{"class":3418,"line":3584},[3416,19455,15357],{"class":3808},[3416,19457,19458],{"class":3418,"line":3590},[3416,19459,19460],{"class":3808},"            \"Projection\": {\"ProjectionType\": \"KEYS_ONLY\"}\n",[3416,19462,19463],{"class":3418,"line":3596},[3416,19464,8533],{"class":3808},[3416,19466,19467,19469],{"class":3418,"line":3602},[3416,19468,9816],{"class":3808},[3416,19470,6341],{"class":6340},[3416,19472,19473,19475,19477],{"class":3418,"line":3608},[3416,19474,10753],{"class":4368},[3416,19476,10756],{"class":3808},[3416,19478,6341],{"class":6340},[3416,19480,19481,19483],{"class":3418,"line":3614},[3416,19482,6366],{"class":4368},[3416,19484,6369],{"class":3808},[3416,19486,19487],{"class":3418,"line":3620},[3416,19488,3441],{"emptyLinePlaceholder":3440},[3416,19490,19491],{"class":3418,"line":3626},[3416,19492,19493],{"class":3789},"# ── Запис нового PENDING замовлення (потрапляє в Sparse GSI) ──────────────────\n",[3416,19495,19496,19498,19500,19502],{"class":3418,"line":3631},[3416,19497,6331],{"class":6330},[3416,19499,6334],{"class":3808},[3416,19501,6643],{"class":3808},[3416,19503,6341],{"class":6340},[3416,19505,19506,19508,19510],{"class":3418,"line":3636},[3416,19507,6346],{"class":4368},[3416,19509,19317],{"class":3808},[3416,19511,6341],{"class":6340},[3416,19513,19514,19516],{"class":3418,"line":3641},[3416,19515,6658],{"class":4368},[3416,19517,6661],{"class":3808},[3416,19519,19520],{"class":3418,"line":3647},[3416,19521,19522],{"class":3808},"        \"CustomerId\":    {\"S\": \"cust-001\"},\n",[3416,19524,19525],{"class":3418,"line":3653},[3416,19526,19527],{"class":3808},"        \"OrderDateId\":   {\"S\": \"2025-06-01T10:00#ord-XYZ\"},\n",[3416,19529,19530],{"class":3418,"line":3659},[3416,19531,19532],{"class":3808},"        \"OrderId\":       {\"S\": \"ord-XYZ\"},\n",[3416,19534,19535],{"class":3418,"line":3665},[3416,19536,19537],{"class":3808},"        \"Status\":        {\"S\": \"PENDING\"},\n",[3416,19539,19540],{"class":3418,"line":3671},[3416,19541,19542],{"class":3808},"        \"PendingStatus\": {\"S\": \"PENDING\"},\n",[3416,19544,19545],{"class":3418,"line":3677},[3416,19546,19547],{"class":3808},"        \"TotalAmount\":   {\"N\": \"149.99\"},\n",[3416,19549,19550],{"class":3418,"line":3683},[3416,19551,19552],{"class":3808},"        \"ProductId_0\":   {\"S\": \"prod-laptop\"}\n",[3416,19554,19555,19557],{"class":3418,"line":3688},[3416,19556,6686],{"class":3808},[3416,19558,6341],{"class":6340},[3416,19560,19561,19563],{"class":3418,"line":3693},[3416,19562,6366],{"class":4368},[3416,19564,6369],{"class":3808},[3416,19566,19567],{"class":3418,"line":3698},[3416,19568,3441],{"emptyLinePlaceholder":3440},[3416,19570,19571],{"class":3418,"line":3704},[3416,19572,19573],{"class":3789},"# ── Оплата замовлення (видалення PendingStatus -> автоматично зникає з GSI) ────\n",[3416,19575,19576,19578,19580,19582],{"class":3418,"line":3710},[3416,19577,6331],{"class":6330},[3416,19579,6334],{"class":3808},[3416,19581,6988],{"class":3808},[3416,19583,6341],{"class":6340},[3416,19585,19586,19588,19590],{"class":3418,"line":3715},[3416,19587,6346],{"class":4368},[3416,19589,19317],{"class":3808},[3416,19591,6341],{"class":6340},[3416,19593,19594,19596,19599],{"class":3418,"line":12799},[3416,19595,6356],{"class":4368},[3416,19597,19598],{"class":3808}," '{\"CustomerId\": {\"S\": \"cust-001\"}, \"OrderDateId\": {\"S\": \"2025-06-01T10:00#ord-XYZ\"}}'",[3416,19600,6341],{"class":6340},[3416,19602,19603,19605,19608],{"class":3418,"line":12822},[3416,19604,7011],{"class":4368},[3416,19606,19607],{"class":3808}," \"SET #s = :paid REMOVE PendingStatus\"",[3416,19609,6341],{"class":6340},[3416,19611,19612,19615,19618],{"class":3418,"line":12827},[3416,19613,19614],{"class":4368},"    --expression-attribute-names",[3416,19616,19617],{"class":3808}," '{\"#s\": \"Status\"}'",[3416,19619,6341],{"class":6340},[3416,19621,19622,19624,19627],{"class":3418,"line":12832},[3416,19623,7021],{"class":4368},[3416,19625,19626],{"class":3808}," '{\":paid\": {\"S\": \"PAID\"}}'",[3416,19628,6341],{"class":6340},[3416,19630,19631,19633],{"class":3418,"line":12837},[3416,19632,6366],{"class":4368},[3416,19634,6369],{"class":3808},[3416,19636,19637],{"class":3418,"line":12843},[3416,19638,3441],{"emptyLinePlaceholder":3440},[3416,19640,19641],{"class":3418,"line":12860},[3416,19642,19643],{"class":3789},"# ── Отримання активних PENDING замовлень через Sparse GSI ───────────────────────\n",[3416,19645,19646,19648,19650,19652],{"class":3418,"line":12865},[3416,19647,6331],{"class":6330},[3416,19649,6334],{"class":3808},[3416,19651,7676],{"class":3808},[3416,19653,6341],{"class":6340},[3416,19655,19656,19658,19660],{"class":3418,"line":12876},[3416,19657,6346],{"class":4368},[3416,19659,19317],{"class":3808},[3416,19661,6341],{"class":6340},[3416,19663,19664,19666,19669],{"class":3418,"line":12897},[3416,19665,16188],{"class":4368},[3416,19667,19668],{"class":3808}," PendingOrdersByDate",[3416,19670,6341],{"class":6340},[3416,19672,19673,19675,19678],{"class":3418,"line":12902},[3416,19674,7691],{"class":4368},[3416,19676,19677],{"class":3808}," \"PendingStatus = :p\"",[3416,19679,6341],{"class":6340},[3416,19681,19682,19684,19687],{"class":3418,"line":12925},[3416,19683,7021],{"class":4368},[3416,19685,19686],{"class":3808}," '{\":p\": {\"S\": \"PENDING\"}}'",[3416,19688,6341],{"class":6340},[3416,19690,19691,19693],{"class":3418,"line":12948},[3416,19692,6366],{"class":4368},[3416,19694,6369],{"class":3808},[6311,19696,19697],{"label":6372},[3406,19698,19700],{"className":6375,"code":19699,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nvar client = new AmazonDynamoDBClient();\n\n\u002F\u002F ── Створення таблиці Orders з двома глобальними індексами (GSI) ──────────────\nawait client.CreateTableAsync(new CreateTableRequest\n{\n    TableName = \"Orders\",\n    AttributeDefinitions = new List\u003CAttributeDefinition>\n    {\n        new() { AttributeName = \"CustomerId\", AttributeType = ScalarAttributeType.S },\n        new() { AttributeName = \"OrderDateId\", AttributeType = ScalarAttributeType.S },\n        new() { AttributeName = \"PendingStatus\", AttributeType = ScalarAttributeType.S },\n        new() { AttributeName = \"ProductId_0\", AttributeType = ScalarAttributeType.S }\n    },\n    KeySchema = new List\u003CKeySchemaElement>\n    {\n        new() { AttributeName = \"CustomerId\", KeyType = KeyType.HASH },\n        new() { AttributeName = \"OrderDateId\", KeyType = KeyType.RANGE }\n    },\n    GlobalSecondaryIndexes = new List\u003CGlobalSecondaryIndex>\n    {\n        new()\n        {\n            IndexName = \"PendingOrdersByDate\",\n            KeySchema = new List\u003CKeySchemaElement>\n            {\n                new() { AttributeName = \"PendingStatus\", KeyType = KeyType.HASH },\n                new() { AttributeName = \"OrderDateId\", KeyType = KeyType.RANGE }\n            },\n            Projection = new Projection\n            {\n                ProjectionType = ProjectionType.INCLUDE,\n                NonKeyAttributes = new List\u003Cstring> { \"CustomerId\", \"TotalAmount\" }\n            },\n            ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 10 }\n        },\n        new()\n        {\n            IndexName = \"OrdersByProduct\",\n            KeySchema = new List\u003CKeySchemaElement>\n            {\n                new() { AttributeName = \"ProductId_0\", KeyType = KeyType.HASH },\n                new() { AttributeName = \"OrderDateId\", KeyType = KeyType.RANGE }\n            },\n            Projection = new Projection { ProjectionType = ProjectionType.KEYS_ONLY },\n            ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 10, WriteCapacityUnits = 10 }\n        }\n    },\n    BillingMode = BillingMode.PAY_PER_REQUEST\n});\n\n\u002F\u002F ── Запис нового замовлення зі статусом PENDING ──────────────────────────────\nawait client.PutItemAsync(new PutItemRequest\n{\n    TableName = \"Orders\",\n    Item = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"CustomerId\", new AttributeValue { S = \"cust-001\" } },\n        { \"OrderDateId\", new AttributeValue { S = \"2025-06-01T10:00#ord-XYZ\" } },\n        { \"OrderId\", new AttributeValue { S = \"ord-XYZ\" } },\n        { \"Status\", new AttributeValue { S = \"PENDING\" } },\n        { \"PendingStatus\", new AttributeValue { S = \"PENDING\" } },\n        { \"TotalAmount\", new AttributeValue { N = \"149.99\" } },\n        { \"ProductId_0\", new AttributeValue { S = \"prod-laptop\" } }\n    }\n});\n\n\u002F\u002F ── Оплата замовлення: оновлення статусу та видалення PendingStatus ────────────\nawait client.UpdateItemAsync(new UpdateItemRequest\n{\n    TableName = \"Orders\",\n    Key = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"CustomerId\", new AttributeValue { S = \"cust-001\" } },\n        { \"OrderDateId\", new AttributeValue { S = \"2025-06-01T10:00#ord-XYZ\" } }\n    },\n    UpdateExpression = \"SET #s = :paid REMOVE PendingStatus\",\n    ExpressionAttributeNames = new Dictionary\u003Cstring, string> { { \"#s\", \"Status\" } },\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue> { { \":paid\", new AttributeValue { S = \"PAID\" } } }\n});\n\n\u002F\u002F ── Запит активних PENDING замовлень через Sparse GSI ──────────────────────────\nvar pendingQuery = new QueryRequest\n{\n    TableName = \"Orders\",\n    IndexName = \"PendingOrdersByDate\",\n    KeyConditionExpression = \"PendingStatus = :p\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":p\", new AttributeValue { S = \"PENDING\" } }\n    }\n};\nvar pendingResult = await client.QueryAsync(pendingQuery);\n",[3413,19701,19702,19714,19730,19734,19748,19752,19757,19773,19777,19788,19804,19808,19835,19862,19889,19916,19920,19936,19940,19966,19992,19996,20014,20018,20024,20028,20039,20055,20059,20085,20111,20115,20125,20129,20143,20168,20172,20205,20209,20215,20219,20230,20246,20250,20276,20302,20306,20331,20359,20363,20367,20379,20383,20387,20392,20408,20412,20422,20442,20446,20469,20492,20516,20539,20561,20584,20607,20612,20617,20622,20628,20645,20650,20661,20682,20687,20710,20733,20738,20750,20782,20824,20829,20834,20840,20854,20859,20870,20881,20893,20914,20919,20943,20948,20953],{"__ignoreMap":3411},[3416,19703,19704,19706,19708,19710,19712],{"class":3418,"line":3419},[3416,19705,17433],{"class":11427},[3416,19707,17436],{"class":6397},[3416,19709,4043],{"class":3795},[3416,19711,17441],{"class":6397},[3416,19713,11594],{"class":3795},[3416,19715,19716,19718,19720,19722,19724,19726,19728],{"class":3418,"line":3425},[3416,19717,17433],{"class":11427},[3416,19719,17436],{"class":6397},[3416,19721,4043],{"class":3795},[3416,19723,17441],{"class":6397},[3416,19725,4043],{"class":3795},[3416,19727,17458],{"class":6397},[3416,19729,11594],{"class":3795},[3416,19731,19732],{"class":3418,"line":3431},[3416,19733,3441],{"emptyLinePlaceholder":3440},[3416,19735,19736,19738,19740,19742,19744,19746],{"class":3418,"line":3437},[3416,19737,6384],{"class":4368},[3416,19739,6388],{"class":6387},[3416,19741,6391],{"class":3795},[3416,19743,6394],{"class":4368},[3416,19745,6398],{"class":6397},[3416,19747,6401],{"class":3795},[3416,19749,19750],{"class":3418,"line":3444},[3416,19751,3441],{"emptyLinePlaceholder":3440},[3416,19753,19754],{"class":3418,"line":3450},[3416,19755,19756],{"class":3789},"\u002F\u002F ── Створення таблиці Orders з двома глобальними індексами (GSI) ──────────────\n",[3416,19758,19759,19761,19763,19765,19767,19769,19771],{"class":3418,"line":3456},[3416,19760,6413],{"class":4368},[3416,19762,6388],{"class":6387},[3416,19764,4043],{"class":3795},[3416,19766,10802],{"class":6330},[3416,19768,6423],{"class":3795},[3416,19770,6394],{"class":4368},[3416,19772,10809],{"class":6397},[3416,19774,19775],{"class":3418,"line":3462},[3416,19776,3796],{"class":3795},[3416,19778,19779,19781,19783,19786],{"class":3418,"line":3468},[3416,19780,6437],{"class":6387},[3416,19782,6391],{"class":3795},[3416,19784,19785],{"class":3808},"\"Orders\"",[3416,19787,3812],{"class":3795},[3416,19789,19790,19792,19794,19796,19798,19800,19802],{"class":3418,"line":3474},[3416,19791,10828],{"class":6387},[3416,19793,6391],{"class":3795},[3416,19795,6394],{"class":4368},[3416,19797,8640],{"class":6397},[3416,19799,5861],{"class":3795},[3416,19801,10839],{"class":6397},[3416,19803,6469],{"class":3795},[3416,19805,19806],{"class":3418,"line":3480},[3416,19807,6474],{"class":3795},[3416,19809,19810,19812,19814,19816,19818,19821,19823,19825,19827,19829,19831,19833],{"class":3418,"line":3486},[3416,19811,9886],{"class":4368},[3416,19813,17546],{"class":3795},[3416,19815,10857],{"class":6387},[3416,19817,6391],{"class":3795},[3416,19819,19820],{"class":3808},"\"CustomerId\"",[3416,19822,4384],{"class":3795},[3416,19824,10866],{"class":6387},[3416,19826,6391],{"class":3795},[3416,19828,10871],{"class":6387},[3416,19830,4043],{"class":3795},[3416,19832,6495],{"class":6387},[3416,19834,8915],{"class":3795},[3416,19836,19837,19839,19841,19843,19845,19848,19850,19852,19854,19856,19858,19860],{"class":3418,"line":3492},[3416,19838,9886],{"class":4368},[3416,19840,17546],{"class":3795},[3416,19842,10857],{"class":6387},[3416,19844,6391],{"class":3795},[3416,19846,19847],{"class":3808},"\"OrderDateId\"",[3416,19849,4384],{"class":3795},[3416,19851,10866],{"class":6387},[3416,19853,6391],{"class":3795},[3416,19855,10871],{"class":6387},[3416,19857,4043],{"class":3795},[3416,19859,6495],{"class":6387},[3416,19861,8915],{"class":3795},[3416,19863,19864,19866,19868,19870,19872,19875,19877,19879,19881,19883,19885,19887],{"class":3418,"line":3498},[3416,19865,9886],{"class":4368},[3416,19867,17546],{"class":3795},[3416,19869,10857],{"class":6387},[3416,19871,6391],{"class":3795},[3416,19873,19874],{"class":3808},"\"PendingStatus\"",[3416,19876,4384],{"class":3795},[3416,19878,10866],{"class":6387},[3416,19880,6391],{"class":3795},[3416,19882,10871],{"class":6387},[3416,19884,4043],{"class":3795},[3416,19886,6495],{"class":6387},[3416,19888,8915],{"class":3795},[3416,19890,19891,19893,19895,19897,19899,19902,19904,19906,19908,19910,19912,19914],{"class":3418,"line":3504},[3416,19892,9886],{"class":4368},[3416,19894,17546],{"class":3795},[3416,19896,10857],{"class":6387},[3416,19898,6391],{"class":3795},[3416,19900,19901],{"class":3808},"\"ProductId_0\"",[3416,19903,4384],{"class":3795},[3416,19905,10866],{"class":6387},[3416,19907,6391],{"class":3795},[3416,19909,10871],{"class":6387},[3416,19911,4043],{"class":3795},[3416,19913,6495],{"class":6387},[3416,19915,8948],{"class":3795},[3416,19917,19918],{"class":3418,"line":3510},[3416,19919,4442],{"class":3795},[3416,19921,19922,19924,19926,19928,19930,19932,19934],{"class":3418,"line":3515},[3416,19923,10914],{"class":6387},[3416,19925,6391],{"class":3795},[3416,19927,6394],{"class":4368},[3416,19929,8640],{"class":6397},[3416,19931,5861],{"class":3795},[3416,19933,10925],{"class":6397},[3416,19935,6469],{"class":3795},[3416,19937,19938],{"class":3418,"line":3521},[3416,19939,6474],{"class":3795},[3416,19941,19942,19944,19946,19948,19950,19952,19954,19956,19958,19960,19962,19964],{"class":3418,"line":3527},[3416,19943,9886],{"class":4368},[3416,19945,17546],{"class":3795},[3416,19947,10857],{"class":6387},[3416,19949,6391],{"class":3795},[3416,19951,19820],{"class":3808},[3416,19953,4384],{"class":3795},[3416,19955,10951],{"class":6387},[3416,19957,6391],{"class":3795},[3416,19959,10951],{"class":6387},[3416,19961,4043],{"class":3795},[3416,19963,10960],{"class":6387},[3416,19965,8915],{"class":3795},[3416,19967,19968,19970,19972,19974,19976,19978,19980,19982,19984,19986,19988,19990],{"class":3418,"line":3533},[3416,19969,9886],{"class":4368},[3416,19971,17546],{"class":3795},[3416,19973,10857],{"class":6387},[3416,19975,6391],{"class":3795},[3416,19977,19847],{"class":3808},[3416,19979,4384],{"class":3795},[3416,19981,10951],{"class":6387},[3416,19983,6391],{"class":3795},[3416,19985,10951],{"class":6387},[3416,19987,4043],{"class":3795},[3416,19989,10989],{"class":6387},[3416,19991,8948],{"class":3795},[3416,19993,19994],{"class":3418,"line":3539},[3416,19995,4442],{"class":3795},[3416,19997,19998,20001,20003,20005,20007,20009,20012],{"class":3418,"line":3545},[3416,19999,20000],{"class":6387},"    GlobalSecondaryIndexes",[3416,20002,6391],{"class":3795},[3416,20004,6394],{"class":4368},[3416,20006,8640],{"class":6397},[3416,20008,5861],{"class":3795},[3416,20010,20011],{"class":6397},"GlobalSecondaryIndex",[3416,20013,6469],{"class":3795},[3416,20015,20016],{"class":3418,"line":3551},[3416,20017,6474],{"class":3795},[3416,20019,20020,20022],{"class":3418,"line":3557},[3416,20021,9886],{"class":4368},[3416,20023,17625],{"class":3795},[3416,20025,20026],{"class":3418,"line":3563},[3416,20027,8611],{"class":3795},[3416,20029,20030,20032,20034,20037],{"class":3418,"line":3569},[3416,20031,15683],{"class":6387},[3416,20033,6391],{"class":3795},[3416,20035,20036],{"class":3808},"\"PendingOrdersByDate\"",[3416,20038,3812],{"class":3795},[3416,20040,20041,20043,20045,20047,20049,20051,20053],{"class":3418,"line":3574},[3416,20042,15695],{"class":6387},[3416,20044,6391],{"class":3795},[3416,20046,6394],{"class":4368},[3416,20048,8640],{"class":6397},[3416,20050,5861],{"class":3795},[3416,20052,10925],{"class":6397},[3416,20054,6469],{"class":3795},[3416,20056,20057],{"class":3418,"line":3579},[3416,20058,8628],{"class":3795},[3416,20060,20061,20063,20065,20067,20069,20071,20073,20075,20077,20079,20081,20083],{"class":3418,"line":3584},[3416,20062,9213],{"class":4368},[3416,20064,17546],{"class":3795},[3416,20066,10857],{"class":6387},[3416,20068,6391],{"class":3795},[3416,20070,19874],{"class":3808},[3416,20072,4384],{"class":3795},[3416,20074,10951],{"class":6387},[3416,20076,6391],{"class":3795},[3416,20078,10951],{"class":6387},[3416,20080,4043],{"class":3795},[3416,20082,10960],{"class":6387},[3416,20084,8915],{"class":3795},[3416,20086,20087,20089,20091,20093,20095,20097,20099,20101,20103,20105,20107,20109],{"class":3418,"line":3590},[3416,20088,9213],{"class":4368},[3416,20090,17546],{"class":3795},[3416,20092,10857],{"class":6387},[3416,20094,6391],{"class":3795},[3416,20096,19847],{"class":3808},[3416,20098,4384],{"class":3795},[3416,20100,10951],{"class":6387},[3416,20102,6391],{"class":3795},[3416,20104,10951],{"class":6387},[3416,20106,4043],{"class":3795},[3416,20108,10989],{"class":6387},[3416,20110,8948],{"class":3795},[3416,20112,20113],{"class":3418,"line":3596},[3416,20114,9066],{"class":3795},[3416,20116,20117,20119,20121,20123],{"class":3418,"line":3602},[3416,20118,15776],{"class":6387},[3416,20120,6391],{"class":3795},[3416,20122,6394],{"class":4368},[3416,20124,15783],{"class":6397},[3416,20126,20127],{"class":3418,"line":3608},[3416,20128,8628],{"class":3795},[3416,20130,20131,20133,20135,20137,20139,20141],{"class":3418,"line":3614},[3416,20132,15792],{"class":6387},[3416,20134,6391],{"class":3795},[3416,20136,15797],{"class":6387},[3416,20138,4043],{"class":3795},[3416,20140,15082],{"class":6387},[3416,20142,3812],{"class":3795},[3416,20144,20145,20147,20149,20151,20153,20155,20157,20159,20161,20163,20166],{"class":3418,"line":3620},[3416,20146,15808],{"class":6387},[3416,20148,6391],{"class":3795},[3416,20150,6394],{"class":4368},[3416,20152,8640],{"class":6397},[3416,20154,5861],{"class":3795},[3416,20156,6461],{"class":4368},[3416,20158,15821],{"class":3795},[3416,20160,19820],{"class":3808},[3416,20162,4384],{"class":3795},[3416,20164,20165],{"class":3808},"\"TotalAmount\"",[3416,20167,8948],{"class":3795},[3416,20169,20170],{"class":3418,"line":3626},[3416,20171,9066],{"class":3795},[3416,20173,20174,20177,20179,20181,20184,20186,20189,20191,20194,20196,20199,20201,20203],{"class":3418,"line":3631},[3416,20175,20176],{"class":6387},"            ProvisionedThroughput",[3416,20178,6391],{"class":3795},[3416,20180,6394],{"class":4368},[3416,20182,20183],{"class":6397}," ProvisionedThroughput",[3416,20185,6492],{"class":3795},[3416,20187,20188],{"class":6387},"ReadCapacityUnits",[3416,20190,6391],{"class":3795},[3416,20192,20193],{"class":3870},"10",[3416,20195,4384],{"class":3795},[3416,20197,20198],{"class":6387},"WriteCapacityUnits",[3416,20200,6391],{"class":3795},[3416,20202,20193],{"class":3870},[3416,20204,8948],{"class":3795},[3416,20206,20207],{"class":3418,"line":3636},[3416,20208,9774],{"class":3795},[3416,20210,20211,20213],{"class":3418,"line":3641},[3416,20212,9886],{"class":4368},[3416,20214,17625],{"class":3795},[3416,20216,20217],{"class":3418,"line":3647},[3416,20218,8611],{"class":3795},[3416,20220,20221,20223,20225,20228],{"class":3418,"line":3653},[3416,20222,15683],{"class":6387},[3416,20224,6391],{"class":3795},[3416,20226,20227],{"class":3808},"\"OrdersByProduct\"",[3416,20229,3812],{"class":3795},[3416,20231,20232,20234,20236,20238,20240,20242,20244],{"class":3418,"line":3659},[3416,20233,15695],{"class":6387},[3416,20235,6391],{"class":3795},[3416,20237,6394],{"class":4368},[3416,20239,8640],{"class":6397},[3416,20241,5861],{"class":3795},[3416,20243,10925],{"class":6397},[3416,20245,6469],{"class":3795},[3416,20247,20248],{"class":3418,"line":3665},[3416,20249,8628],{"class":3795},[3416,20251,20252,20254,20256,20258,20260,20262,20264,20266,20268,20270,20272,20274],{"class":3418,"line":3671},[3416,20253,9213],{"class":4368},[3416,20255,17546],{"class":3795},[3416,20257,10857],{"class":6387},[3416,20259,6391],{"class":3795},[3416,20261,19901],{"class":3808},[3416,20263,4384],{"class":3795},[3416,20265,10951],{"class":6387},[3416,20267,6391],{"class":3795},[3416,20269,10951],{"class":6387},[3416,20271,4043],{"class":3795},[3416,20273,10960],{"class":6387},[3416,20275,8915],{"class":3795},[3416,20277,20278,20280,20282,20284,20286,20288,20290,20292,20294,20296,20298,20300],{"class":3418,"line":3677},[3416,20279,9213],{"class":4368},[3416,20281,17546],{"class":3795},[3416,20283,10857],{"class":6387},[3416,20285,6391],{"class":3795},[3416,20287,19847],{"class":3808},[3416,20289,4384],{"class":3795},[3416,20291,10951],{"class":6387},[3416,20293,6391],{"class":3795},[3416,20295,10951],{"class":6387},[3416,20297,4043],{"class":3795},[3416,20299,10989],{"class":6387},[3416,20301,8948],{"class":3795},[3416,20303,20304],{"class":3418,"line":3683},[3416,20305,9066],{"class":3795},[3416,20307,20308,20310,20312,20314,20317,20319,20321,20323,20325,20327,20329],{"class":3418,"line":3688},[3416,20309,15776],{"class":6387},[3416,20311,6391],{"class":3795},[3416,20313,6394],{"class":4368},[3416,20315,20316],{"class":6397}," Projection",[3416,20318,6492],{"class":3795},[3416,20320,15797],{"class":6387},[3416,20322,6391],{"class":3795},[3416,20324,15797],{"class":6387},[3416,20326,4043],{"class":3795},[3416,20328,15069],{"class":6387},[3416,20330,8915],{"class":3795},[3416,20332,20333,20335,20337,20339,20341,20343,20345,20347,20349,20351,20353,20355,20357],{"class":3418,"line":3693},[3416,20334,20176],{"class":6387},[3416,20336,6391],{"class":3795},[3416,20338,6394],{"class":4368},[3416,20340,20183],{"class":6397},[3416,20342,6492],{"class":3795},[3416,20344,20188],{"class":6387},[3416,20346,6391],{"class":3795},[3416,20348,20193],{"class":3870},[3416,20350,4384],{"class":3795},[3416,20352,20198],{"class":6387},[3416,20354,6391],{"class":3795},[3416,20356,20193],{"class":3870},[3416,20358,8948],{"class":3795},[3416,20360,20361],{"class":3418,"line":3698},[3416,20362,8533],{"class":3795},[3416,20364,20365],{"class":3418,"line":3704},[3416,20366,4442],{"class":3795},[3416,20368,20369,20371,20373,20375,20377],{"class":3418,"line":3710},[3416,20370,11000],{"class":6387},[3416,20372,6391],{"class":3795},[3416,20374,11005],{"class":6387},[3416,20376,4043],{"class":3795},[3416,20378,11010],{"class":6387},[3416,20380,20381],{"class":3418,"line":3715},[3416,20382,6537],{"class":3795},[3416,20384,20385],{"class":3418,"line":12799},[3416,20386,3441],{"emptyLinePlaceholder":3440},[3416,20388,20389],{"class":3418,"line":12822},[3416,20390,20391],{"class":3789},"\u002F\u002F ── Запис нового замовлення зі статусом PENDING ──────────────────────────────\n",[3416,20393,20394,20396,20398,20400,20402,20404,20406],{"class":3418,"line":12827},[3416,20395,6413],{"class":4368},[3416,20397,6388],{"class":6387},[3416,20399,4043],{"class":3795},[3416,20401,6718],{"class":6330},[3416,20403,6423],{"class":3795},[3416,20405,6394],{"class":4368},[3416,20407,6725],{"class":6397},[3416,20409,20410],{"class":3418,"line":12832},[3416,20411,3796],{"class":3795},[3416,20413,20414,20416,20418,20420],{"class":3418,"line":12837},[3416,20415,6437],{"class":6387},[3416,20417,6391],{"class":3795},[3416,20419,19785],{"class":3808},[3416,20421,3812],{"class":3795},[3416,20423,20424,20426,20428,20430,20432,20434,20436,20438,20440],{"class":3418,"line":12843},[3416,20425,6744],{"class":6387},[3416,20427,6391],{"class":3795},[3416,20429,6394],{"class":4368},[3416,20431,6456],{"class":6397},[3416,20433,5861],{"class":3795},[3416,20435,6461],{"class":4368},[3416,20437,4384],{"class":3795},[3416,20439,6466],{"class":6397},[3416,20441,6469],{"class":3795},[3416,20443,20444],{"class":3418,"line":12860},[3416,20445,6474],{"class":3795},[3416,20447,20448,20450,20452,20454,20456,20458,20460,20462,20464,20467],{"class":3418,"line":12865},[3416,20449,6479],{"class":3795},[3416,20451,19820],{"class":3808},[3416,20453,4384],{"class":3795},[3416,20455,6394],{"class":4368},[3416,20457,6489],{"class":6397},[3416,20459,6492],{"class":3795},[3416,20461,6495],{"class":6387},[3416,20463,6391],{"class":3795},[3416,20465,20466],{"class":3808},"\"cust-001\"",[3416,20468,6503],{"class":3795},[3416,20470,20471,20473,20475,20477,20479,20481,20483,20485,20487,20490],{"class":3418,"line":12876},[3416,20472,6479],{"class":3795},[3416,20474,19847],{"class":3808},[3416,20476,4384],{"class":3795},[3416,20478,6394],{"class":4368},[3416,20480,6489],{"class":6397},[3416,20482,6492],{"class":3795},[3416,20484,6495],{"class":6387},[3416,20486,6391],{"class":3795},[3416,20488,20489],{"class":3808},"\"2025-06-01T10:00#ord-XYZ\"",[3416,20491,6503],{"class":3795},[3416,20493,20494,20496,20499,20501,20503,20505,20507,20509,20511,20514],{"class":3418,"line":12897},[3416,20495,6479],{"class":3795},[3416,20497,20498],{"class":3808},"\"OrderId\"",[3416,20500,4384],{"class":3795},[3416,20502,6394],{"class":4368},[3416,20504,6489],{"class":6397},[3416,20506,6492],{"class":3795},[3416,20508,6495],{"class":6387},[3416,20510,6391],{"class":3795},[3416,20512,20513],{"class":3808},"\"ord-XYZ\"",[3416,20515,6503],{"class":3795},[3416,20517,20518,20520,20522,20524,20526,20528,20530,20532,20534,20537],{"class":3418,"line":12902},[3416,20519,6479],{"class":3795},[3416,20521,11860],{"class":3808},[3416,20523,4384],{"class":3795},[3416,20525,6394],{"class":4368},[3416,20527,6489],{"class":6397},[3416,20529,6492],{"class":3795},[3416,20531,6495],{"class":6387},[3416,20533,6391],{"class":3795},[3416,20535,20536],{"class":3808},"\"PENDING\"",[3416,20538,6503],{"class":3795},[3416,20540,20541,20543,20545,20547,20549,20551,20553,20555,20557,20559],{"class":3418,"line":12925},[3416,20542,6479],{"class":3795},[3416,20544,19874],{"class":3808},[3416,20546,4384],{"class":3795},[3416,20548,6394],{"class":4368},[3416,20550,6489],{"class":6397},[3416,20552,6492],{"class":3795},[3416,20554,6495],{"class":6387},[3416,20556,6391],{"class":3795},[3416,20558,20536],{"class":3808},[3416,20560,6503],{"class":3795},[3416,20562,20563,20565,20567,20569,20571,20573,20575,20577,20579,20582],{"class":3418,"line":12948},[3416,20564,6479],{"class":3795},[3416,20566,20165],{"class":3808},[3416,20568,4384],{"class":3795},[3416,20570,6394],{"class":4368},[3416,20572,6489],{"class":6397},[3416,20574,6492],{"class":3795},[3416,20576,10168],{"class":6387},[3416,20578,6391],{"class":3795},[3416,20580,20581],{"class":3808},"\"149.99\"",[3416,20583,6503],{"class":3795},[3416,20585,20586,20588,20590,20592,20594,20596,20598,20600,20602,20605],{"class":3418,"line":12953},[3416,20587,6479],{"class":3795},[3416,20589,19901],{"class":3808},[3416,20591,4384],{"class":3795},[3416,20593,6394],{"class":4368},[3416,20595,6489],{"class":6397},[3416,20597,6492],{"class":3795},[3416,20599,6495],{"class":6387},[3416,20601,6391],{"class":3795},[3416,20603,20604],{"class":3808},"\"prod-laptop\"",[3416,20606,6528],{"class":3795},[3416,20608,20610],{"class":3418,"line":20609},67,[3416,20611,4167],{"class":3795},[3416,20613,20615],{"class":3418,"line":20614},68,[3416,20616,6537],{"class":3795},[3416,20618,20620],{"class":3418,"line":20619},69,[3416,20621,3441],{"emptyLinePlaceholder":3440},[3416,20623,20625],{"class":3418,"line":20624},70,[3416,20626,20627],{"class":3789},"\u002F\u002F ── Оплата замовлення: оновлення статусу та видалення PendingStatus ────────────\n",[3416,20629,20631,20633,20635,20637,20639,20641,20643],{"class":3418,"line":20630},71,[3416,20632,6413],{"class":4368},[3416,20634,6388],{"class":6387},[3416,20636,4043],{"class":3795},[3416,20638,7069],{"class":6330},[3416,20640,6423],{"class":3795},[3416,20642,6394],{"class":4368},[3416,20644,7076],{"class":6397},[3416,20646,20648],{"class":3418,"line":20647},72,[3416,20649,3796],{"class":3795},[3416,20651,20653,20655,20657,20659],{"class":3418,"line":20652},73,[3416,20654,6437],{"class":6387},[3416,20656,6391],{"class":3795},[3416,20658,19785],{"class":3808},[3416,20660,3812],{"class":3795},[3416,20662,20664,20666,20668,20670,20672,20674,20676,20678,20680],{"class":3418,"line":20663},74,[3416,20665,6449],{"class":6387},[3416,20667,6391],{"class":3795},[3416,20669,6394],{"class":4368},[3416,20671,6456],{"class":6397},[3416,20673,5861],{"class":3795},[3416,20675,6461],{"class":4368},[3416,20677,4384],{"class":3795},[3416,20679,6466],{"class":6397},[3416,20681,6469],{"class":3795},[3416,20683,20685],{"class":3418,"line":20684},75,[3416,20686,6474],{"class":3795},[3416,20688,20690,20692,20694,20696,20698,20700,20702,20704,20706,20708],{"class":3418,"line":20689},76,[3416,20691,6479],{"class":3795},[3416,20693,19820],{"class":3808},[3416,20695,4384],{"class":3795},[3416,20697,6394],{"class":4368},[3416,20699,6489],{"class":6397},[3416,20701,6492],{"class":3795},[3416,20703,6495],{"class":6387},[3416,20705,6391],{"class":3795},[3416,20707,20466],{"class":3808},[3416,20709,6503],{"class":3795},[3416,20711,20713,20715,20717,20719,20721,20723,20725,20727,20729,20731],{"class":3418,"line":20712},77,[3416,20714,6479],{"class":3795},[3416,20716,19847],{"class":3808},[3416,20718,4384],{"class":3795},[3416,20720,6394],{"class":4368},[3416,20722,6489],{"class":6397},[3416,20724,6492],{"class":3795},[3416,20726,6495],{"class":6387},[3416,20728,6391],{"class":3795},[3416,20730,20489],{"class":3808},[3416,20732,6528],{"class":3795},[3416,20734,20736],{"class":3418,"line":20735},78,[3416,20737,4442],{"class":3795},[3416,20739,20741,20743,20745,20748],{"class":3418,"line":20740},79,[3416,20742,7167],{"class":6387},[3416,20744,6391],{"class":3795},[3416,20746,20747],{"class":3808},"\"SET #s = :paid REMOVE PendingStatus\"",[3416,20749,3812],{"class":3795},[3416,20751,20753,20756,20758,20760,20762,20764,20766,20768,20770,20773,20776,20778,20780],{"class":3418,"line":20752},80,[3416,20754,20755],{"class":6387},"    ExpressionAttributeNames",[3416,20757,6391],{"class":3795},[3416,20759,6394],{"class":4368},[3416,20761,6456],{"class":6397},[3416,20763,5861],{"class":3795},[3416,20765,6461],{"class":4368},[3416,20767,4384],{"class":3795},[3416,20769,6461],{"class":4368},[3416,20771,20772],{"class":3795},"> { { ",[3416,20774,20775],{"class":3808},"\"#s\"",[3416,20777,4384],{"class":3795},[3416,20779,11860],{"class":3808},[3416,20781,6503],{"class":3795},[3416,20783,20785,20787,20789,20791,20793,20795,20797,20799,20801,20803,20806,20808,20810,20812,20814,20816,20818,20821],{"class":3418,"line":20784},81,[3416,20786,7179],{"class":6387},[3416,20788,6391],{"class":3795},[3416,20790,6394],{"class":4368},[3416,20792,6456],{"class":6397},[3416,20794,5861],{"class":3795},[3416,20796,6461],{"class":4368},[3416,20798,4384],{"class":3795},[3416,20800,6466],{"class":6397},[3416,20802,20772],{"class":3795},[3416,20804,20805],{"class":3808},"\":paid\"",[3416,20807,4384],{"class":3795},[3416,20809,6394],{"class":4368},[3416,20811,6489],{"class":6397},[3416,20813,6492],{"class":3795},[3416,20815,6495],{"class":6387},[3416,20817,6391],{"class":3795},[3416,20819,20820],{"class":3808},"\"PAID\"",[3416,20822,20823],{"class":3795}," } } }\n",[3416,20825,20827],{"class":3418,"line":20826},82,[3416,20828,6537],{"class":3795},[3416,20830,20832],{"class":3418,"line":20831},83,[3416,20833,3441],{"emptyLinePlaceholder":3440},[3416,20835,20837],{"class":3418,"line":20836},84,[3416,20838,20839],{"class":3789},"\u002F\u002F ── Запит активних PENDING замовлень через Sparse GSI ──────────────────────────\n",[3416,20841,20843,20845,20848,20850,20852],{"class":3418,"line":20842},85,[3416,20844,6384],{"class":4368},[3416,20846,20847],{"class":6387}," pendingQuery",[3416,20849,6391],{"class":3795},[3416,20851,6394],{"class":4368},[3416,20853,7755],{"class":6397},[3416,20855,20857],{"class":3418,"line":20856},86,[3416,20858,3796],{"class":3795},[3416,20860,20862,20864,20866,20868],{"class":3418,"line":20861},87,[3416,20863,6437],{"class":6387},[3416,20865,6391],{"class":3795},[3416,20867,19785],{"class":3808},[3416,20869,3812],{"class":3795},[3416,20871,20873,20875,20877,20879],{"class":3418,"line":20872},88,[3416,20874,16032],{"class":6387},[3416,20876,6391],{"class":3795},[3416,20878,20036],{"class":3808},[3416,20880,3812],{"class":3795},[3416,20882,20884,20886,20888,20891],{"class":3418,"line":20883},89,[3416,20885,7774],{"class":6387},[3416,20887,6391],{"class":3795},[3416,20889,20890],{"class":3808},"\"PendingStatus = :p\"",[3416,20892,3812],{"class":3795},[3416,20894,20896,20898,20900,20902,20904,20906,20908,20910,20912],{"class":3418,"line":20895},90,[3416,20897,7179],{"class":6387},[3416,20899,6391],{"class":3795},[3416,20901,6394],{"class":4368},[3416,20903,6456],{"class":6397},[3416,20905,5861],{"class":3795},[3416,20907,6461],{"class":4368},[3416,20909,4384],{"class":3795},[3416,20911,6466],{"class":6397},[3416,20913,6469],{"class":3795},[3416,20915,20917],{"class":3418,"line":20916},91,[3416,20918,6474],{"class":3795},[3416,20920,20922,20924,20927,20929,20931,20933,20935,20937,20939,20941],{"class":3418,"line":20921},92,[3416,20923,6479],{"class":3795},[3416,20925,20926],{"class":3808},"\":p\"",[3416,20928,4384],{"class":3795},[3416,20930,6394],{"class":4368},[3416,20932,6489],{"class":6397},[3416,20934,6492],{"class":3795},[3416,20936,6495],{"class":6387},[3416,20938,6391],{"class":3795},[3416,20940,20536],{"class":3808},[3416,20942,6528],{"class":3795},[3416,20944,20946],{"class":3418,"line":20945},93,[3416,20947,4167],{"class":3795},[3416,20949,20951],{"class":3418,"line":20950},94,[3416,20952,18505],{"class":3795},[3416,20954,20956,20958,20961,20963,20965,20967,20969,20971,20973,20976],{"class":3418,"line":20955},95,[3416,20957,6384],{"class":4368},[3416,20959,20960],{"class":6387}," pendingResult",[3416,20962,6391],{"class":3795},[3416,20964,6413],{"class":4368},[3416,20966,6388],{"class":6387},[3416,20968,4043],{"class":3795},[3416,20970,7748],{"class":6330},[3416,20972,6423],{"class":3795},[3416,20974,20975],{"class":6387},"pendingQuery",[3416,20977,11465],{"class":3795},[6311,20979,20980],{"label":6540},[3406,20981,20983],{"className":6543,"code":20982,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n# ── Запис нового PENDING замовлення ──────────────────────────────────────────\n$item = @{\n    CustomerId    = New-DDBEntry -S 'cust-001'\n    OrderDateId   = New-DDBEntry -S '2025-06-01T10:00#ord-XYZ'\n    OrderId       = New-DDBEntry -S 'ord-XYZ'\n    Status        = New-DDBEntry -S 'PENDING'\n    PendingStatus = New-DDBEntry -S 'PENDING'\n    TotalAmount   = New-DDBEntry -N '149.99'\n    ProductId_0   = New-DDBEntry -S 'prod-laptop'\n}\nSet-DDBItem -TableName Orders -Item $item -Region eu-central-1\n\n# ── Оновлення статусу замовлення та видалення PendingStatus ──────────────────\nUpdate-DDBItem `\n    -TableName Orders `\n    -Key @{ CustomerId = New-DDBEntry -S 'cust-001'; OrderDateId = New-DDBEntry -S '2025-06-01T10:00#ord-XYZ' } `\n    -UpdateExpression \"SET #s = :paid REMOVE PendingStatus\" `\n    -ExpressionAttributeName @{ '#s' = 'Status' } `\n    -ExpressionAttributeValue @{ ':paid' = New-DDBEntry -S 'PAID' } `\n    -Region eu-central-1\n\n# ── Запит active PENDING замовлень через Sparse GSI ──────────────────────────\n$queryReq = [Amazon.DynamoDBv2.Model.QueryRequest]@{\n    TableName              = 'Orders'\n    IndexName              = 'PendingOrdersByDate'\n    KeyConditionExpression = 'PendingStatus = :p'\n    ExpressionAttributeValues = @{ ':p' = New-DDBEntry -S 'PENDING' }\n}\n(Invoke-DDBQuery -QueryRequest $queryReq -Region eu-central-1).Items\n",[3413,20984,20985,20991,20995,21000,21010,21024,21038,21053,21066,21079,21093,21107,21111,21124,21128,21133,21139,21144,21180,21189,21208,21231,21238,21242,21247,21262,21271,21280,21289,21313,21317],{"__ignoreMap":3411},[3416,20986,20987,20989],{"class":3418,"line":3419},[3416,20988,12967],{"class":6330},[3416,20990,12970],{"class":3795},[3416,20992,20993],{"class":3418,"line":3425},[3416,20994,3441],{"emptyLinePlaceholder":3440},[3416,20996,20997],{"class":3418,"line":3431},[3416,20998,20999],{"class":3789},"# ── Запис нового PENDING замовлення ──────────────────────────────────────────\n",[3416,21001,21002,21004,21006,21008],{"class":3418,"line":3437},[3416,21003,6881],{"class":6387},[3416,21005,6391],{"class":3795},[3416,21007,6561],{"class":4368},[3416,21009,3796],{"class":3795},[3416,21011,21012,21015,21017,21019,21021],{"class":3418,"line":3444},[3416,21013,21014],{"class":6387},"    CustomerId",[3416,21016,6571],{"class":3795},[3416,21018,6574],{"class":6330},[3416,21020,6577],{"class":3795},[3416,21022,21023],{"class":3808},"'cust-001'\n",[3416,21025,21026,21029,21031,21033,21035],{"class":3418,"line":3450},[3416,21027,21028],{"class":6387},"    OrderDateId",[3416,21030,7374],{"class":3795},[3416,21032,6574],{"class":6330},[3416,21034,6577],{"class":3795},[3416,21036,21037],{"class":3808},"'2025-06-01T10:00#ord-XYZ'\n",[3416,21039,21040,21043,21046,21048,21050],{"class":3418,"line":3456},[3416,21041,21042],{"class":6387},"    OrderId",[3416,21044,21045],{"class":3795},"       = ",[3416,21047,6574],{"class":6330},[3416,21049,6577],{"class":3795},[3416,21051,21052],{"class":3808},"'ord-XYZ'\n",[3416,21054,21055,21057,21059,21061,21063],{"class":3418,"line":3462},[3416,21056,11803],{"class":6387},[3416,21058,7923],{"class":3795},[3416,21060,6574],{"class":6330},[3416,21062,6577],{"class":3795},[3416,21064,21065],{"class":3808},"'PENDING'\n",[3416,21067,21068,21071,21073,21075,21077],{"class":3418,"line":3468},[3416,21069,21070],{"class":6387},"    PendingStatus",[3416,21072,6391],{"class":3795},[3416,21074,6574],{"class":6330},[3416,21076,6577],{"class":3795},[3416,21078,21065],{"class":3808},[3416,21080,21081,21084,21086,21088,21090],{"class":3418,"line":3474},[3416,21082,21083],{"class":6387},"    TotalAmount",[3416,21085,7374],{"class":3795},[3416,21087,6574],{"class":6330},[3416,21089,10395],{"class":3795},[3416,21091,21092],{"class":3808},"'149.99'\n",[3416,21094,21095,21098,21100,21102,21104],{"class":3418,"line":3480},[3416,21096,21097],{"class":6387},"    ProductId_0",[3416,21099,7374],{"class":3795},[3416,21101,6574],{"class":6330},[3416,21103,6577],{"class":3795},[3416,21105,21106],{"class":3808},"'prod-laptop'\n",[3416,21108,21109],{"class":3418,"line":3486},[3416,21110,3507],{"class":3795},[3416,21112,21113,21115,21118,21120,21122],{"class":3418,"line":3492},[3416,21114,6950],{"class":6330},[3416,21116,21117],{"class":3795}," -TableName Orders -Item ",[3416,21119,6881],{"class":6387},[3416,21121,6611],{"class":3795},[3416,21123,6614],{"class":3870},[3416,21125,21126],{"class":3418,"line":3498},[3416,21127,3441],{"emptyLinePlaceholder":3440},[3416,21129,21130],{"class":3418,"line":3504},[3416,21131,21132],{"class":3789},"# ── Оновлення статусу замовлення та видалення PendingStatus ──────────────────\n",[3416,21134,21135,21137],{"class":3418,"line":3510},[3416,21136,7394],{"class":6330},[3416,21138,11105],{"class":3795},[3416,21140,21141],{"class":3418,"line":3515},[3416,21142,21143],{"class":3795},"    -TableName Orders `\n",[3416,21145,21146,21149,21151,21153,21155,21157,21159,21161,21164,21166,21168,21170,21172,21174,21177],{"class":3418,"line":3521},[3416,21147,21148],{"class":3795},"    -Key ",[3416,21150,6561],{"class":4368},[3416,21152,8886],{"class":3795},[3416,21154,19086],{"class":6387},[3416,21156,6391],{"class":3795},[3416,21158,6574],{"class":6330},[3416,21160,6577],{"class":3795},[3416,21162,21163],{"class":3808},"'cust-001'",[3416,21165,8900],{"class":3795},[3416,21167,19110],{"class":6387},[3416,21169,6391],{"class":3795},[3416,21171,6574],{"class":6330},[3416,21173,6577],{"class":3795},[3416,21175,21176],{"class":3808},"'2025-06-01T10:00#ord-XYZ'",[3416,21178,21179],{"class":3795}," } `\n",[3416,21181,21182,21185,21187],{"class":3418,"line":3527},[3416,21183,21184],{"class":3795},"    -UpdateExpression ",[3416,21186,20747],{"class":3808},[3416,21188,11105],{"class":3795},[3416,21190,21191,21194,21196,21198,21201,21203,21206],{"class":3418,"line":3533},[3416,21192,21193],{"class":3795},"    -ExpressionAttributeName ",[3416,21195,6561],{"class":4368},[3416,21197,8886],{"class":3795},[3416,21199,21200],{"class":3808},"'#s'",[3416,21202,6391],{"class":3795},[3416,21204,21205],{"class":3808},"'Status'",[3416,21207,21179],{"class":3795},[3416,21209,21210,21213,21215,21217,21220,21222,21224,21226,21229],{"class":3418,"line":3539},[3416,21211,21212],{"class":3795},"    -ExpressionAttributeValue ",[3416,21214,6561],{"class":4368},[3416,21216,8886],{"class":3795},[3416,21218,21219],{"class":3808},"':paid'",[3416,21221,6391],{"class":3795},[3416,21223,6574],{"class":6330},[3416,21225,6577],{"class":3795},[3416,21227,21228],{"class":3808},"'PAID'",[3416,21230,21179],{"class":3795},[3416,21232,21233,21236],{"class":3418,"line":3545},[3416,21234,21235],{"class":3795},"    -Region eu-central-",[3416,21237,6614],{"class":3870},[3416,21239,21240],{"class":3418,"line":3551},[3416,21241,3441],{"emptyLinePlaceholder":3440},[3416,21243,21244],{"class":3418,"line":3557},[3416,21245,21246],{"class":3789},"# ── Запит active PENDING замовлень через Sparse GSI ──────────────────────────\n",[3416,21248,21249,21252,21254,21256,21258,21260],{"class":3418,"line":3563},[3416,21250,21251],{"class":6387},"$queryReq",[3416,21253,7274],{"class":3795},[3416,21255,7882],{"class":4368},[3416,21257,7280],{"class":3795},[3416,21259,6561],{"class":4368},[3416,21261,3796],{"class":3795},[3416,21263,21264,21266,21268],{"class":3418,"line":3569},[3416,21265,6437],{"class":6387},[3416,21267,13271],{"class":3795},[3416,21269,21270],{"class":3808},"'Orders'\n",[3416,21272,21273,21275,21277],{"class":3418,"line":3574},[3416,21274,16032],{"class":6387},[3416,21276,13271],{"class":3795},[3416,21278,21279],{"class":3808},"'PendingOrdersByDate'\n",[3416,21281,21282,21284,21286],{"class":3418,"line":3579},[3416,21283,7774],{"class":6387},[3416,21285,6391],{"class":3795},[3416,21287,21288],{"class":3808},"'PendingStatus = :p'\n",[3416,21290,21291,21293,21295,21297,21299,21302,21304,21306,21308,21311],{"class":3418,"line":3584},[3416,21292,7179],{"class":6387},[3416,21294,6391],{"class":3795},[3416,21296,6561],{"class":4368},[3416,21298,8886],{"class":3795},[3416,21300,21301],{"class":3808},"':p'",[3416,21303,6391],{"class":3795},[3416,21305,6574],{"class":6330},[3416,21307,6577],{"class":3795},[3416,21309,21310],{"class":3808},"'PENDING'",[3416,21312,8948],{"class":3795},[3416,21314,21315],{"class":3418,"line":3590},[3416,21316,3507],{"class":3795},[3416,21318,21319,21321,21323,21325,21327,21329,21331],{"class":3418,"line":3596},[3416,21320,6423],{"class":3795},[3416,21322,7956],{"class":6330},[3416,21324,7959],{"class":3795},[3416,21326,21251],{"class":6387},[3416,21328,6611],{"class":3795},[3416,21330,13510],{"class":3870},[3416,21332,21333],{"class":3795},").Items\n",[11159,21335,21337],{"title":21336},"Вибірка PENDING замовлень через Sparse GSI",[3406,21338,21340],{"className":3780,"code":21339,"language":3782,"meta":3411,"style":3411},"{\n    \"Items\": [\n        {\n            \"PendingStatus\": { \"S\": \"PENDING\" },\n            \"OrderDateId\": { \"S\": \"2025-06-01T10:00#ord-XYZ\" },\n            \"CustomerId\": { \"S\": \"cust-001\" },\n            \"TotalAmount\": { \"S\": \"149.99\" }\n        }\n    ],\n    \"Count\": 1\n}\n",[3413,21341,21342,21346,21354,21358,21373,21388,21403,21418,21422,21427,21436],{"__ignoreMap":3411},[3416,21343,21344],{"class":3418,"line":3419},[3416,21345,3796],{"class":3795},[3416,21347,21348,21351],{"class":3418,"line":3425},[3416,21349,21350],{"class":3801},"    \"Items\"",[3416,21352,21353],{"class":3795},": [\n",[3416,21355,21356],{"class":3418,"line":3431},[3416,21357,8611],{"class":3795},[3416,21359,21360,21363,21365,21367,21369,21371],{"class":3418,"line":3437},[3416,21361,21362],{"class":3801},"            \"PendingStatus\"",[3416,21364,13460],{"class":3795},[3416,21366,13450],{"class":3801},[3416,21368,3805],{"class":3795},[3416,21370,20536],{"class":3808},[3416,21372,8915],{"class":3795},[3416,21374,21375,21378,21380,21382,21384,21386],{"class":3418,"line":3444},[3416,21376,21377],{"class":3801},"            \"OrderDateId\"",[3416,21379,13460],{"class":3795},[3416,21381,13450],{"class":3801},[3416,21383,3805],{"class":3795},[3416,21385,20489],{"class":3808},[3416,21387,8915],{"class":3795},[3416,21389,21390,21393,21395,21397,21399,21401],{"class":3418,"line":3450},[3416,21391,21392],{"class":3801},"            \"CustomerId\"",[3416,21394,13460],{"class":3795},[3416,21396,13450],{"class":3801},[3416,21398,3805],{"class":3795},[3416,21400,20466],{"class":3808},[3416,21402,8915],{"class":3795},[3416,21404,21405,21408,21410,21412,21414,21416],{"class":3418,"line":3456},[3416,21406,21407],{"class":3801},"            \"TotalAmount\"",[3416,21409,13460],{"class":3795},[3416,21411,13450],{"class":3801},[3416,21413,3805],{"class":3795},[3416,21415,20581],{"class":3808},[3416,21417,8948],{"class":3795},[3416,21419,21420],{"class":3418,"line":3462},[3416,21421,8533],{"class":3795},[3416,21423,21424],{"class":3418,"line":3468},[3416,21425,21426],{"class":3795},"    ],\n",[3416,21428,21429,21432,21434],{"class":3418,"line":3474},[3416,21430,21431],{"class":3801},"    \"Count\"",[3416,21433,3805],{"class":3795},[3416,21435,6614],{"class":3870},[3416,21437,21438],{"class":3418,"line":3480},[3416,21439,3507],{"class":3795},[3720,21441],{},[3348,21443,21445],{"id":21444},"частина-3-режими-керування-пропускною-здатністю-capacity-modes","Частина 3: Режими керування пропускною здатністю (Capacity Modes)",[3353,21447,21448,21449,21452,21453,21456],{},"Одним із найбільш критичних архітектурних рішень при проектуванні систем на базі Amazon DynamoDB є вибір режиму керування обчислювальною ємністю. Цей параметр визначає не лише фінансову модель використання СУБД, а й механізми виділення фізичних ресурсів на рівні партицій, поведінку системи при непередбачуваних піках навантаження та стратегії автоматичного масштабування. DynamoDB пропонує два фундаментально різні підходи: ",[3363,21450,21451],{},"Provisioned Mode"," (режим резервування пропускної здатності) та ",[3363,21454,21455],{},"On-Demand Mode"," (режим оплати за фактичні запити).",[3403,21458,21459],{},[3406,21460,21462],{"className":3408,"code":21461,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Режими обчислювальної ємності DynamoDB\n\nrectangle \"Таблиця DynamoDB\" as table #E8F4FD\n\nrectangle \"Provisioned Mode (Резервування)\" as prov #D5E8D4 {\n  rectangle \"Read Capacity Units\\n(RCU)\" as rcu #82B366\n  rectangle \"Write Capacity Units\\n(WCU)\" as wcu #82B366\n  rectangle \"Application Auto Scaling\\n(Динамічне підлаштування)\" as as #B8D9A9\n}\n\nrectangle \"On-Demand Mode (За запитом)\" as od #FFF2CC {\n  rectangle \"Request Read Units\\n(RRU)\" as rru #D6B656\n  rectangle \"Request Write Units\\n(RWU)\" as rwu #D6B656\n  note right of rru : \"Плата виключно за\\nфактично виконані запити\"\n}\n\ntable --> prov : \"Фіксоване виділення\\nресурсів на годину\"\ntable --> od : \"Автоматичне виділення\\nресурсів під трафік\"\n\nnote bottom of prov\n  Оплата: $\u002FRCU\u002Fгод + $\u002FWCU\u002Fгод (фіксована)\n  Ризик: Обмеження (Throttling) при перевищенні лімітів\nend note\n\nnote bottom of od\n  Оплата: $\u002Fмільйон RRU + $\u002Fмільйон RWU\n  Ризик: Висока вартість при стабільному передбачуваному навантаженні\nend note\n@enduml\n",[3413,21463,21464,21468,21472,21476,21480,21484,21489,21493,21498,21502,21507,21512,21517,21522,21526,21530,21535,21540,21545,21550,21554,21558,21563,21568,21572,21577,21582,21587,21591,21595,21600,21605,21610,21614],{"__ignoreMap":3411},[3416,21465,21466],{"class":3418,"line":3419},[3416,21467,3422],{},[3416,21469,21470],{"class":3418,"line":3425},[3416,21471,16755],{},[3416,21473,21474],{"class":3418,"line":3431},[3416,21475,16760],{},[3416,21477,21478],{"class":3418,"line":3437},[3416,21479,16765],{},[3416,21481,21482],{"class":3418,"line":3444},[3416,21483,3441],{"emptyLinePlaceholder":3440},[3416,21485,21486],{"class":3418,"line":3450},[3416,21487,21488],{},"title Режими обчислювальної ємності DynamoDB\n",[3416,21490,21491],{"class":3418,"line":3456},[3416,21492,3441],{"emptyLinePlaceholder":3440},[3416,21494,21495],{"class":3418,"line":3462},[3416,21496,21497],{},"rectangle \"Таблиця DynamoDB\" as table #E8F4FD\n",[3416,21499,21500],{"class":3418,"line":3468},[3416,21501,3441],{"emptyLinePlaceholder":3440},[3416,21503,21504],{"class":3418,"line":3474},[3416,21505,21506],{},"rectangle \"Provisioned Mode (Резервування)\" as prov #D5E8D4 {\n",[3416,21508,21509],{"class":3418,"line":3480},[3416,21510,21511],{},"  rectangle \"Read Capacity Units\\n(RCU)\" as rcu #82B366\n",[3416,21513,21514],{"class":3418,"line":3486},[3416,21515,21516],{},"  rectangle \"Write Capacity Units\\n(WCU)\" as wcu #82B366\n",[3416,21518,21519],{"class":3418,"line":3492},[3416,21520,21521],{},"  rectangle \"Application Auto Scaling\\n(Динамічне підлаштування)\" as as #B8D9A9\n",[3416,21523,21524],{"class":3418,"line":3498},[3416,21525,3507],{},[3416,21527,21528],{"class":3418,"line":3504},[3416,21529,3441],{"emptyLinePlaceholder":3440},[3416,21531,21532],{"class":3418,"line":3510},[3416,21533,21534],{},"rectangle \"On-Demand Mode (За запитом)\" as od #FFF2CC {\n",[3416,21536,21537],{"class":3418,"line":3515},[3416,21538,21539],{},"  rectangle \"Request Read Units\\n(RRU)\" as rru #D6B656\n",[3416,21541,21542],{"class":3418,"line":3521},[3416,21543,21544],{},"  rectangle \"Request Write Units\\n(RWU)\" as rwu #D6B656\n",[3416,21546,21547],{"class":3418,"line":3527},[3416,21548,21549],{},"  note right of rru : \"Плата виключно за\\nфактично виконані запити\"\n",[3416,21551,21552],{"class":3418,"line":3533},[3416,21553,3507],{},[3416,21555,21556],{"class":3418,"line":3539},[3416,21557,3441],{"emptyLinePlaceholder":3440},[3416,21559,21560],{"class":3418,"line":3545},[3416,21561,21562],{},"table --> prov : \"Фіксоване виділення\\nресурсів на годину\"\n",[3416,21564,21565],{"class":3418,"line":3551},[3416,21566,21567],{},"table --> od : \"Автоматичне виділення\\nресурсів під трафік\"\n",[3416,21569,21570],{"class":3418,"line":3557},[3416,21571,3441],{"emptyLinePlaceholder":3440},[3416,21573,21574],{"class":3418,"line":3563},[3416,21575,21576],{},"note bottom of prov\n",[3416,21578,21579],{"class":3418,"line":3569},[3416,21580,21581],{},"  Оплата: $\u002FRCU\u002Fгод + $\u002FWCU\u002Fгод (фіксована)\n",[3416,21583,21584],{"class":3418,"line":3574},[3416,21585,21586],{},"  Ризик: Обмеження (Throttling) при перевищенні лімітів\n",[3416,21588,21589],{"class":3418,"line":3579},[3416,21590,5088],{},[3416,21592,21593],{"class":3418,"line":3584},[3416,21594,3441],{"emptyLinePlaceholder":3440},[3416,21596,21597],{"class":3418,"line":3590},[3416,21598,21599],{},"note bottom of od\n",[3416,21601,21602],{"class":3418,"line":3596},[3416,21603,21604],{},"  Оплата: $\u002Fмільйон RRU + $\u002Fмільйон RWU\n",[3416,21606,21607],{"class":3418,"line":3602},[3416,21608,21609],{},"  Ризик: Висока вартість при стабільному передбачуваному навантаженні\n",[3416,21611,21612],{"class":3418,"line":3608},[3416,21613,5088],{},[3416,21615,21616],{"class":3418,"line":3614},[3416,21617,3718],{},[3720,21619],{},[3727,21621,21623],{"id":21622},"provisioned-mode-резервування-обчислювальних-ресурсів","Provisioned Mode — резервування обчислювальних ресурсів",[3353,21625,21626,21627,21630,21631,21634,21635,21638],{},"У режимі ",[3363,21628,21629],{},"Provisioned"," архітектор заздалегідь визначає обсяг обчислювальної потужності таблиці, виражений в одиницях пропускної здатності читання (",[3363,21632,21633],{},"RCU",") та запису (",[3363,21636,21637],{},"WCU","). AWS резервує ці ресурси на фізичному рівні (виділяючи відповідну кількість партицій та обчислювальних потужностей на вузлах збереження даних) та підтримує їх у стані постійної готовності. Оплата нараховується за кожну годину резервування, незалежно від того, чи виконувалися запити до таблиці.",[4584,21640,21642],{"id":21641},"математична-модель-тарифікації-на-прикладі-регіону-eu-central-1","Математична модель тарифікації (на прикладі регіону eu-central-1):",[3353,21644,21645],{},"Вартість резервування розраховується за наступними базовими ставками:",[4488,21647,21648,21654],{},[3377,21649,21650,21653],{},[3363,21651,21652],{},"1 RCU:"," ≈ 0.00013 USD за годину (що становить приблизно 0.095 USD на місяць).",[3377,21655,21656,21659],{},[3363,21657,21658],{},"1 WCU:"," ≈ 0.00065 USD за годину (що становить приблизно 0.474 USD на місяць).",[3353,21661,21662],{},"При резервуванні 100 WCU та 200 RCU щомісячна вартість утримання таблиці (без врахування вартості збереження даних) становитиме:",[13667,21664,21665],{},"\\text{Вартість} = (100 \\times 0.00065 + 200 \\times 0.00013) \\times 24 \\times 30 = 65.52\\text{ USD\u002Fмісяць}",[4584,21667,21669],{"id":21668},"механізм-обмеження-пропускної-здатності-throttling","Механізм обмеження пропускної здатності (Throttling)",[3353,21671,21672,21673,21675],{},"Якщо обсяг вхідних запитів за секунду перевищує сумарно зарезервовану ємність, DynamoDB ініціює механізм захисту ресурсів, повертаючи клієнту виняток ",[3413,21674,16738],{}," (HTTP статус 400).",[3353,21677,21678],{},"Під капотом цей процес працює так:",[3374,21680,21681,21687,21693],{},[3377,21682,21683,21686],{},[3363,21684,21685],{},"Генерація винятку:"," Запит відхиляється на рівні Request Router ще до моменту виконання операції на вузлі партиції, що запобігає перевантаженню сховища.",[3377,21688,21689,21692],{},[3363,21690,21691],{},"Клієнтська обробка (Retry & Backoff):"," Офіційні клієнтські бібліотеки AWS SDK містять вбудовані обробники цього винятку. Вони автоматично повторюють запит, використовуючи алгоритм експоненціальної затримки з додаванням випадкового шуму (Exponential Backoff з Full Jitter). Це запобігає ефекту \"лавини ретраїв\" (retry storm), коли клієнти синхронно перевантажують базу даних повторними запитами.",[3377,21694,21695,21698],{},[3363,21696,21697],{},"Вплив на затримку (Latency):"," Незважаючи на автоматичне відновлення, повторні спроби збільшують загальний час відповіді системи (Round Trip Time, RTT) для кінцевого користувача.",[4584,21700,21702],{"id":21701},"механізм-burst-capacity-імпульсна-ємність","Механізм Burst Capacity (Імпульсна ємність)",[3353,21704,21705,21706,4043],{},"Для згладжування короткочасних стрибків трафіку DynamoDB використовує алгоритм маркерного кошика (Token Bucket) під назвою ",[3363,21707,21708],{},"Burst Capacity",[4488,21710,21711,21717],{},[3377,21712,21713,21716],{},[3363,21714,21715],{},"Накопичення ресурсів:"," Якщо реальне споживання пропускної здатності таблиці є нижчим за ліміт (u(t) \u003C C, де C — зарезервована ємність), невикористані одиниці ємності акумулюються в спеціальному пулі (кошику).",[3377,21718,21719,21722,21723,21726],{},[3363,21720,21721],{},"Обмеження об'єму кошика:"," Максимальний об'єм накопичених токенів обмежений часовим інтервалом у ",[3363,21724,21725],{},"5 хвилин"," (300 секунд). Формально, максимальний запас токенів T_max дорівнює:",[13667,21728,21729],{},"T_{\\max} = 300 \\times C",[4488,21731,21732,21738],{},[3377,21733,21734,21737],{},[3363,21735,21736],{},"Використання імпульсу:"," При різкому стрибку навантаження, що перевищує C, Request Router починає списувати токени з пулу Burst Capacity, дозволяючи додатку виконувати запити без помилок throttling.",[3377,21739,21740,21743,21744,21747],{},[3363,21741,21742],{},"Обмеження гарантій:"," Burst Capacity є сервісом з рівнем доступності ",[4091,21745,21746],{},"Best Effort",". AWS не гарантує надання накопиченої ємності, якщо запити концентруються на одній фізичній партиції (викликаючи Hot Partition) або якщо фізичний вузол, на якому розміщено партицію, перевантажений іншими клієнтами (noisy neighbor effect).",[3403,21749,21750],{},[3406,21751,21753],{"className":3408,"code":21752,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Схема роботи механізму Burst Capacity\n\nrectangle \"Часова шкала життєвого циклу (інтервал 5 хв)\" {\n  rectangle \"0:00–2:00 (Накопичення)\\nСпоживання: 50 WCU\\nРезерв: 100 WCU\\nПул: +50 WCU\u002Fсек × 120 сек = 6000 токенів\" as t1 #D5E8D4\n  rectangle \"2:01–2:30 (Імпульс)\\nСпоживання: 300 WCU\\nРезерв: 100 WCU\\nПул покриває дефіцит 200 WCU\u002Fсек\" as t2 #FFF2CC\n  rectangle \"2:31+ (Вичерпання)\\nПул порожній\\nБудь-який запис > 100 WCU\\nвикликає Throttling\" as t3 #F8CECC\n}\n\nt1 -right-> t2\nt2 -right-> t3\n@enduml\n",[3413,21754,21755,21759,21763,21767,21771,21775,21780,21784,21789,21794,21799,21804,21808,21812,21817,21822],{"__ignoreMap":3411},[3416,21756,21757],{"class":3418,"line":3419},[3416,21758,3422],{},[3416,21760,21761],{"class":3418,"line":3425},[3416,21762,16755],{},[3416,21764,21765],{"class":3418,"line":3431},[3416,21766,16760],{},[3416,21768,21769],{"class":3418,"line":3437},[3416,21770,16765],{},[3416,21772,21773],{"class":3418,"line":3444},[3416,21774,3441],{"emptyLinePlaceholder":3440},[3416,21776,21777],{"class":3418,"line":3450},[3416,21778,21779],{},"title Схема роботи механізму Burst Capacity\n",[3416,21781,21782],{"class":3418,"line":3456},[3416,21783,3441],{"emptyLinePlaceholder":3440},[3416,21785,21786],{"class":3418,"line":3462},[3416,21787,21788],{},"rectangle \"Часова шкала життєвого циклу (інтервал 5 хв)\" {\n",[3416,21790,21791],{"class":3418,"line":3468},[3416,21792,21793],{},"  rectangle \"0:00–2:00 (Накопичення)\\nСпоживання: 50 WCU\\nРезерв: 100 WCU\\nПул: +50 WCU\u002Fсек × 120 сек = 6000 токенів\" as t1 #D5E8D4\n",[3416,21795,21796],{"class":3418,"line":3474},[3416,21797,21798],{},"  rectangle \"2:01–2:30 (Імпульс)\\nСпоживання: 300 WCU\\nРезерв: 100 WCU\\nПул покриває дефіцит 200 WCU\u002Fсек\" as t2 #FFF2CC\n",[3416,21800,21801],{"class":3418,"line":3480},[3416,21802,21803],{},"  rectangle \"2:31+ (Вичерпання)\\nПул порожній\\nБудь-який запис > 100 WCU\\nвикликає Throttling\" as t3 #F8CECC\n",[3416,21805,21806],{"class":3418,"line":3486},[3416,21807,3507],{},[3416,21809,21810],{"class":3418,"line":3492},[3416,21811,3441],{"emptyLinePlaceholder":3440},[3416,21813,21814],{"class":3418,"line":3498},[3416,21815,21816],{},"t1 -right-> t2\n",[3416,21818,21819],{"class":3418,"line":3504},[3416,21820,21821],{},"t2 -right-> t3\n",[3416,21823,21824],{"class":3418,"line":3510},[3416,21825,3718],{},[3720,21827],{},[3727,21829,21831],{"id":21830},"динамічне-масштабування-auto-scaling-у-provisioned-mode","Динамічне масштабування (Auto Scaling) у Provisioned Mode",[3353,21833,21834,21835,21838],{},"Для мінімізації ручного керування та запобігання надлишковим витратам режим Provisioned інтегрується з сервісом ",[3363,21836,21837],{},"AWS Application Auto Scaling",". Цей механізм автоматично коригує зарезервовану ємність таблиці у відповідь на динаміку реального трафіку.",[4584,21840,21842],{"id":21841},"архітектура-взаємодії-компонентів","Архітектура взаємодії компонентів:",[3374,21844,21845,21858,21864],{},[3377,21846,21847,21850,21851,4384,21854,21857],{},[3363,21848,21849],{},"Моніторинг метрик:"," DynamoDB кожну хвилину надсилає метрики використання ємності (",[3413,21852,21853],{},"ConsumedReadCapacityUnits",[3413,21855,21856],{},"ConsumedWriteCapacityUnits",") до Amazon CloudWatch.",[3377,21859,21860,21863],{},[3363,21861,21862],{},"CloudWatch Alarms:"," На основі конфігурації Auto Scaling створюються два триггери (Alarms): один для масштабування вгору (Scale-out), інший — для масштабування вниз (Scale-in). Вони активуються, коли середнє споживання ємності за певний проміжок часу відхиляється від встановленого цільового показника (Target Utilization, зазвичай 70%).",[3377,21865,21866,21869,21870,21872,21873,4043],{},[3363,21867,21868],{},"Application Auto Scaling:"," При спрацьовуванні CloudWatch Alarm сервіс Auto Scaling викликає API-метод DynamoDB ",[3413,21871,17207],{}," для зміни параметрів ",[3413,21874,21875],{},"ProvisionedThroughput",[3403,21877,21878],{},[3406,21879,21881],{"className":3408,"code":21880,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Архітектура та життєвий цикл DynamoDB Auto Scaling\n\nparticipant \"Клієнтський додаток\" as app\nparticipant \"Таблиця DynamoDB\" as ddb\nparticipant \"Amazon CloudWatch\" as cw\nparticipant \"Application Auto Scaling\" as aas\n\napp -> ddb : Виконання запитів (зростання трафіку)\nddb -> cw : Публікація метрики ConsumedWriteCapacityUnits\ncw -> aas : Активація Alarm: Споживання > 70% від ліміту\naas -> ddb : Виклик UpdateTable (збільшення WCU)\nddb -> app : Ліміти розширено, Throttling припинено\n\nnote right of aas\n  **Періоди затримки (Cooldowns):**\n  * Scale-out Cooldown: 0-30 сек (миттєве розширення)\n  * Scale-in Cooldown: 900 сек (захист від осциляції лімітів)\n  end note\n@enduml\n",[3413,21882,21883,21887,21891,21895,21899,21903,21908,21912,21917,21922,21927,21932,21936,21941,21946,21951,21956,21961,21965,21970,21975,21980,21985,21990],{"__ignoreMap":3411},[3416,21884,21885],{"class":3418,"line":3419},[3416,21886,3422],{},[3416,21888,21889],{"class":3418,"line":3425},[3416,21890,16755],{},[3416,21892,21893],{"class":3418,"line":3431},[3416,21894,16760],{},[3416,21896,21897],{"class":3418,"line":3437},[3416,21898,16765],{},[3416,21900,21901],{"class":3418,"line":3444},[3416,21902,3441],{"emptyLinePlaceholder":3440},[3416,21904,21905],{"class":3418,"line":3450},[3416,21906,21907],{},"title Архітектура та життєвий цикл DynamoDB Auto Scaling\n",[3416,21909,21910],{"class":3418,"line":3456},[3416,21911,3441],{"emptyLinePlaceholder":3440},[3416,21913,21914],{"class":3418,"line":3462},[3416,21915,21916],{},"participant \"Клієнтський додаток\" as app\n",[3416,21918,21919],{"class":3418,"line":3468},[3416,21920,21921],{},"participant \"Таблиця DynamoDB\" as ddb\n",[3416,21923,21924],{"class":3418,"line":3474},[3416,21925,21926],{},"participant \"Amazon CloudWatch\" as cw\n",[3416,21928,21929],{"class":3418,"line":3480},[3416,21930,21931],{},"participant \"Application Auto Scaling\" as aas\n",[3416,21933,21934],{"class":3418,"line":3486},[3416,21935,3441],{"emptyLinePlaceholder":3440},[3416,21937,21938],{"class":3418,"line":3492},[3416,21939,21940],{},"app -> ddb : Виконання запитів (зростання трафіку)\n",[3416,21942,21943],{"class":3418,"line":3498},[3416,21944,21945],{},"ddb -> cw : Публікація метрики ConsumedWriteCapacityUnits\n",[3416,21947,21948],{"class":3418,"line":3504},[3416,21949,21950],{},"cw -> aas : Активація Alarm: Споживання > 70% від ліміту\n",[3416,21952,21953],{"class":3418,"line":3510},[3416,21954,21955],{},"aas -> ddb : Виклик UpdateTable (збільшення WCU)\n",[3416,21957,21958],{"class":3418,"line":3515},[3416,21959,21960],{},"ddb -> app : Ліміти розширено, Throttling припинено\n",[3416,21962,21963],{"class":3418,"line":3521},[3416,21964,3441],{"emptyLinePlaceholder":3440},[3416,21966,21967],{"class":3418,"line":3527},[3416,21968,21969],{},"note right of aas\n",[3416,21971,21972],{"class":3418,"line":3533},[3416,21973,21974],{},"  **Періоди затримки (Cooldowns):**\n",[3416,21976,21977],{"class":3418,"line":3539},[3416,21978,21979],{},"  * Scale-out Cooldown: 0-30 сек (миттєве розширення)\n",[3416,21981,21982],{"class":3418,"line":3545},[3416,21983,21984],{},"  * Scale-in Cooldown: 900 сек (захист від осциляції лімітів)\n",[3416,21986,21987],{"class":3418,"line":3551},[3416,21988,21989],{},"  end note\n",[3416,21991,21992],{"class":3418,"line":3557},[3416,21993,3718],{},[4584,21995,21997],{"id":21996},"ковзні-інтервали-та-запобігання-осциляції-flapping","Ковзні інтервали та запобігання осциляції (Flapping)",[4488,21999,22000,22010],{},[3377,22001,22002,22005,22006,22009],{},[3363,22003,22004],{},"Scale-out (Масштабування вгору):"," Виконується максимально оперативно. Коли споживання перевищує цільове значення протягом кількох хвилин, ліміти збільшуються. Параметр ",[4091,22007,22008],{},"Scale-out cooldown"," зазвичай встановлюється в 0 секунд, дозволяючи миттєву реакцію на зростання трафіку.",[3377,22011,22012,22015,22016,22019,22020,22023],{},[3363,22013,22014],{},"Scale-in (Масштабування вниз):"," Здійснюється консервативно. Зменшення лімітів ініціюється лише тоді, коли навантаження стабільно тримається нижче цільового рівня протягом тривалого часу. Параметр ",[4091,22017,22018],{},"Scale-in cooldown"," за замовчуванням дорівнює ",[3363,22021,22022],{},"900 секундам"," (15 хвилинам). Це запобігає ефекту \"флаппінгу\" (flapping) — постійного перемикання ємності туди-сюди при короткочасних спадах трафіку, що могло б призвести до штучного дефіциту ресурсів при повторному стрибку.",[3720,22025],{},[3727,22027,22029],{"id":22028},"on-demand-mode-оплата-за-фактично-оброблені-запити","On-Demand Mode — оплата за фактично оброблені запити",[3353,22031,22032,22033,22036,22037,5167,22040,22043],{},"Режим ",[3363,22034,22035],{},"On-Demand"," повністю абстрагує поняття планування ємності. Замість резервування віртуальних каналів зв'язку, користувач оплачує кожен успішно виконаний запит читання чи запису, виражений в ",[3363,22038,22039],{},"Request Read Units (RRU)",[3363,22041,22042],{},"Request Write Units (RWU)",". Розмірність та правила округлення для RRU\u002FRWU є повністю аналогічними до RCU\u002FWCU (читання блоками по 4 KB, запис блоками по 1 KB).",[4584,22045,22047],{"id":22046},"вартість-використання-on-demand-на-прикладі-регіону-eu-central-1","Вартість використання On-Demand (на прикладі регіону eu-central-1):",[4488,22049,22050,22056],{},[3377,22051,22052,22055],{},[3363,22053,22054],{},"1 мільйон RRU:"," ≈ 0.284 USD",[3377,22057,22058,22061],{},[3363,22059,22060],{},"1 мільйон RWU:"," ≈ 1.42 USD",[4584,22063,22065],{"id":22064},"алгоритм-автоматичного-масштабування-під-капом","Алгоритм автоматичного масштабування під капом",[3353,22067,22068],{},"On-Demand не потребує налаштування тригерів масштабування. Проте, важливо розуміти фізичні обмеження масштабованості:",[3374,22070,22071,22077,22083],{},[3377,22072,22073,22076],{},[3363,22074,22075],{},"Історичний пік (Peak Capacity):"," DynamoDB гарантує миттєве обслуговування трафіку, який не перевищує подвоєне значення максимального навантаження за останні 30 хвилин. Наприклад, якщо таблиця успішно обробила пік у 10 000 RPS, вона може безпосередньо з цього моменту обробити до 20 000 RPS.",[3377,22078,22079,22082],{},[3363,22080,22081],{},"Поділ партицій при перевищенні піку:"," Якщо навантаження перевищує 2 × Peak, DynamoDB запускає фоновий процес поділу партицій (Partition Splitting) для горизонтального розширення сховища та обчислювальних ресурсів. Під час цього процесу (який може тривати до кількох хвилин) запити, що виходять за межі подвоєного піку, можуть зазнавати тимчасового throttling.",[3377,22084,22085,22088],{},[3363,22086,22087],{},"Стартові ліміти:"," Для абсолютно нової таблиці в режимі On-Demand встановлено ліміти у 4000 Write Requests\u002Fsec та 12 000 Read Requests\u002Fsec. Ці обмеження автоматично піднімаються в міру зростання реального трафіку.",[3720,22090],{},[3727,22092,22094],{"id":22093},"порівняльна-характеристика-режимів-ємності","Порівняльна характеристика режимів ємності",[3756,22096,22097,22109],{},[4617,22098,22099],{},[4620,22100,22101,22104,22107],{},[4623,22102,22103],{"align":4625},"Критерій порівняння",[4623,22105,22106],{"align":4625},"Provisioned Mode (+ Auto Scaling)",[4623,22108,21455],{"align":4625},[4657,22110,22111,22124,22137,22150,22163,22176],{},[4620,22112,22113,22118,22121],{},[4662,22114,22115],{"align":4625},[3363,22116,22117],{},"Характер тарифікації",[4662,22119,22120],{"align":4625},"Погодинна плата за зарезервовану ємність",[4662,22122,22123],{"align":4625},"Плата за фактичну кількість виконаних запитів",[4620,22125,22126,22131,22134],{},[4662,22127,22128],{"align":4625},[3363,22129,22130],{},"Реакція на різкі стрибки",[4662,22132,22133],{"align":4625},"З затримкою 5–15 хв (поки відпрацює Auto Scaling)",[4662,22135,22136],{"align":4625},"Миттєва (у межах подвоєного історичного піку)",[4620,22138,22139,22144,22147],{},[4662,22140,22141],{"align":4625},[3363,22142,22143],{},"Фінансова ефективність",[4662,22145,22146],{"align":4625},"Максимальна при стабільному, прогнозованому трафіку",[4662,22148,22149],{"align":4625},"Оптимальна при нерівномірному, непередбачуваному трафіку",[4620,22151,22152,22157,22160],{},[4662,22153,22154],{"align":4625},[3363,22155,22156],{},"Ризик виникнення Throttling",[4662,22158,22159],{"align":4625},"Присутній під час різких переходів навантаження",[4662,22161,22162],{"align":4625},"Майже відсутній (окрім екстремальних стрибків)",[4620,22164,22165,22170,22173],{},[4662,22166,22167],{"align":4625},[3363,22168,22169],{},"Адміністративні витрати",[4662,22171,22172],{"align":4625},"Потребує аналізу профілю навантаження та налаштування лімітів",[4662,22174,22175],{"align":4625},"Повний \"Zero Ops\" — не потребує втручання",[4620,22177,22178,22183,22186],{},[4662,22179,22180],{"align":4625},[3363,22181,22182],{},"Рекомендовано для",[4662,22184,22185],{"align":4625},"Production-середовищ зі стабільними добовими циклами",[4662,22187,22188],{"align":4625},"MVP, розробки, тестування, систем з імпульсним трафіком",[3720,22190],{},[3727,22192,22194],{"id":22193},"стратегія-перемикання-між-режимами","Стратегія перемикання між режимами",[3403,22196,22197],{},[3406,22198,22200],{"className":3408,"code":22199,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Алгоритм вибору режиму керування ємністю\n\nstart\n\nif (Таблиця використовується для тестування, MVP чи розробки?) then (так)\n  :Вибрати On-Demand Mode\\n(мінімізація адміністрування та базових витрат);\n  stop\nelse (ні)\n  if (Профіль навантаження є стабільним або прогнозованим?) then (так)\n    :Вибрати Provisioned Mode + Auto Scaling\\n(Оптимізація витрат, ціль: 70% утилізації);\n    stop\n  else (ні)\n    if (Зростання трафіку перевищує 2х за 5 хвилин?) then (так)\n      :Вибрати On-Demand Mode\\n(Уникнення затримок масштабування Auto Scaling);\n      stop\n    else (ні)\n      :Вибрати Provisioned Mode + Auto Scaling\\nз широким діапазоном min\u002Fmax ємностей;\n      stop\n    endif\n  endif\nendif\n@enduml\n",[3413,22201,22202,22206,22210,22214,22218,22222,22227,22231,22235,22239,22244,22249,22253,22257,22262,22267,22271,22275,22280,22285,22289,22293,22298,22302,22306,22310,22314],{"__ignoreMap":3411},[3416,22203,22204],{"class":3418,"line":3419},[3416,22205,3422],{},[3416,22207,22208],{"class":3418,"line":3425},[3416,22209,16755],{},[3416,22211,22212],{"class":3418,"line":3431},[3416,22213,16760],{},[3416,22215,22216],{"class":3418,"line":3437},[3416,22217,16765],{},[3416,22219,22220],{"class":3418,"line":3444},[3416,22221,3441],{"emptyLinePlaceholder":3440},[3416,22223,22224],{"class":3418,"line":3450},[3416,22225,22226],{},"title Алгоритм вибору режиму керування ємністю\n",[3416,22228,22229],{"class":3418,"line":3456},[3416,22230,3441],{"emptyLinePlaceholder":3440},[3416,22232,22233],{"class":3418,"line":3462},[3416,22234,18894],{},[3416,22236,22237],{"class":3418,"line":3468},[3416,22238,3441],{"emptyLinePlaceholder":3440},[3416,22240,22241],{"class":3418,"line":3474},[3416,22242,22243],{},"if (Таблиця використовується для тестування, MVP чи розробки?) then (так)\n",[3416,22245,22246],{"class":3418,"line":3480},[3416,22247,22248],{},"  :Вибрати On-Demand Mode\\n(мінімізація адміністрування та базових витрат);\n",[3416,22250,22251],{"class":3418,"line":3486},[3416,22252,19012],{},[3416,22254,22255],{"class":3418,"line":3492},[3416,22256,19002],{},[3416,22258,22259],{"class":3418,"line":3498},[3416,22260,22261],{},"  if (Профіль навантаження є стабільним або прогнозованим?) then (так)\n",[3416,22263,22264],{"class":3418,"line":3504},[3416,22265,22266],{},"    :Вибрати Provisioned Mode + Auto Scaling\\n(Оптимізація витрат, ціль: 70% утилізації);\n",[3416,22268,22269],{"class":3418,"line":3510},[3416,22270,18992],{},[3416,22272,22273],{"class":3418,"line":3515},[3416,22274,18982],{},[3416,22276,22277],{"class":3418,"line":3521},[3416,22278,22279],{},"    if (Зростання трафіку перевищує 2х за 5 хвилин?) then (так)\n",[3416,22281,22282],{"class":3418,"line":3527},[3416,22283,22284],{},"      :Вибрати On-Demand Mode\\n(Уникнення затримок масштабування Auto Scaling);\n",[3416,22286,22287],{"class":3418,"line":3533},[3416,22288,18928],{},[3416,22290,22291],{"class":3418,"line":3539},[3416,22292,18933],{},[3416,22294,22295],{"class":3418,"line":3545},[3416,22296,22297],{},"      :Вибрати Provisioned Mode + Auto Scaling\\nз широким діапазоном min\u002Fmax ємностей;\n",[3416,22299,22300],{"class":3418,"line":3551},[3416,22301,18928],{},[3416,22303,22304],{"class":3418,"line":3557},[3416,22305,18977],{},[3416,22307,22308],{"class":3418,"line":3563},[3416,22309,18997],{},[3416,22311,22312],{"class":3418,"line":3569},[3416,22313,19017],{},[3416,22315,22316],{"class":3418,"line":3574},[3416,22317,3718],{},[22319,22320,22321],"blockquote",{},[3353,22322,22323,22326,22329,22330,4043],{},[3416,22324,22325],{},"!WARNING",[3363,22327,22328],{},"Обмеження на перемикання режимів","\nЗміна режиму з Provisioned на On-Demand (і навпаки) дозволяється не частіше ніж ",[3363,22331,22332],{},"один раз на 24 години",[4584,22334,22336],{"id":22335},"стратегія-проведення-навантажувального-тестування-load-testing","Стратегія проведення навантажувального тестування (Load Testing):",[3353,22338,22339],{},"Якщо планується масштабне тестування системи або очікується маркетинговий реліз (наприклад, Black Friday), використання On-Demand для нової таблиці може викликати throttling через низький стартовий ліміт. Рекомендована стратегія:",[3374,22341,22342,22347,22350,22353],{},[3377,22343,22344,22345,4043],{},"Тимчасово перевести таблицю в режим ",[3363,22346,21629],{},[3377,22348,22349],{},"Встановити вручну високі показники ємності (наприклад, 10 000 WCU та 20 000 RCU), що змусить DynamoDB миттєво виділити необхідну кількість фізичних партицій (\"прогріти таблицю\").",[3377,22351,22352],{},"Провести тестування.",[3377,22354,22355,22356,22358],{},"Повернути таблицю в режим ",[3363,22357,22035],{}," (або знизити Provisioned ліміти) для повсякденної експлуатації.",[3720,22360],{},[3727,22362,22364],{"id":22363},"налаштування-режимів-ємності-через-інтерфейси-керування","Налаштування режимів ємності через інтерфейси керування",[6308,22366,22367,22722,23479],{},[6311,22368,22369],{"label":6313},[3406,22370,22372],{"className":6316,"code":22371,"language":6318,"meta":3411,"style":3411},"# ── Створення нової таблиці в режимі On-Demand (PAY_PER_REQUEST) ─────────────\naws dynamodb create-table \\\n    --table-name Orders \\\n    --attribute-definitions \\\n        AttributeName=CustomerId,AttributeType=S \\\n        AttributeName=OrderId,AttributeType=S \\\n    --key-schema \\\n        AttributeName=CustomerId,KeyType=HASH \\\n        AttributeName=OrderId,KeyType=RANGE \\\n    --billing-mode PAY_PER_REQUEST \\\n    --region eu-central-1\n\n# ── Переведення існуючої таблиці в режим Provisioned з базовими лімітами ──────\naws dynamodb update-table \\\n    --table-name Orders \\\n    --billing-mode PROVISIONED \\\n    --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=50 \\\n    --region eu-central-1\n\n# ── Реєстрація таблиці як об'єкта масштабування для WCU в Auto Scaling ───────\naws application-autoscaling register-scalable-target \\\n    --service-namespace dynamodb \\\n    --resource-id \"table\u002FOrders\" \\\n    --scalable-dimension \"dynamodb:table:WriteCapacityUnits\" \\\n    --min-capacity 10 \\\n    --max-capacity 500 \\\n    --region eu-central-1\n\n# ── Створення політики відстеження цільового використання (Target Tracking) ──\naws application-autoscaling put-scaling-policy \\\n    --service-namespace dynamodb \\\n    --resource-id \"table\u002FOrders\" \\\n    --scalable-dimension \"dynamodb:table:WriteCapacityUnits\" \\\n    --policy-name \"Orders-WCU-Scaling-Policy\" \\\n    --policy-type TargetTrackingScaling \\\n    --target-tracking-scaling-policy-configuration '{\n        \"TargetValue\": 70.0,\n        \"PredefinedMetricSpecification\": {\n            \"PredefinedMetricType\": \"DynamoDBWriteCapacityUtilization\"\n        }\n    }' \\\n    --region eu-central-1\n\n# ── Повернення таблиці в режим оплати за фактичні запити (On-Demand) ─────────\naws dynamodb update-table \\\n    --table-name Orders \\\n    --billing-mode PAY_PER_REQUEST \\\n    --region eu-central-1\n",[3413,22373,22374,22379,22389,22397,22403,22409,22416,22422,22428,22435,22443,22449,22453,22458,22468,22476,22485,22497,22503,22507,22512,22524,22533,22543,22553,22563,22573,22579,22583,22588,22599,22607,22615,22623,22633,22643,22650,22655,22660,22665,22669,22675,22681,22685,22690,22700,22708,22716],{"__ignoreMap":3411},[3416,22375,22376],{"class":3418,"line":3419},[3416,22377,22378],{"class":3789},"# ── Створення нової таблиці в режимі On-Demand (PAY_PER_REQUEST) ─────────────\n",[3416,22380,22381,22383,22385,22387],{"class":3418,"line":3425},[3416,22382,6331],{"class":6330},[3416,22384,6334],{"class":3808},[3416,22386,10696],{"class":3808},[3416,22388,6341],{"class":6340},[3416,22390,22391,22393,22395],{"class":3418,"line":3431},[3416,22392,6346],{"class":4368},[3416,22394,19317],{"class":3808},[3416,22396,6341],{"class":6340},[3416,22398,22399,22401],{"class":3418,"line":3437},[3416,22400,10711],{"class":4368},[3416,22402,6341],{"class":6340},[3416,22404,22405,22407],{"class":3418,"line":3444},[3416,22406,19330],{"class":3808},[3416,22408,6341],{"class":6340},[3416,22410,22411,22414],{"class":3418,"line":3450},[3416,22412,22413],{"class":3808},"        AttributeName=OrderId,AttributeType=S",[3416,22415,6341],{"class":6340},[3416,22417,22418,22420],{"class":3418,"line":3456},[3416,22419,10732],{"class":4368},[3416,22421,6341],{"class":6340},[3416,22423,22424,22426],{"class":3418,"line":3462},[3416,22425,19364],{"class":3808},[3416,22427,6341],{"class":6340},[3416,22429,22430,22433],{"class":3418,"line":3468},[3416,22431,22432],{"class":3808},"        AttributeName=OrderId,KeyType=RANGE",[3416,22434,6341],{"class":6340},[3416,22436,22437,22439,22441],{"class":3418,"line":3474},[3416,22438,10753],{"class":4368},[3416,22440,10756],{"class":3808},[3416,22442,6341],{"class":6340},[3416,22444,22445,22447],{"class":3418,"line":3480},[3416,22446,6366],{"class":4368},[3416,22448,6369],{"class":3808},[3416,22450,22451],{"class":3418,"line":3486},[3416,22452,3441],{"emptyLinePlaceholder":3440},[3416,22454,22455],{"class":3418,"line":3492},[3416,22456,22457],{"class":3789},"# ── Переведення існуючої таблиці в режим Provisioned з базовими лімітами ──────\n",[3416,22459,22460,22462,22464,22466],{"class":3418,"line":3498},[3416,22461,6331],{"class":6330},[3416,22463,6334],{"class":3808},[3416,22465,17279],{"class":3808},[3416,22467,6341],{"class":6340},[3416,22469,22470,22472,22474],{"class":3418,"line":3504},[3416,22471,6346],{"class":4368},[3416,22473,19317],{"class":3808},[3416,22475,6341],{"class":6340},[3416,22477,22478,22480,22483],{"class":3418,"line":3510},[3416,22479,10753],{"class":4368},[3416,22481,22482],{"class":3808}," PROVISIONED",[3416,22484,6341],{"class":6340},[3416,22486,22487,22490,22493,22495],{"class":3418,"line":3515},[3416,22488,22489],{"class":4368},"    --provisioned-throughput",[3416,22491,22492],{"class":3808}," ReadCapacityUnits=100,WriteCapacityUnits=",[3416,22494,17819],{"class":3870},[3416,22496,6341],{"class":6340},[3416,22498,22499,22501],{"class":3418,"line":3521},[3416,22500,6366],{"class":4368},[3416,22502,6369],{"class":3808},[3416,22504,22505],{"class":3418,"line":3527},[3416,22506,3441],{"emptyLinePlaceholder":3440},[3416,22508,22509],{"class":3418,"line":3533},[3416,22510,22511],{"class":3789},"# ── Реєстрація таблиці як об'єкта масштабування для WCU в Auto Scaling ───────\n",[3416,22513,22514,22516,22519,22522],{"class":3418,"line":3539},[3416,22515,6331],{"class":6330},[3416,22517,22518],{"class":3808}," application-autoscaling",[3416,22520,22521],{"class":3808}," register-scalable-target",[3416,22523,6341],{"class":6340},[3416,22525,22526,22529,22531],{"class":3418,"line":3545},[3416,22527,22528],{"class":4368},"    --service-namespace",[3416,22530,6334],{"class":3808},[3416,22532,6341],{"class":6340},[3416,22534,22535,22538,22541],{"class":3418,"line":3551},[3416,22536,22537],{"class":4368},"    --resource-id",[3416,22539,22540],{"class":3808}," \"table\u002FOrders\"",[3416,22542,6341],{"class":6340},[3416,22544,22545,22548,22551],{"class":3418,"line":3557},[3416,22546,22547],{"class":4368},"    --scalable-dimension",[3416,22549,22550],{"class":3808}," \"dynamodb:table:WriteCapacityUnits\"",[3416,22552,6341],{"class":6340},[3416,22554,22555,22558,22561],{"class":3418,"line":3563},[3416,22556,22557],{"class":4368},"    --min-capacity",[3416,22559,22560],{"class":3870}," 10",[3416,22562,6341],{"class":6340},[3416,22564,22565,22568,22571],{"class":3418,"line":3569},[3416,22566,22567],{"class":4368},"    --max-capacity",[3416,22569,22570],{"class":3870}," 500",[3416,22572,6341],{"class":6340},[3416,22574,22575,22577],{"class":3418,"line":3574},[3416,22576,6366],{"class":4368},[3416,22578,6369],{"class":3808},[3416,22580,22581],{"class":3418,"line":3579},[3416,22582,3441],{"emptyLinePlaceholder":3440},[3416,22584,22585],{"class":3418,"line":3584},[3416,22586,22587],{"class":3789},"# ── Створення політики відстеження цільового використання (Target Tracking) ──\n",[3416,22589,22590,22592,22594,22597],{"class":3418,"line":3590},[3416,22591,6331],{"class":6330},[3416,22593,22518],{"class":3808},[3416,22595,22596],{"class":3808}," put-scaling-policy",[3416,22598,6341],{"class":6340},[3416,22600,22601,22603,22605],{"class":3418,"line":3596},[3416,22602,22528],{"class":4368},[3416,22604,6334],{"class":3808},[3416,22606,6341],{"class":6340},[3416,22608,22609,22611,22613],{"class":3418,"line":3602},[3416,22610,22537],{"class":4368},[3416,22612,22540],{"class":3808},[3416,22614,6341],{"class":6340},[3416,22616,22617,22619,22621],{"class":3418,"line":3608},[3416,22618,22547],{"class":4368},[3416,22620,22550],{"class":3808},[3416,22622,6341],{"class":6340},[3416,22624,22625,22628,22631],{"class":3418,"line":3614},[3416,22626,22627],{"class":4368},"    --policy-name",[3416,22629,22630],{"class":3808}," \"Orders-WCU-Scaling-Policy\"",[3416,22632,6341],{"class":6340},[3416,22634,22635,22638,22641],{"class":3418,"line":3620},[3416,22636,22637],{"class":4368},"    --policy-type",[3416,22639,22640],{"class":3808}," TargetTrackingScaling",[3416,22642,6341],{"class":6340},[3416,22644,22645,22648],{"class":3418,"line":3626},[3416,22646,22647],{"class":4368},"    --target-tracking-scaling-policy-configuration",[3416,22649,6661],{"class":3808},[3416,22651,22652],{"class":3418,"line":3631},[3416,22653,22654],{"class":3808},"        \"TargetValue\": 70.0,\n",[3416,22656,22657],{"class":3418,"line":3636},[3416,22658,22659],{"class":3808},"        \"PredefinedMetricSpecification\": {\n",[3416,22661,22662],{"class":3418,"line":3641},[3416,22663,22664],{"class":3808},"            \"PredefinedMetricType\": \"DynamoDBWriteCapacityUtilization\"\n",[3416,22666,22667],{"class":3418,"line":3647},[3416,22668,8533],{"class":3808},[3416,22670,22671,22673],{"class":3418,"line":3653},[3416,22672,6686],{"class":3808},[3416,22674,6341],{"class":6340},[3416,22676,22677,22679],{"class":3418,"line":3659},[3416,22678,6366],{"class":4368},[3416,22680,6369],{"class":3808},[3416,22682,22683],{"class":3418,"line":3665},[3416,22684,3441],{"emptyLinePlaceholder":3440},[3416,22686,22687],{"class":3418,"line":3671},[3416,22688,22689],{"class":3789},"# ── Повернення таблиці в режим оплати за фактичні запити (On-Demand) ─────────\n",[3416,22691,22692,22694,22696,22698],{"class":3418,"line":3677},[3416,22693,6331],{"class":6330},[3416,22695,6334],{"class":3808},[3416,22697,17279],{"class":3808},[3416,22699,6341],{"class":6340},[3416,22701,22702,22704,22706],{"class":3418,"line":3683},[3416,22703,6346],{"class":4368},[3416,22705,19317],{"class":3808},[3416,22707,6341],{"class":6340},[3416,22709,22710,22712,22714],{"class":3418,"line":3688},[3416,22711,10753],{"class":4368},[3416,22713,10756],{"class":3808},[3416,22715,6341],{"class":6340},[3416,22717,22718,22720],{"class":3418,"line":3693},[3416,22719,6366],{"class":4368},[3416,22721,6369],{"class":3808},[6311,22723,22724],{"label":6372},[3406,22725,22727],{"className":6375,"code":22726,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\nusing Amazon.ApplicationAutoScaling;\nusing Amazon.ApplicationAutoScaling.Model;\n\nvar ddbClient = new AmazonDynamoDBClient(Amazon.RegionEndpoint.EUCentral1);\nvar scalingClient = new AmazonApplicationAutoScalingClient(Amazon.RegionEndpoint.EUCentral1);\n\n\u002F\u002F ── Ініціалізація нової таблиці в режимі On-Demand (PAY_PER_REQUEST) ────────\nawait ddbClient.CreateTableAsync(new CreateTableRequest\n{\n    TableName = \"Orders\",\n    AttributeDefinitions = new List\u003CAttributeDefinition>\n    {\n        new() { AttributeName = \"CustomerId\", AttributeType = ScalarAttributeType.S },\n        new() { AttributeName = \"OrderId\", AttributeType = ScalarAttributeType.S }\n    },\n    KeySchema = new List\u003CKeySchemaElement>\n    {\n        new() { AttributeName = \"CustomerId\", KeyType = KeyType.HASH },\n        new() { AttributeName = \"OrderId\", KeyType = KeyType.RANGE }\n    },\n    BillingMode = BillingMode.PAY_PER_REQUEST\n});\n\n\u002F\u002F ── Переведення таблиці на зарезервовану ємність (Provisioned Mode) ───────────\nawait ddbClient.UpdateTableAsync(new UpdateTableRequest\n{\n    TableName = \"Orders\",\n    BillingMode = BillingMode.PROVISIONED,\n    ProvisionedThroughput = new ProvisionedThroughput\n    {\n        ReadCapacityUnits = 100,\n        WriteCapacityUnits = 50\n    }\n});\n\n\u002F\u002F ── Налаштування масштабованого об'єкта в Application Auto Scaling ───────────\nawait scalingClient.RegisterScalableTargetAsync(new RegisterScalableTargetRequest\n{\n    ServiceNamespace = ServiceNamespace.Dynamodb,\n    ResourceId = \"table\u002FOrders\",\n    ScalableDimension = ScalableDimension.DynamodbTableWriteCapacityUnits,\n    MinCapacity = 10,\n    MaxCapacity = 500\n});\n\n\u002F\u002F ── Створення політики динамічного масштабування для WCU на рівні 70% ─────────\nawait scalingClient.PutScalingPolicyAsync(new PutScalingPolicyRequest\n{\n    ServiceNamespace = ServiceNamespace.Dynamodb,\n    ResourceId = \"table\u002FOrders\",\n    ScalableDimension = ScalableDimension.DynamodbTableWriteCapacityUnits,\n    PolicyName = \"Orders-WCU-AutoScaling-Policy\",\n    PolicyType = PolicyType.TargetTrackingScaling,\n    TargetTrackingScalingPolicyConfiguration = new TargetTrackingScalingPolicyConfiguration\n    {\n        TargetValue = 70.0,\n        PredefinedMetricSpecification = new PredefinedMetricSpecification\n        {\n            PredefinedMetricType = MetricType.DynamoDBWriteCapacityUtilization\n        }\n    }\n});\n\n\u002F\u002F ── Повернення таблиці до конфігурації On-Demand ──────────────────────────────\nawait ddbClient.UpdateTableAsync(new UpdateTableRequest\n{\n    TableName = \"Orders\",\n    BillingMode = BillingMode.PAY_PER_REQUEST\n});\n",[3413,22728,22729,22741,22757,22770,22786,22790,22820,22848,22852,22857,22873,22877,22887,22903,22907,22933,22959,22963,22979,22983,23009,23035,23039,23051,23055,23059,23064,23080,23084,23094,23109,23120,23124,23136,23145,23149,23153,23157,23162,23180,23184,23201,23213,23230,23241,23251,23255,23259,23264,23282,23286,23300,23310,23324,23336,23353,23365,23369,23381,23393,23397,23412,23416,23420,23424,23428,23433,23449,23453,23463,23475],{"__ignoreMap":3411},[3416,22730,22731,22733,22735,22737,22739],{"class":3418,"line":3419},[3416,22732,17433],{"class":11427},[3416,22734,17436],{"class":6397},[3416,22736,4043],{"class":3795},[3416,22738,17441],{"class":6397},[3416,22740,11594],{"class":3795},[3416,22742,22743,22745,22747,22749,22751,22753,22755],{"class":3418,"line":3425},[3416,22744,17433],{"class":11427},[3416,22746,17436],{"class":6397},[3416,22748,4043],{"class":3795},[3416,22750,17441],{"class":6397},[3416,22752,4043],{"class":3795},[3416,22754,17458],{"class":6397},[3416,22756,11594],{"class":3795},[3416,22758,22759,22761,22763,22765,22768],{"class":3418,"line":3431},[3416,22760,17433],{"class":11427},[3416,22762,17436],{"class":6397},[3416,22764,4043],{"class":3795},[3416,22766,22767],{"class":6397},"ApplicationAutoScaling",[3416,22769,11594],{"class":3795},[3416,22771,22772,22774,22776,22778,22780,22782,22784],{"class":3418,"line":3437},[3416,22773,17433],{"class":11427},[3416,22775,17436],{"class":6397},[3416,22777,4043],{"class":3795},[3416,22779,22767],{"class":6397},[3416,22781,4043],{"class":3795},[3416,22783,17458],{"class":6397},[3416,22785,11594],{"class":3795},[3416,22787,22788],{"class":3418,"line":3444},[3416,22789,3441],{"emptyLinePlaceholder":3440},[3416,22791,22792,22794,22797,22799,22801,22803,22805,22808,22810,22813,22815,22818],{"class":3418,"line":3450},[3416,22793,6384],{"class":4368},[3416,22795,22796],{"class":6387}," ddbClient",[3416,22798,6391],{"class":3795},[3416,22800,6394],{"class":4368},[3416,22802,6398],{"class":6397},[3416,22804,6423],{"class":3795},[3416,22806,22807],{"class":6387},"Amazon",[3416,22809,4043],{"class":3795},[3416,22811,22812],{"class":6387},"RegionEndpoint",[3416,22814,4043],{"class":3795},[3416,22816,22817],{"class":6387},"EUCentral1",[3416,22819,11465],{"class":3795},[3416,22821,22822,22824,22827,22829,22831,22834,22836,22838,22840,22842,22844,22846],{"class":3418,"line":3456},[3416,22823,6384],{"class":4368},[3416,22825,22826],{"class":6387}," scalingClient",[3416,22828,6391],{"class":3795},[3416,22830,6394],{"class":4368},[3416,22832,22833],{"class":6397}," AmazonApplicationAutoScalingClient",[3416,22835,6423],{"class":3795},[3416,22837,22807],{"class":6387},[3416,22839,4043],{"class":3795},[3416,22841,22812],{"class":6387},[3416,22843,4043],{"class":3795},[3416,22845,22817],{"class":6387},[3416,22847,11465],{"class":3795},[3416,22849,22850],{"class":3418,"line":3462},[3416,22851,3441],{"emptyLinePlaceholder":3440},[3416,22853,22854],{"class":3418,"line":3468},[3416,22855,22856],{"class":3789},"\u002F\u002F ── Ініціалізація нової таблиці в режимі On-Demand (PAY_PER_REQUEST) ────────\n",[3416,22858,22859,22861,22863,22865,22867,22869,22871],{"class":3418,"line":3474},[3416,22860,6413],{"class":4368},[3416,22862,22796],{"class":6387},[3416,22864,4043],{"class":3795},[3416,22866,10802],{"class":6330},[3416,22868,6423],{"class":3795},[3416,22870,6394],{"class":4368},[3416,22872,10809],{"class":6397},[3416,22874,22875],{"class":3418,"line":3480},[3416,22876,3796],{"class":3795},[3416,22878,22879,22881,22883,22885],{"class":3418,"line":3486},[3416,22880,6437],{"class":6387},[3416,22882,6391],{"class":3795},[3416,22884,19785],{"class":3808},[3416,22886,3812],{"class":3795},[3416,22888,22889,22891,22893,22895,22897,22899,22901],{"class":3418,"line":3492},[3416,22890,10828],{"class":6387},[3416,22892,6391],{"class":3795},[3416,22894,6394],{"class":4368},[3416,22896,8640],{"class":6397},[3416,22898,5861],{"class":3795},[3416,22900,10839],{"class":6397},[3416,22902,6469],{"class":3795},[3416,22904,22905],{"class":3418,"line":3498},[3416,22906,6474],{"class":3795},[3416,22908,22909,22911,22913,22915,22917,22919,22921,22923,22925,22927,22929,22931],{"class":3418,"line":3504},[3416,22910,9886],{"class":4368},[3416,22912,17546],{"class":3795},[3416,22914,10857],{"class":6387},[3416,22916,6391],{"class":3795},[3416,22918,19820],{"class":3808},[3416,22920,4384],{"class":3795},[3416,22922,10866],{"class":6387},[3416,22924,6391],{"class":3795},[3416,22926,10871],{"class":6387},[3416,22928,4043],{"class":3795},[3416,22930,6495],{"class":6387},[3416,22932,8915],{"class":3795},[3416,22934,22935,22937,22939,22941,22943,22945,22947,22949,22951,22953,22955,22957],{"class":3418,"line":3510},[3416,22936,9886],{"class":4368},[3416,22938,17546],{"class":3795},[3416,22940,10857],{"class":6387},[3416,22942,6391],{"class":3795},[3416,22944,20498],{"class":3808},[3416,22946,4384],{"class":3795},[3416,22948,10866],{"class":6387},[3416,22950,6391],{"class":3795},[3416,22952,10871],{"class":6387},[3416,22954,4043],{"class":3795},[3416,22956,6495],{"class":6387},[3416,22958,8948],{"class":3795},[3416,22960,22961],{"class":3418,"line":3515},[3416,22962,4442],{"class":3795},[3416,22964,22965,22967,22969,22971,22973,22975,22977],{"class":3418,"line":3521},[3416,22966,10914],{"class":6387},[3416,22968,6391],{"class":3795},[3416,22970,6394],{"class":4368},[3416,22972,8640],{"class":6397},[3416,22974,5861],{"class":3795},[3416,22976,10925],{"class":6397},[3416,22978,6469],{"class":3795},[3416,22980,22981],{"class":3418,"line":3527},[3416,22982,6474],{"class":3795},[3416,22984,22985,22987,22989,22991,22993,22995,22997,22999,23001,23003,23005,23007],{"class":3418,"line":3533},[3416,22986,9886],{"class":4368},[3416,22988,17546],{"class":3795},[3416,22990,10857],{"class":6387},[3416,22992,6391],{"class":3795},[3416,22994,19820],{"class":3808},[3416,22996,4384],{"class":3795},[3416,22998,10951],{"class":6387},[3416,23000,6391],{"class":3795},[3416,23002,10951],{"class":6387},[3416,23004,4043],{"class":3795},[3416,23006,10960],{"class":6387},[3416,23008,8915],{"class":3795},[3416,23010,23011,23013,23015,23017,23019,23021,23023,23025,23027,23029,23031,23033],{"class":3418,"line":3539},[3416,23012,9886],{"class":4368},[3416,23014,17546],{"class":3795},[3416,23016,10857],{"class":6387},[3416,23018,6391],{"class":3795},[3416,23020,20498],{"class":3808},[3416,23022,4384],{"class":3795},[3416,23024,10951],{"class":6387},[3416,23026,6391],{"class":3795},[3416,23028,10951],{"class":6387},[3416,23030,4043],{"class":3795},[3416,23032,10989],{"class":6387},[3416,23034,8948],{"class":3795},[3416,23036,23037],{"class":3418,"line":3545},[3416,23038,4442],{"class":3795},[3416,23040,23041,23043,23045,23047,23049],{"class":3418,"line":3551},[3416,23042,11000],{"class":6387},[3416,23044,6391],{"class":3795},[3416,23046,11005],{"class":6387},[3416,23048,4043],{"class":3795},[3416,23050,11010],{"class":6387},[3416,23052,23053],{"class":3418,"line":3557},[3416,23054,6537],{"class":3795},[3416,23056,23057],{"class":3418,"line":3563},[3416,23058,3441],{"emptyLinePlaceholder":3440},[3416,23060,23061],{"class":3418,"line":3569},[3416,23062,23063],{"class":3789},"\u002F\u002F ── Переведення таблиці на зарезервовану ємність (Provisioned Mode) ───────────\n",[3416,23065,23066,23068,23070,23072,23074,23076,23078],{"class":3418,"line":3574},[3416,23067,6413],{"class":4368},[3416,23069,22796],{"class":6387},[3416,23071,4043],{"class":3795},[3416,23073,17498],{"class":6330},[3416,23075,6423],{"class":3795},[3416,23077,6394],{"class":4368},[3416,23079,17505],{"class":6397},[3416,23081,23082],{"class":3418,"line":3579},[3416,23083,3796],{"class":3795},[3416,23085,23086,23088,23090,23092],{"class":3418,"line":3584},[3416,23087,6437],{"class":6387},[3416,23089,6391],{"class":3795},[3416,23091,19785],{"class":3808},[3416,23093,3812],{"class":3795},[3416,23095,23096,23098,23100,23102,23104,23107],{"class":3418,"line":3590},[3416,23097,11000],{"class":6387},[3416,23099,6391],{"class":3795},[3416,23101,11005],{"class":6387},[3416,23103,4043],{"class":3795},[3416,23105,23106],{"class":6387},"PROVISIONED",[3416,23108,3812],{"class":3795},[3416,23110,23111,23114,23116,23118],{"class":3418,"line":3596},[3416,23112,23113],{"class":6387},"    ProvisionedThroughput",[3416,23115,6391],{"class":3795},[3416,23117,6394],{"class":4368},[3416,23119,17805],{"class":6397},[3416,23121,23122],{"class":3418,"line":3602},[3416,23123,6474],{"class":3795},[3416,23125,23126,23129,23131,23134],{"class":3418,"line":3608},[3416,23127,23128],{"class":6387},"        ReadCapacityUnits",[3416,23130,6391],{"class":3795},[3416,23132,23133],{"class":3870},"100",[3416,23135,3812],{"class":3795},[3416,23137,23138,23141,23143],{"class":3418,"line":3614},[3416,23139,23140],{"class":6387},"        WriteCapacityUnits",[3416,23142,6391],{"class":3795},[3416,23144,17831],{"class":3870},[3416,23146,23147],{"class":3418,"line":3620},[3416,23148,4167],{"class":3795},[3416,23150,23151],{"class":3418,"line":3626},[3416,23152,6537],{"class":3795},[3416,23154,23155],{"class":3418,"line":3631},[3416,23156,3441],{"emptyLinePlaceholder":3440},[3416,23158,23159],{"class":3418,"line":3636},[3416,23160,23161],{"class":3789},"\u002F\u002F ── Налаштування масштабованого об'єкта в Application Auto Scaling ───────────\n",[3416,23163,23164,23166,23168,23170,23173,23175,23177],{"class":3418,"line":3641},[3416,23165,6413],{"class":4368},[3416,23167,22826],{"class":6387},[3416,23169,4043],{"class":3795},[3416,23171,23172],{"class":6330},"RegisterScalableTargetAsync",[3416,23174,6423],{"class":3795},[3416,23176,6394],{"class":4368},[3416,23178,23179],{"class":6397}," RegisterScalableTargetRequest\n",[3416,23181,23182],{"class":3418,"line":3647},[3416,23183,3796],{"class":3795},[3416,23185,23186,23189,23191,23194,23196,23199],{"class":3418,"line":3653},[3416,23187,23188],{"class":6387},"    ServiceNamespace",[3416,23190,6391],{"class":3795},[3416,23192,23193],{"class":6387},"ServiceNamespace",[3416,23195,4043],{"class":3795},[3416,23197,23198],{"class":6387},"Dynamodb",[3416,23200,3812],{"class":3795},[3416,23202,23203,23206,23208,23211],{"class":3418,"line":3659},[3416,23204,23205],{"class":6387},"    ResourceId",[3416,23207,6391],{"class":3795},[3416,23209,23210],{"class":3808},"\"table\u002FOrders\"",[3416,23212,3812],{"class":3795},[3416,23214,23215,23218,23220,23223,23225,23228],{"class":3418,"line":3665},[3416,23216,23217],{"class":6387},"    ScalableDimension",[3416,23219,6391],{"class":3795},[3416,23221,23222],{"class":6387},"ScalableDimension",[3416,23224,4043],{"class":3795},[3416,23226,23227],{"class":6387},"DynamodbTableWriteCapacityUnits",[3416,23229,3812],{"class":3795},[3416,23231,23232,23235,23237,23239],{"class":3418,"line":3671},[3416,23233,23234],{"class":6387},"    MinCapacity",[3416,23236,6391],{"class":3795},[3416,23238,20193],{"class":3870},[3416,23240,3812],{"class":3795},[3416,23242,23243,23246,23248],{"class":3418,"line":3677},[3416,23244,23245],{"class":6387},"    MaxCapacity",[3416,23247,6391],{"class":3795},[3416,23249,23250],{"class":3870},"500\n",[3416,23252,23253],{"class":3418,"line":3683},[3416,23254,6537],{"class":3795},[3416,23256,23257],{"class":3418,"line":3688},[3416,23258,3441],{"emptyLinePlaceholder":3440},[3416,23260,23261],{"class":3418,"line":3693},[3416,23262,23263],{"class":3789},"\u002F\u002F ── Створення політики динамічного масштабування для WCU на рівні 70% ─────────\n",[3416,23265,23266,23268,23270,23272,23275,23277,23279],{"class":3418,"line":3698},[3416,23267,6413],{"class":4368},[3416,23269,22826],{"class":6387},[3416,23271,4043],{"class":3795},[3416,23273,23274],{"class":6330},"PutScalingPolicyAsync",[3416,23276,6423],{"class":3795},[3416,23278,6394],{"class":4368},[3416,23280,23281],{"class":6397}," PutScalingPolicyRequest\n",[3416,23283,23284],{"class":3418,"line":3704},[3416,23285,3796],{"class":3795},[3416,23287,23288,23290,23292,23294,23296,23298],{"class":3418,"line":3710},[3416,23289,23188],{"class":6387},[3416,23291,6391],{"class":3795},[3416,23293,23193],{"class":6387},[3416,23295,4043],{"class":3795},[3416,23297,23198],{"class":6387},[3416,23299,3812],{"class":3795},[3416,23301,23302,23304,23306,23308],{"class":3418,"line":3715},[3416,23303,23205],{"class":6387},[3416,23305,6391],{"class":3795},[3416,23307,23210],{"class":3808},[3416,23309,3812],{"class":3795},[3416,23311,23312,23314,23316,23318,23320,23322],{"class":3418,"line":12799},[3416,23313,23217],{"class":6387},[3416,23315,6391],{"class":3795},[3416,23317,23222],{"class":6387},[3416,23319,4043],{"class":3795},[3416,23321,23227],{"class":6387},[3416,23323,3812],{"class":3795},[3416,23325,23326,23329,23331,23334],{"class":3418,"line":12822},[3416,23327,23328],{"class":6387},"    PolicyName",[3416,23330,6391],{"class":3795},[3416,23332,23333],{"class":3808},"\"Orders-WCU-AutoScaling-Policy\"",[3416,23335,3812],{"class":3795},[3416,23337,23338,23341,23343,23346,23348,23351],{"class":3418,"line":12827},[3416,23339,23340],{"class":6387},"    PolicyType",[3416,23342,6391],{"class":3795},[3416,23344,23345],{"class":6387},"PolicyType",[3416,23347,4043],{"class":3795},[3416,23349,23350],{"class":6387},"TargetTrackingScaling",[3416,23352,3812],{"class":3795},[3416,23354,23355,23358,23360,23362],{"class":3418,"line":12832},[3416,23356,23357],{"class":6387},"    TargetTrackingScalingPolicyConfiguration",[3416,23359,6391],{"class":3795},[3416,23361,6394],{"class":4368},[3416,23363,23364],{"class":6397}," TargetTrackingScalingPolicyConfiguration\n",[3416,23366,23367],{"class":3418,"line":12837},[3416,23368,6474],{"class":3795},[3416,23370,23371,23374,23376,23379],{"class":3418,"line":12843},[3416,23372,23373],{"class":6387},"        TargetValue",[3416,23375,6391],{"class":3795},[3416,23377,23378],{"class":3870},"70.0",[3416,23380,3812],{"class":3795},[3416,23382,23383,23386,23388,23390],{"class":3418,"line":12860},[3416,23384,23385],{"class":6387},"        PredefinedMetricSpecification",[3416,23387,6391],{"class":3795},[3416,23389,6394],{"class":4368},[3416,23391,23392],{"class":6397}," PredefinedMetricSpecification\n",[3416,23394,23395],{"class":3418,"line":12865},[3416,23396,8611],{"class":3795},[3416,23398,23399,23402,23404,23407,23409],{"class":3418,"line":12876},[3416,23400,23401],{"class":6387},"            PredefinedMetricType",[3416,23403,6391],{"class":3795},[3416,23405,23406],{"class":6387},"MetricType",[3416,23408,4043],{"class":3795},[3416,23410,23411],{"class":6387},"DynamoDBWriteCapacityUtilization\n",[3416,23413,23414],{"class":3418,"line":12897},[3416,23415,8533],{"class":3795},[3416,23417,23418],{"class":3418,"line":12902},[3416,23419,4167],{"class":3795},[3416,23421,23422],{"class":3418,"line":12925},[3416,23423,6537],{"class":3795},[3416,23425,23426],{"class":3418,"line":12948},[3416,23427,3441],{"emptyLinePlaceholder":3440},[3416,23429,23430],{"class":3418,"line":12953},[3416,23431,23432],{"class":3789},"\u002F\u002F ── Повернення таблиці до конфігурації On-Demand ──────────────────────────────\n",[3416,23434,23435,23437,23439,23441,23443,23445,23447],{"class":3418,"line":20609},[3416,23436,6413],{"class":4368},[3416,23438,22796],{"class":6387},[3416,23440,4043],{"class":3795},[3416,23442,17498],{"class":6330},[3416,23444,6423],{"class":3795},[3416,23446,6394],{"class":4368},[3416,23448,17505],{"class":6397},[3416,23450,23451],{"class":3418,"line":20614},[3416,23452,3796],{"class":3795},[3416,23454,23455,23457,23459,23461],{"class":3418,"line":20619},[3416,23456,6437],{"class":6387},[3416,23458,6391],{"class":3795},[3416,23460,19785],{"class":3808},[3416,23462,3812],{"class":3795},[3416,23464,23465,23467,23469,23471,23473],{"class":3418,"line":20624},[3416,23466,11000],{"class":6387},[3416,23468,6391],{"class":3795},[3416,23470,11005],{"class":6387},[3416,23472,4043],{"class":3795},[3416,23474,11010],{"class":6387},[3416,23476,23477],{"class":3418,"line":20630},[3416,23478,6537],{"class":3795},[6311,23480,23481],{"label":6540},[3406,23482,23484],{"className":6543,"code":23483,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\nImport-Module AWS.Tools.ApplicationAutoScaling\n\n# ── Створення таблиці в режимі On-Demand ──────────────────────────────────────\n$attrDefs = @(\n    New-DDBAttributeDefinition -AttributeName CustomerId -AttributeType S\n    New-DDBAttributeDefinition -AttributeName OrderId    -AttributeType S\n)\n$keySchema = @(\n    New-DDBKeySchemaElement -AttributeName CustomerId -KeyType HASH\n    New-DDBKeySchemaElement -AttributeName OrderId    -KeyType RANGE\n)\nNew-DDBTable `\n    -TableName Orders `\n    -AttributeDefinition $attrDefs `\n    -KeySchema $keySchema `\n    -BillingMode PAY_PER_REQUEST `\n    -Region eu-central-1\n\n# ── Переведення таблиці на зарезервовану ємність (Provisioned) ────────────────\n$throughput = [Amazon.DynamoDBv2.Model.ProvisionedThroughput]@{\n    ReadCapacityUnits  = 100\n    WriteCapacityUnits = 50\n}\nUpdate-DDBTable `\n    -TableName Orders `\n    -BillingMode PROVISIONED `\n    -ProvisionedThroughput $throughput `\n    -Region eu-central-1\n\n# ── Реєстрація цілі масштабування для WCU через Auto Scaling ─────────────────\nAdd-AASScalableTarget `\n    -ServiceNamespace dynamodb `\n    -ResourceId 'table\u002FOrders' `\n    -ScalableDimension 'dynamodb:table:WriteCapacityUnits' `\n    -MinCapacity 10 `\n    -MaxCapacity 500 `\n    -Region eu-central-1\n\n# ── Встановлення цільової політики масштабування (70% утилізації) ────────────\n$metricSpec = [Amazon.ApplicationAutoScaling.Model.PredefinedMetricSpecification]@{\n    PredefinedMetricType = 'DynamoDBWriteCapacityUtilization'\n}\n$policyConfig = [Amazon.ApplicationAutoScaling.Model.TargetTrackingScalingPolicyConfiguration]@{\n    TargetValue                      = 70.0\n    PredefinedMetricSpecification    = $metricSpec\n}\nSet-AASScalingPolicy `\n    -ServiceNamespace dynamodb `\n    -ResourceId 'table\u002FOrders' `\n    -ScalableDimension 'dynamodb:table:WriteCapacityUnits' `\n    -PolicyName 'Orders-WCU-AutoScaling-Policy' `\n    -PolicyType TargetTrackingScaling `\n    -TargetTrackingScalingPolicyConfiguration $policyConfig `\n    -Region eu-central-1\n\n# ── Повернення таблиці на On-Demand режим ─────────────────────────────────────\nUpdate-DDBTable `\n    -TableName Orders `\n    -BillingMode PAY_PER_REQUEST `\n    -Region eu-central-1\n",[3413,23485,23486,23492,23499,23503,23508,23519,23527,23534,23538,23549,23557,23564,23568,23574,23578,23586,23595,23599,23605,23609,23614,23630,23640,23649,23653,23659,23663,23668,23677,23683,23687,23692,23699,23704,23714,23724,23733,23743,23749,23753,23758,23774,23784,23788,23804,23815,23825,23829,23836,23840,23848,23856,23866,23871,23880,23886,23890,23895,23901,23905,23909],{"__ignoreMap":3411},[3416,23487,23488,23490],{"class":3418,"line":3419},[3416,23489,12967],{"class":6330},[3416,23491,12970],{"class":3795},[3416,23493,23494,23496],{"class":3418,"line":3425},[3416,23495,12967],{"class":6330},[3416,23497,23498],{"class":3795}," AWS.Tools.ApplicationAutoScaling\n",[3416,23500,23501],{"class":3418,"line":3431},[3416,23502,3441],{"emptyLinePlaceholder":3440},[3416,23504,23505],{"class":3418,"line":3437},[3416,23506,23507],{"class":3789},"# ── Створення таблиці в режимі On-Demand ──────────────────────────────────────\n",[3416,23509,23510,23513,23515,23517],{"class":3418,"line":3444},[3416,23511,23512],{"class":6387},"$attrDefs",[3416,23514,6391],{"class":3795},[3416,23516,6561],{"class":4368},[3416,23518,8878],{"class":3795},[3416,23520,23521,23524],{"class":3418,"line":3450},[3416,23522,23523],{"class":6330},"    New-DDBAttributeDefinition",[3416,23525,23526],{"class":3795}," -AttributeName CustomerId -AttributeType S\n",[3416,23528,23529,23531],{"class":3418,"line":3456},[3416,23530,23523],{"class":6330},[3416,23532,23533],{"class":3795}," -AttributeName OrderId    -AttributeType S\n",[3416,23535,23536],{"class":3418,"line":3462},[3416,23537,9656],{"class":3795},[3416,23539,23540,23543,23545,23547],{"class":3418,"line":3468},[3416,23541,23542],{"class":6387},"$keySchema",[3416,23544,6391],{"class":3795},[3416,23546,6561],{"class":4368},[3416,23548,8878],{"class":3795},[3416,23550,23551,23554],{"class":3418,"line":3474},[3416,23552,23553],{"class":6330},"    New-DDBKeySchemaElement",[3416,23555,23556],{"class":3795}," -AttributeName CustomerId -KeyType HASH\n",[3416,23558,23559,23561],{"class":3418,"line":3480},[3416,23560,23553],{"class":6330},[3416,23562,23563],{"class":3795}," -AttributeName OrderId    -KeyType RANGE\n",[3416,23565,23566],{"class":3418,"line":3486},[3416,23567,9656],{"class":3795},[3416,23569,23570,23572],{"class":3418,"line":3492},[3416,23571,11102],{"class":6330},[3416,23573,11105],{"class":3795},[3416,23575,23576],{"class":3418,"line":3498},[3416,23577,21143],{"class":3795},[3416,23579,23580,23582,23584],{"class":3418,"line":3504},[3416,23581,11115],{"class":3795},[3416,23583,23512],{"class":6387},[3416,23585,11105],{"class":3795},[3416,23587,23588,23591,23593],{"class":3418,"line":3510},[3416,23589,23590],{"class":3795},"    -KeySchema ",[3416,23592,23542],{"class":6387},[3416,23594,11105],{"class":3795},[3416,23596,23597],{"class":3418,"line":3515},[3416,23598,11150],{"class":3795},[3416,23600,23601,23603],{"class":3418,"line":3521},[3416,23602,21235],{"class":3795},[3416,23604,6614],{"class":3870},[3416,23606,23607],{"class":3418,"line":3527},[3416,23608,3441],{"emptyLinePlaceholder":3440},[3416,23610,23611],{"class":3418,"line":3533},[3416,23612,23613],{"class":3789},"# ── Переведення таблиці на зарезервовану ємність (Provisioned) ────────────────\n",[3416,23615,23616,23619,23621,23624,23626,23628],{"class":3418,"line":3539},[3416,23617,23618],{"class":6387},"$throughput",[3416,23620,7274],{"class":3795},[3416,23622,23623],{"class":4368},"Amazon.DynamoDBv2.Model.ProvisionedThroughput",[3416,23625,7280],{"class":3795},[3416,23627,6561],{"class":4368},[3416,23629,3796],{"class":3795},[3416,23631,23632,23635,23637],{"class":3418,"line":3545},[3416,23633,23634],{"class":6387},"    ReadCapacityUnits",[3416,23636,6933],{"class":3795},[3416,23638,23639],{"class":3870},"100\n",[3416,23641,23642,23645,23647],{"class":3418,"line":3551},[3416,23643,23644],{"class":6387},"    WriteCapacityUnits",[3416,23646,6391],{"class":3795},[3416,23648,17831],{"class":3870},[3416,23650,23651],{"class":3418,"line":3557},[3416,23652,3507],{"class":3795},[3416,23654,23655,23657],{"class":3418,"line":3563},[3416,23656,18062],{"class":6330},[3416,23658,11105],{"class":3795},[3416,23660,23661],{"class":3418,"line":3569},[3416,23662,21143],{"class":3795},[3416,23664,23665],{"class":3418,"line":3574},[3416,23666,23667],{"class":3795},"    -BillingMode PROVISIONED `\n",[3416,23669,23670,23673,23675],{"class":3418,"line":3579},[3416,23671,23672],{"class":3795},"    -ProvisionedThroughput ",[3416,23674,23618],{"class":6387},[3416,23676,11105],{"class":3795},[3416,23678,23679,23681],{"class":3418,"line":3584},[3416,23680,21235],{"class":3795},[3416,23682,6614],{"class":3870},[3416,23684,23685],{"class":3418,"line":3590},[3416,23686,3441],{"emptyLinePlaceholder":3440},[3416,23688,23689],{"class":3418,"line":3596},[3416,23690,23691],{"class":3789},"# ── Реєстрація цілі масштабування для WCU через Auto Scaling ─────────────────\n",[3416,23693,23694,23697],{"class":3418,"line":3602},[3416,23695,23696],{"class":6330},"Add-AASScalableTarget",[3416,23698,11105],{"class":3795},[3416,23700,23701],{"class":3418,"line":3608},[3416,23702,23703],{"class":3795},"    -ServiceNamespace dynamodb `\n",[3416,23705,23706,23709,23712],{"class":3418,"line":3614},[3416,23707,23708],{"class":3795},"    -ResourceId ",[3416,23710,23711],{"class":3808},"'table\u002FOrders'",[3416,23713,11105],{"class":3795},[3416,23715,23716,23719,23722],{"class":3418,"line":3620},[3416,23717,23718],{"class":3795},"    -ScalableDimension ",[3416,23720,23721],{"class":3808},"'dynamodb:table:WriteCapacityUnits'",[3416,23723,11105],{"class":3795},[3416,23725,23726,23729,23731],{"class":3418,"line":3626},[3416,23727,23728],{"class":3795},"    -MinCapacity ",[3416,23730,20193],{"class":3870},[3416,23732,11105],{"class":3795},[3416,23734,23735,23738,23741],{"class":3418,"line":3631},[3416,23736,23737],{"class":3795},"    -MaxCapacity ",[3416,23739,23740],{"class":3870},"500",[3416,23742,11105],{"class":3795},[3416,23744,23745,23747],{"class":3418,"line":3636},[3416,23746,21235],{"class":3795},[3416,23748,6614],{"class":3870},[3416,23750,23751],{"class":3418,"line":3641},[3416,23752,3441],{"emptyLinePlaceholder":3440},[3416,23754,23755],{"class":3418,"line":3647},[3416,23756,23757],{"class":3789},"# ── Встановлення цільової політики масштабування (70% утилізації) ────────────\n",[3416,23759,23760,23763,23765,23768,23770,23772],{"class":3418,"line":3653},[3416,23761,23762],{"class":6387},"$metricSpec",[3416,23764,7274],{"class":3795},[3416,23766,23767],{"class":4368},"Amazon.ApplicationAutoScaling.Model.PredefinedMetricSpecification",[3416,23769,7280],{"class":3795},[3416,23771,6561],{"class":4368},[3416,23773,3796],{"class":3795},[3416,23775,23776,23779,23781],{"class":3418,"line":3659},[3416,23777,23778],{"class":6387},"    PredefinedMetricType",[3416,23780,6391],{"class":3795},[3416,23782,23783],{"class":3808},"'DynamoDBWriteCapacityUtilization'\n",[3416,23785,23786],{"class":3418,"line":3665},[3416,23787,3507],{"class":3795},[3416,23789,23790,23793,23795,23798,23800,23802],{"class":3418,"line":3671},[3416,23791,23792],{"class":6387},"$policyConfig",[3416,23794,7274],{"class":3795},[3416,23796,23797],{"class":4368},"Amazon.ApplicationAutoScaling.Model.TargetTrackingScalingPolicyConfiguration",[3416,23799,7280],{"class":3795},[3416,23801,6561],{"class":4368},[3416,23803,3796],{"class":3795},[3416,23805,23806,23809,23812],{"class":3418,"line":3677},[3416,23807,23808],{"class":6387},"    TargetValue",[3416,23810,23811],{"class":3795},"                      = ",[3416,23813,23814],{"class":3870},"70.0\n",[3416,23816,23817,23820,23822],{"class":3418,"line":3683},[3416,23818,23819],{"class":6387},"    PredefinedMetricSpecification",[3416,23821,6571],{"class":3795},[3416,23823,23824],{"class":6387},"$metricSpec\n",[3416,23826,23827],{"class":3418,"line":3688},[3416,23828,3507],{"class":3795},[3416,23830,23831,23834],{"class":3418,"line":3693},[3416,23832,23833],{"class":6330},"Set-AASScalingPolicy",[3416,23835,11105],{"class":3795},[3416,23837,23838],{"class":3418,"line":3698},[3416,23839,23703],{"class":3795},[3416,23841,23842,23844,23846],{"class":3418,"line":3704},[3416,23843,23708],{"class":3795},[3416,23845,23711],{"class":3808},[3416,23847,11105],{"class":3795},[3416,23849,23850,23852,23854],{"class":3418,"line":3710},[3416,23851,23718],{"class":3795},[3416,23853,23721],{"class":3808},[3416,23855,11105],{"class":3795},[3416,23857,23858,23861,23864],{"class":3418,"line":3715},[3416,23859,23860],{"class":3795},"    -PolicyName ",[3416,23862,23863],{"class":3808},"'Orders-WCU-AutoScaling-Policy'",[3416,23865,11105],{"class":3795},[3416,23867,23868],{"class":3418,"line":12799},[3416,23869,23870],{"class":3795},"    -PolicyType TargetTrackingScaling `\n",[3416,23872,23873,23876,23878],{"class":3418,"line":12822},[3416,23874,23875],{"class":3795},"    -TargetTrackingScalingPolicyConfiguration ",[3416,23877,23792],{"class":6387},[3416,23879,11105],{"class":3795},[3416,23881,23882,23884],{"class":3418,"line":12827},[3416,23883,21235],{"class":3795},[3416,23885,6614],{"class":3870},[3416,23887,23888],{"class":3418,"line":12832},[3416,23889,3441],{"emptyLinePlaceholder":3440},[3416,23891,23892],{"class":3418,"line":12837},[3416,23893,23894],{"class":3789},"# ── Повернення таблиці на On-Demand режим ─────────────────────────────────────\n",[3416,23896,23897,23899],{"class":3418,"line":12843},[3416,23898,18062],{"class":6330},[3416,23900,11105],{"class":3795},[3416,23902,23903],{"class":3418,"line":12860},[3416,23904,21143],{"class":3795},[3416,23906,23907],{"class":3418,"line":12865},[3416,23908,11150],{"class":3795},[3416,23910,23911,23913],{"class":3418,"line":12876},[3416,23912,21235],{"class":3795},[3416,23914,6614],{"class":3870},[11159,23916,23918],{"title":23917},"Вихідні дані CLI при успішному перемиканні режиму",[3406,23919,23921],{"className":3780,"code":23920,"language":3782,"meta":3411,"style":3411},"{\n    \"TableDescription\": {\n        \"TableName\": \"Orders\",\n        \"TableStatus\": \"UPDATING\",\n        \"BillingModeSummary\": {\n            \"BillingMode\": \"PROVISIONED\",\n            \"LastUpdateToPayPerRequestDateTime\": \"2026-06-03T10:00:00Z\"\n        },\n        \"ProvisionedThroughput\": {\n            \"ReadCapacityUnits\": 100,\n            \"WriteCapacityUnits\": 50\n        }\n    }\n}\n",[3413,23922,23923,23927,23934,23945,23957,23964,23976,23986,23990,23997,24008,24017,24021,24025],{"__ignoreMap":3411},[3416,23924,23925],{"class":3418,"line":3419},[3416,23926,3796],{"class":3795},[3416,23928,23929,23932],{"class":3418,"line":3425},[3416,23930,23931],{"class":3801},"    \"TableDescription\"",[3416,23933,4403],{"class":3795},[3416,23935,23936,23939,23941,23943],{"class":3418,"line":3431},[3416,23937,23938],{"class":3801},"        \"TableName\"",[3416,23940,3805],{"class":3795},[3416,23942,19785],{"class":3808},[3416,23944,3812],{"class":3795},[3416,23946,23947,23950,23952,23955],{"class":3418,"line":3437},[3416,23948,23949],{"class":3801},"        \"TableStatus\"",[3416,23951,3805],{"class":3795},[3416,23953,23954],{"class":3808},"\"UPDATING\"",[3416,23956,3812],{"class":3795},[3416,23958,23959,23962],{"class":3418,"line":3444},[3416,23960,23961],{"class":3801},"        \"BillingModeSummary\"",[3416,23963,4403],{"class":3795},[3416,23965,23966,23969,23971,23974],{"class":3418,"line":3450},[3416,23967,23968],{"class":3801},"            \"BillingMode\"",[3416,23970,3805],{"class":3795},[3416,23972,23973],{"class":3808},"\"PROVISIONED\"",[3416,23975,3812],{"class":3795},[3416,23977,23978,23981,23983],{"class":3418,"line":3456},[3416,23979,23980],{"class":3801},"            \"LastUpdateToPayPerRequestDateTime\"",[3416,23982,3805],{"class":3795},[3416,23984,23985],{"class":3808},"\"2026-06-03T10:00:00Z\"\n",[3416,23987,23988],{"class":3418,"line":3462},[3416,23989,9774],{"class":3795},[3416,23991,23992,23995],{"class":3418,"line":3468},[3416,23993,23994],{"class":3801},"        \"ProvisionedThroughput\"",[3416,23996,4403],{"class":3795},[3416,23998,23999,24002,24004,24006],{"class":3418,"line":3474},[3416,24000,24001],{"class":3801},"            \"ReadCapacityUnits\"",[3416,24003,3805],{"class":3795},[3416,24005,23133],{"class":3870},[3416,24007,3812],{"class":3795},[3416,24009,24010,24013,24015],{"class":3418,"line":3480},[3416,24011,24012],{"class":3801},"            \"WriteCapacityUnits\"",[3416,24014,3805],{"class":3795},[3416,24016,17831],{"class":3870},[3416,24018,24019],{"class":3418,"line":3486},[3416,24020,8533],{"class":3795},[3416,24022,24023],{"class":3418,"line":3492},[3416,24024,4167],{"class":3795},[3416,24026,24027],{"class":3418,"line":3498},[3416,24028,3507],{"class":3795},[3348,24030,24032],{"id":24031},"частина-4-dynamodb-streams-та-транзакції","Частина 4: DynamoDB Streams та Транзакції",[3727,24034,24036],{"id":24035},"dynamodb-streams-архітектура-потоків-змін","DynamoDB Streams — архітектура потоків змін",[3353,24038,24039,24042,24043,24045,24046,24048,24049,24051],{},[3363,24040,24041],{},"DynamoDB Streams"," є високодоступним, розподіленим журналом транзакційних логів (Change Data Capture, CDC), який фіксує всі модифікації даних у таблиці в хронологічному порядку. Кожна операція створення (",[3413,24044,6619],{},"), оновлення (",[3413,24047,6964],{},") чи видалення (",[3413,24050,7408],{},") генерує відповідний запис зміни (Stream Record).",[4584,24053,24055],{"id":24054},"архітектурні-принципи-та-гарантії","Архітектурні принципи та гарантії:",[3374,24057,24058,24064,24074,24084],{},[3377,24059,24060,24063],{},[3363,24061,24062],{},"Шардування (Shards):"," Потік даних автоматично розділяється на логічні фрагменти — шарди. Кожен шард відповідає певному діапазону ключів партицій і обслуговується власною обчислювальною інфраструктурою. Шарди є ефемерними: при збільшенні навантаження або обсягу даних вони автоматично розгалужуються (split), а при зменшенні — закриваються.",[3377,24065,24066,24069,24070,24073],{},[3363,24067,24068],{},"Впорядкованість записів:"," DynamoDB гарантує строгу послідовність записів ",[3363,24071,24072],{},"виключно в межах одного шарду",". Якщо два записи належать до різних партицій (і відповідно, потрапляють у різні шарди), їх взаємний порядок у потоці не гарантується.",[3377,24075,24076,24079,24080,24083],{},[3363,24077,24078],{},"Життєвий цикл (Data Retention):"," Всі записи в потоці зберігаються строго ",[3363,24081,24082],{},"протягом 24 годин"," із моменту створення. Після цього дані видаляються без можливості відновлення.",[3377,24085,24086,24089,24090,24093],{},[3363,24087,24088],{},"Гарантія доставки (Delivery Guarantees):"," Забезпечується доставка типу ",[4091,24091,24092],{},"At-least-once"," (щонайменше один раз). Споживачі повинні бути готовими до обробки дублікатів записів (дедуплікація на рівні бізнес-логіки).",[3403,24095,24096],{},[3406,24097,24099],{"className":3408,"code":24098,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Архітектура DynamoDB Streams та інтеграція зі споживачами\n\nrectangle \"Таблиця: Orders\" as table #E8F4FD\n\nrectangle \"Потік змін (Streams)\" as streams #D5E8D4 {\n  rectangle \"Шард 1\\n(Партиції A–M)\" as sh1 #82B366\n  rectangle \"Шард 2\\n(Партиції N–Z)\" as sh2 #82B366\n}\n\nrectangle \"AWS Lambda\\n(Event Source Mapping)\" as lambda #FFF2CC\nrectangle \"Синхронізатор\\n(InventorySync)\" as lambda2 #FFF2CC\n\nrectangle \"Черга SQS\\n(Сповіщення)\" as sqs #F0E6FF\nrectangle \"OpenSearch\\n(Пошуковий індекс)\" as es #FFE6E6\n\ntable --> sh1 : \"Запис операцій (PK: A-M)\"\ntable --> sh2 : \"Запис операцій (PK: N-Z)\"\n\nsh1 --> lambda : \"Опитування (Polling) та пакетний виклик\"\nsh2 --> lambda : \"Опитування (Polling) та пакетний виклик\"\nsh1 --> lambda2 : \"Зчитування дельти\"\n\nlambda --> sqs : \"Відправка подій\"\nlambda2 --> es : \"Синхронізація стану\"\n\nnote right of table\n  * Життєвий цикл записів: 24 години\n  * Доставка: At-least-once\n  * Шарди автоматично масштабуються\nend note\n@enduml\n",[3413,24100,24101,24105,24109,24113,24117,24121,24126,24130,24135,24139,24144,24149,24154,24158,24162,24167,24172,24176,24181,24186,24190,24195,24200,24204,24209,24214,24219,24223,24228,24233,24237,24242,24247,24252,24257,24261],{"__ignoreMap":3411},[3416,24102,24103],{"class":3418,"line":3419},[3416,24104,3422],{},[3416,24106,24107],{"class":3418,"line":3425},[3416,24108,16755],{},[3416,24110,24111],{"class":3418,"line":3431},[3416,24112,16760],{},[3416,24114,24115],{"class":3418,"line":3437},[3416,24116,16765],{},[3416,24118,24119],{"class":3418,"line":3444},[3416,24120,3441],{"emptyLinePlaceholder":3440},[3416,24122,24123],{"class":3418,"line":3450},[3416,24124,24125],{},"title Архітектура DynamoDB Streams та інтеграція зі споживачами\n",[3416,24127,24128],{"class":3418,"line":3456},[3416,24129,3441],{"emptyLinePlaceholder":3440},[3416,24131,24132],{"class":3418,"line":3462},[3416,24133,24134],{},"rectangle \"Таблиця: Orders\" as table #E8F4FD\n",[3416,24136,24137],{"class":3418,"line":3468},[3416,24138,3441],{"emptyLinePlaceholder":3440},[3416,24140,24141],{"class":3418,"line":3474},[3416,24142,24143],{},"rectangle \"Потік змін (Streams)\" as streams #D5E8D4 {\n",[3416,24145,24146],{"class":3418,"line":3480},[3416,24147,24148],{},"  rectangle \"Шард 1\\n(Партиції A–M)\" as sh1 #82B366\n",[3416,24150,24151],{"class":3418,"line":3486},[3416,24152,24153],{},"  rectangle \"Шард 2\\n(Партиції N–Z)\" as sh2 #82B366\n",[3416,24155,24156],{"class":3418,"line":3492},[3416,24157,3507],{},[3416,24159,24160],{"class":3418,"line":3498},[3416,24161,3441],{"emptyLinePlaceholder":3440},[3416,24163,24164],{"class":3418,"line":3504},[3416,24165,24166],{},"rectangle \"AWS Lambda\\n(Event Source Mapping)\" as lambda #FFF2CC\n",[3416,24168,24169],{"class":3418,"line":3510},[3416,24170,24171],{},"rectangle \"Синхронізатор\\n(InventorySync)\" as lambda2 #FFF2CC\n",[3416,24173,24174],{"class":3418,"line":3515},[3416,24175,3441],{"emptyLinePlaceholder":3440},[3416,24177,24178],{"class":3418,"line":3521},[3416,24179,24180],{},"rectangle \"Черга SQS\\n(Сповіщення)\" as sqs #F0E6FF\n",[3416,24182,24183],{"class":3418,"line":3527},[3416,24184,24185],{},"rectangle \"OpenSearch\\n(Пошуковий індекс)\" as es #FFE6E6\n",[3416,24187,24188],{"class":3418,"line":3533},[3416,24189,3441],{"emptyLinePlaceholder":3440},[3416,24191,24192],{"class":3418,"line":3539},[3416,24193,24194],{},"table --> sh1 : \"Запис операцій (PK: A-M)\"\n",[3416,24196,24197],{"class":3418,"line":3545},[3416,24198,24199],{},"table --> sh2 : \"Запис операцій (PK: N-Z)\"\n",[3416,24201,24202],{"class":3418,"line":3551},[3416,24203,3441],{"emptyLinePlaceholder":3440},[3416,24205,24206],{"class":3418,"line":3557},[3416,24207,24208],{},"sh1 --> lambda : \"Опитування (Polling) та пакетний виклик\"\n",[3416,24210,24211],{"class":3418,"line":3563},[3416,24212,24213],{},"sh2 --> lambda : \"Опитування (Polling) та пакетний виклик\"\n",[3416,24215,24216],{"class":3418,"line":3569},[3416,24217,24218],{},"sh1 --> lambda2 : \"Зчитування дельти\"\n",[3416,24220,24221],{"class":3418,"line":3574},[3416,24222,3441],{"emptyLinePlaceholder":3440},[3416,24224,24225],{"class":3418,"line":3579},[3416,24226,24227],{},"lambda --> sqs : \"Відправка подій\"\n",[3416,24229,24230],{"class":3418,"line":3584},[3416,24231,24232],{},"lambda2 --> es : \"Синхронізація стану\"\n",[3416,24234,24235],{"class":3418,"line":3590},[3416,24236,3441],{"emptyLinePlaceholder":3440},[3416,24238,24239],{"class":3418,"line":3596},[3416,24240,24241],{},"note right of table\n",[3416,24243,24244],{"class":3418,"line":3602},[3416,24245,24246],{},"  * Життєвий цикл записів: 24 години\n",[3416,24248,24249],{"class":3418,"line":3608},[3416,24250,24251],{},"  * Доставка: At-least-once\n",[3416,24253,24254],{"class":3418,"line":3614},[3416,24255,24256],{},"  * Шарди автоматично масштабуються\n",[3416,24258,24259],{"class":3418,"line":3620},[3416,24260,5088],{},[3416,24262,24263],{"class":3418,"line":3626},[3416,24264,3718],{},[3727,24266,24268],{"id":24267},"view-types-класифікація-та-оцінка-накладних-витрат","View Types — класифікація та оцінка накладних витрат",[3353,24270,24271],{},"При активації DynamoDB Streams архітектор зобов'язаний обрати тип представлення даних (View Type), який визначає обсяг інформації, що проектується у кожен запис потоку. Вибір типу безпосередньо впливає на обсяг мережевого трафіку та вартість обробки подій:",[4001,24273,24274,24295,24312,24328],{},[4004,24275,24276,24279,24280,24282,24285,24286,24288,24291,24292,24294],{"icon":15068,"title":15069},[3363,24277,24278],{},"Опис:"," Записуються лише ключові атрибути елемента (Partition Key та Sort Key).\n",[4628,24281],{},[3363,24283,24284],{},"Мережеве навантаження:"," Мінімальне.\n",[4628,24287],{},[3363,24289,24290],{},"Використання:"," Оптимально, коли споживачу достатньо знати факт зміни об'єкта, а повний стан за потреби може бути завантажений з основної таблиці через ",[3413,24293,4873],{}," (хоча це створює додаткове навантаження RCU).",[4004,24296,24299,24301,24302,24304,24306,24307,24309,24311],{"icon":24297,"title":24298},"i-heroicons-arrow-up-circle","NEW_IMAGE",[3363,24300,24278],{}," Містить повний стан елемента після його модифікації.\n",[4628,24303],{},[3363,24305,24284],{}," Середнє.\n",[4628,24308],{},[3363,24310,24290],{}," Найбільш поширений варіант для побудови Read-моделей (CQRS), реплікації в Elasticsearch\u002FRedis або відправки сповіщень про створення нових об'єктів.",[4004,24313,24316,24318,24319,24321,24306,24323,24325,24327],{"icon":24314,"title":24315},"i-heroicons-arrow-down-circle","OLD_IMAGE",[3363,24317,24278],{}," Містить повний стан елемента до його модифікації.\n",[4628,24320],{},[3363,24322,24284],{},[4628,24324],{},[3363,24326,24290],{}," Використовується в аудиторських системах для логування попереднього стану даних, а також у сценаріях компенсаційних транзакцій (Saga Pattern) для відкату змін.",[4004,24329,24332,24334,24335,24337,24339,24340,24342,24344],{"icon":24330,"title":24331},"i-heroicons-arrows-right-left","NEW_AND_OLD_IMAGES",[3363,24333,24278],{}," Одночасно містить стани елемента \"до\" та \"після\" змін.\n",[4628,24336],{},[3363,24338,24284],{}," Максимальне (додаткова серіалізація).\n",[4628,24341],{},[3363,24343,24290],{}," Необхідний для аналізу дельти (diff) змін конкретних атрибутів (наприклад, визначення факту зміни ціни або статусу замовлення).",[3727,24346,24348],{"id":24347},"механізм-інтеграції-aws-lambda-з-dynamodb-streams","Механізм інтеграції AWS Lambda з DynamoDB Streams",[3353,24350,24351,24352,24355],{},"Інтеграція реалізується за допомогою сервісу ",[3363,24353,24354],{},"AWS Lambda Event Source Mapping (ESM)",". Це внутрішній опитувач (Poller), який працює на стороні інфраструктури Lambda, виконуючи періодичні запити до шардів потоку через внутрішній API.",[24357,24358,24359,24365,24378,24383,24387],"field-group",{},[24360,24361,24364],"field",{"name":24362,"type":24363},"BatchSize","integer","Максимальна кількість записів, яка може бути передана в один виклик функції Lambda (діапазон 1–1000). Збільшення батчу підвищує пропускну здатність обробки, але вимагає більше оперативної пам'яті для контейнера Lambda.",[24360,24366,24369,24370,24373,24374,24377],{"name":24367,"type":24368},"StartingPosition","enum","Визначає точку старту обробки потоку. ",[3413,24371,24372],{},"LATEST"," орієнтується виключно на події, що з'явилися після створення тригера. ",[3413,24375,24376],{},"TRIM_HORIZON"," починає зчитування з найстаріших доступних у 24-годинному журналі записів.",[24360,24379,24382],{"name":24380,"type":24381},"BisectBatchOnFunctionError","boolean","Активує алгоритм дихотомічного (бінарного) поділу пакета при виникненні помилки обробки. ESM ділить пакет навпіл і повторює виклики для кожної частини окремо, дозволяючи локалізувати та ізолювати некоректний запис (poison pill).",[24360,24384,24386],{"name":24385,"type":24363},"MaximumRetryAttempts","Визначає граничну кількість спроб повторної обробки пакета при виникненні збоїв (діапазон від 0 до 10000). Після вичерпання ліміту пакет надсилається до Dead Letter Queue (DLQ) або відкидається.",[24360,24388,24391,24392,24395],{"name":24389,"type":24390},"FilterCriteria","object","Задає JSON-шаблони для фільтрації подій до моменту виклику обчислювальної функції. Наприклад, дає змогу відфільтрувати події так, щоб Lambda запускалася лише при створенні записів (",[3413,24393,24394],{},"eventName == INSERT","), економлячи обчислювальні ресурси.",[3727,24397,24399],{"id":24398},"увімкнення-streams-та-lambda-тригера","Увімкнення Streams та Lambda тригера",[6308,24401,24402,24625,25116],{},[6311,24403,24404],{"label":6313},[3406,24405,24407],{"className":6316,"code":24406,"language":6318,"meta":3411,"style":3411},"# ── Увімкнути Streams на таблиці ─────────────────────────────────────────\naws dynamodb update-table \\\n    --table-name Orders \\\n    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \\\n    --region eu-central-1\n\n# ── Отримати ARN потоку ───────────────────────────────────────────────────\nSTREAM_ARN=$(aws dynamodb describe-table \\\n    --table-name Orders \\\n    --query \"Table.LatestStreamArn\" \\\n    --output text \\\n    --region eu-central-1)\necho \"Stream ARN: $STREAM_ARN\"\n\n# ── Підключити Lambda до потоку ───────────────────────────────────────────\naws lambda create-event-source-mapping \\\n    --function-name OrderStreamProcessor \\\n    --event-source-arn \"$STREAM_ARN\" \\\n    --batch-size 100 \\\n    --starting-position LATEST \\\n    --bisect-batch-on-function-error \\\n    --maximum-retry-attempts 3 \\\n    --filter-criteria '{\"Filters\": [{\"Pattern\": \"{\\\"eventName\\\": [\\\"INSERT\\\", \\\"MODIFY\\\"]}\"}]}' \\\n    --region eu-central-1\n",[3413,24408,24409,24414,24424,24432,24447,24453,24457,24462,24478,24486,24495,24505,24513,24526,24530,24535,24547,24557,24572,24582,24592,24599,24609,24619],{"__ignoreMap":3411},[3416,24410,24411],{"class":3418,"line":3419},[3416,24412,24413],{"class":3789},"# ── Увімкнути Streams на таблиці ─────────────────────────────────────────\n",[3416,24415,24416,24418,24420,24422],{"class":3418,"line":3425},[3416,24417,6331],{"class":6330},[3416,24419,6334],{"class":3808},[3416,24421,17279],{"class":3808},[3416,24423,6341],{"class":6340},[3416,24425,24426,24428,24430],{"class":3418,"line":3431},[3416,24427,6346],{"class":4368},[3416,24429,19317],{"class":3808},[3416,24431,6341],{"class":6340},[3416,24433,24434,24437,24440,24442,24445],{"class":3418,"line":3437},[3416,24435,24436],{"class":4368},"    --stream-specification",[3416,24438,24439],{"class":3808}," StreamEnabled=",[3416,24441,4038],{"class":4368},[3416,24443,24444],{"class":3808},",StreamViewType=NEW_AND_OLD_IMAGES",[3416,24446,6341],{"class":6340},[3416,24448,24449,24451],{"class":3418,"line":3444},[3416,24450,6366],{"class":4368},[3416,24452,6369],{"class":3808},[3416,24454,24455],{"class":3418,"line":3450},[3416,24456,3441],{"emptyLinePlaceholder":3440},[3416,24458,24459],{"class":3418,"line":3456},[3416,24460,24461],{"class":3789},"# ── Отримати ARN потоку ───────────────────────────────────────────────────\n",[3416,24463,24464,24467,24470,24472,24474,24476],{"class":3418,"line":3462},[3416,24465,24466],{"class":6387},"STREAM_ARN",[3416,24468,24469],{"class":3795},"=$(",[3416,24471,6331],{"class":6330},[3416,24473,6334],{"class":3808},[3416,24475,11374],{"class":3808},[3416,24477,6341],{"class":6340},[3416,24479,24480,24482,24484],{"class":3418,"line":3468},[3416,24481,6346],{"class":4368},[3416,24483,19317],{"class":3808},[3416,24485,6341],{"class":6340},[3416,24487,24488,24490,24493],{"class":3418,"line":3474},[3416,24489,11398],{"class":4368},[3416,24491,24492],{"class":3808}," \"Table.LatestStreamArn\"",[3416,24494,6341],{"class":6340},[3416,24496,24497,24500,24503],{"class":3418,"line":3480},[3416,24498,24499],{"class":4368},"    --output",[3416,24501,24502],{"class":3808}," text",[3416,24504,6341],{"class":6340},[3416,24506,24507,24509,24511],{"class":3418,"line":3486},[3416,24508,6366],{"class":4368},[3416,24510,11391],{"class":3808},[3416,24512,9656],{"class":3795},[3416,24514,24515,24517,24520,24523],{"class":3418,"line":3492},[3416,24516,11353],{"class":6330},[3416,24518,24519],{"class":3808}," \"Stream ARN: ",[3416,24521,24522],{"class":6387},"$STREAM_ARN",[3416,24524,24525],{"class":3808},"\"\n",[3416,24527,24528],{"class":3418,"line":3498},[3416,24529,3441],{"emptyLinePlaceholder":3440},[3416,24531,24532],{"class":3418,"line":3504},[3416,24533,24534],{"class":3789},"# ── Підключити Lambda до потоку ───────────────────────────────────────────\n",[3416,24536,24537,24539,24542,24545],{"class":3418,"line":3510},[3416,24538,6331],{"class":6330},[3416,24540,24541],{"class":3808}," lambda",[3416,24543,24544],{"class":3808}," create-event-source-mapping",[3416,24546,6341],{"class":6340},[3416,24548,24549,24552,24555],{"class":3418,"line":3515},[3416,24550,24551],{"class":4368},"    --function-name",[3416,24553,24554],{"class":3808}," OrderStreamProcessor",[3416,24556,6341],{"class":6340},[3416,24558,24559,24562,24565,24567,24570],{"class":3418,"line":3521},[3416,24560,24561],{"class":4368},"    --event-source-arn",[3416,24563,24564],{"class":3808}," \"",[3416,24566,24522],{"class":6387},[3416,24568,24569],{"class":3808},"\"",[3416,24571,6341],{"class":6340},[3416,24573,24574,24577,24580],{"class":3418,"line":3527},[3416,24575,24576],{"class":4368},"    --batch-size",[3416,24578,24579],{"class":3870}," 100",[3416,24581,6341],{"class":6340},[3416,24583,24584,24587,24590],{"class":3418,"line":3533},[3416,24585,24586],{"class":4368},"    --starting-position",[3416,24588,24589],{"class":3808}," LATEST",[3416,24591,6341],{"class":6340},[3416,24593,24594,24597],{"class":3418,"line":3539},[3416,24595,24596],{"class":4368},"    --bisect-batch-on-function-error",[3416,24598,6341],{"class":6340},[3416,24600,24601,24604,24607],{"class":3418,"line":3545},[3416,24602,24603],{"class":4368},"    --maximum-retry-attempts",[3416,24605,24606],{"class":3870}," 3",[3416,24608,6341],{"class":6340},[3416,24610,24611,24614,24617],{"class":3418,"line":3551},[3416,24612,24613],{"class":4368},"    --filter-criteria",[3416,24615,24616],{"class":3808}," '{\"Filters\": [{\"Pattern\": \"{\\\"eventName\\\": [\\\"INSERT\\\", \\\"MODIFY\\\"]}\"}]}'",[3416,24618,6341],{"class":6340},[3416,24620,24621,24623],{"class":3418,"line":3557},[3416,24622,6366],{"class":4368},[3416,24624,6369],{"class":3808},[6311,24626,24627],{"label":6372},[3406,24628,24630],{"className":6375,"code":24629,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\nusing Amazon.Lambda;\nusing Amazon.Lambda.Model;\n\nvar ddbClient = new AmazonDynamoDBClient(Amazon.RegionEndpoint.EUCentral1);\nvar lambdaClient = new AmazonLambdaClient(Amazon.RegionEndpoint.EUCentral1);\n\n\u002F\u002F ── Увімкнути Streams на таблиці ─────────────────────────────────────────\nawait ddbClient.UpdateTableAsync(new UpdateTableRequest\n{\n    TableName = \"Orders\",\n    StreamSpecification = new StreamSpecification\n    {\n        StreamEnabled = true,\n        StreamViewType = StreamViewType.NEW_AND_OLD_IMAGES\n    }\n});\n\n\u002F\u002F ── Отримати ARN потоку ───────────────────────────────────────────────────\nvar tableDescription = await ddbClient.DescribeTableAsync(\"Orders\");\nstring streamArn = tableDescription.Table.LatestStreamArn;\nConsole.WriteLine($\"Stream ARN: {streamArn}\");\n\n\u002F\u002F ── Підключити Lambda до потоку ───────────────────────────────────────────\nawait lambdaClient.CreateEventSourceMappingAsync(new CreateEventSourceMappingRequest\n{\n    FunctionName = \"OrderStreamProcessor\",\n    EventSourceArn = streamArn,\n    BatchSize = 100,\n    StartingPosition = EventSourcePosition.LATEST,\n    BisectBatchOnFunctionError = true,\n    MaximumRetryAttempts = 3,\n    FilterCriteria = new FilterCriteria\n    {\n        Filters = new List\u003CFilter>\n        {\n            new() { Pattern = \"{\\\"eventName\\\": [\\\"INSERT\\\", \\\"MODIFY\\\"]}\" }\n        }\n    }\n});\n",[3413,24631,24632,24644,24660,24673,24689,24693,24719,24747,24751,24756,24772,24776,24786,24798,24802,24813,24828,24832,24836,24840,24845,24868,24891,24916,24920,24925,24943,24947,24959,24970,24981,24997,25008,25020,25032,25036,25054,25058,25104,25108,25112],{"__ignoreMap":3411},[3416,24633,24634,24636,24638,24640,24642],{"class":3418,"line":3419},[3416,24635,17433],{"class":11427},[3416,24637,17436],{"class":6397},[3416,24639,4043],{"class":3795},[3416,24641,17441],{"class":6397},[3416,24643,11594],{"class":3795},[3416,24645,24646,24648,24650,24652,24654,24656,24658],{"class":3418,"line":3425},[3416,24647,17433],{"class":11427},[3416,24649,17436],{"class":6397},[3416,24651,4043],{"class":3795},[3416,24653,17441],{"class":6397},[3416,24655,4043],{"class":3795},[3416,24657,17458],{"class":6397},[3416,24659,11594],{"class":3795},[3416,24661,24662,24664,24666,24668,24671],{"class":3418,"line":3431},[3416,24663,17433],{"class":11427},[3416,24665,17436],{"class":6397},[3416,24667,4043],{"class":3795},[3416,24669,24670],{"class":6397},"Lambda",[3416,24672,11594],{"class":3795},[3416,24674,24675,24677,24679,24681,24683,24685,24687],{"class":3418,"line":3437},[3416,24676,17433],{"class":11427},[3416,24678,17436],{"class":6397},[3416,24680,4043],{"class":3795},[3416,24682,24670],{"class":6397},[3416,24684,4043],{"class":3795},[3416,24686,17458],{"class":6397},[3416,24688,11594],{"class":3795},[3416,24690,24691],{"class":3418,"line":3444},[3416,24692,3441],{"emptyLinePlaceholder":3440},[3416,24694,24695,24697,24699,24701,24703,24705,24707,24709,24711,24713,24715,24717],{"class":3418,"line":3450},[3416,24696,6384],{"class":4368},[3416,24698,22796],{"class":6387},[3416,24700,6391],{"class":3795},[3416,24702,6394],{"class":4368},[3416,24704,6398],{"class":6397},[3416,24706,6423],{"class":3795},[3416,24708,22807],{"class":6387},[3416,24710,4043],{"class":3795},[3416,24712,22812],{"class":6387},[3416,24714,4043],{"class":3795},[3416,24716,22817],{"class":6387},[3416,24718,11465],{"class":3795},[3416,24720,24721,24723,24726,24728,24730,24733,24735,24737,24739,24741,24743,24745],{"class":3418,"line":3456},[3416,24722,6384],{"class":4368},[3416,24724,24725],{"class":6387}," lambdaClient",[3416,24727,6391],{"class":3795},[3416,24729,6394],{"class":4368},[3416,24731,24732],{"class":6397}," AmazonLambdaClient",[3416,24734,6423],{"class":3795},[3416,24736,22807],{"class":6387},[3416,24738,4043],{"class":3795},[3416,24740,22812],{"class":6387},[3416,24742,4043],{"class":3795},[3416,24744,22817],{"class":6387},[3416,24746,11465],{"class":3795},[3416,24748,24749],{"class":3418,"line":3462},[3416,24750,3441],{"emptyLinePlaceholder":3440},[3416,24752,24753],{"class":3418,"line":3468},[3416,24754,24755],{"class":3789},"\u002F\u002F ── Увімкнути Streams на таблиці ─────────────────────────────────────────\n",[3416,24757,24758,24760,24762,24764,24766,24768,24770],{"class":3418,"line":3474},[3416,24759,6413],{"class":4368},[3416,24761,22796],{"class":6387},[3416,24763,4043],{"class":3795},[3416,24765,17498],{"class":6330},[3416,24767,6423],{"class":3795},[3416,24769,6394],{"class":4368},[3416,24771,17505],{"class":6397},[3416,24773,24774],{"class":3418,"line":3480},[3416,24775,3796],{"class":3795},[3416,24777,24778,24780,24782,24784],{"class":3418,"line":3486},[3416,24779,6437],{"class":6387},[3416,24781,6391],{"class":3795},[3416,24783,19785],{"class":3808},[3416,24785,3812],{"class":3795},[3416,24787,24788,24791,24793,24795],{"class":3418,"line":3492},[3416,24789,24790],{"class":6387},"    StreamSpecification",[3416,24792,6391],{"class":3795},[3416,24794,6394],{"class":4368},[3416,24796,24797],{"class":6397}," StreamSpecification\n",[3416,24799,24800],{"class":3418,"line":3498},[3416,24801,6474],{"class":3795},[3416,24803,24804,24807,24809,24811],{"class":3418,"line":3504},[3416,24805,24806],{"class":6387},"        StreamEnabled",[3416,24808,6391],{"class":3795},[3416,24810,4038],{"class":4368},[3416,24812,3812],{"class":3795},[3416,24814,24815,24818,24820,24823,24825],{"class":3418,"line":3510},[3416,24816,24817],{"class":6387},"        StreamViewType",[3416,24819,6391],{"class":3795},[3416,24821,24822],{"class":6387},"StreamViewType",[3416,24824,4043],{"class":3795},[3416,24826,24827],{"class":6387},"NEW_AND_OLD_IMAGES\n",[3416,24829,24830],{"class":3418,"line":3515},[3416,24831,4167],{"class":3795},[3416,24833,24834],{"class":3418,"line":3521},[3416,24835,6537],{"class":3795},[3416,24837,24838],{"class":3418,"line":3527},[3416,24839,3441],{"emptyLinePlaceholder":3440},[3416,24841,24842],{"class":3418,"line":3533},[3416,24843,24844],{"class":3789},"\u002F\u002F ── Отримати ARN потоку ───────────────────────────────────────────────────\n",[3416,24846,24847,24849,24852,24854,24856,24858,24860,24862,24864,24866],{"class":3418,"line":3539},[3416,24848,6384],{"class":4368},[3416,24850,24851],{"class":6387}," tableDescription",[3416,24853,6391],{"class":3795},[3416,24855,6413],{"class":4368},[3416,24857,22796],{"class":6387},[3416,24859,4043],{"class":3795},[3416,24861,11458],{"class":6330},[3416,24863,6423],{"class":3795},[3416,24865,19785],{"class":3808},[3416,24867,11465],{"class":3795},[3416,24869,24870,24872,24875,24877,24880,24882,24884,24886,24889],{"class":3418,"line":3545},[3416,24871,6461],{"class":4368},[3416,24873,24874],{"class":6387}," streamArn",[3416,24876,6391],{"class":3795},[3416,24878,24879],{"class":6387},"tableDescription",[3416,24881,4043],{"class":3795},[3416,24883,11480],{"class":6387},[3416,24885,4043],{"class":3795},[3416,24887,24888],{"class":6387},"LatestStreamArn",[3416,24890,11594],{"class":3795},[3416,24892,24893,24896,24898,24900,24902,24905,24907,24910,24912,24914],{"class":3418,"line":3551},[3416,24894,24895],{"class":6387},"Console",[3416,24897,4043],{"class":3795},[3416,24899,11510],{"class":6330},[3416,24901,6423],{"class":3795},[3416,24903,24904],{"class":3808},"$\"Stream ARN: ",[3416,24906,11177],{"class":11533},[3416,24908,24909],{"class":6387},"streamArn",[3416,24911,11302],{"class":11533},[3416,24913,24569],{"class":3808},[3416,24915,11465],{"class":3795},[3416,24917,24918],{"class":3418,"line":3557},[3416,24919,3441],{"emptyLinePlaceholder":3440},[3416,24921,24922],{"class":3418,"line":3563},[3416,24923,24924],{"class":3789},"\u002F\u002F ── Підключити Lambda до потоку ───────────────────────────────────────────\n",[3416,24926,24927,24929,24931,24933,24936,24938,24940],{"class":3418,"line":3569},[3416,24928,6413],{"class":4368},[3416,24930,24725],{"class":6387},[3416,24932,4043],{"class":3795},[3416,24934,24935],{"class":6330},"CreateEventSourceMappingAsync",[3416,24937,6423],{"class":3795},[3416,24939,6394],{"class":4368},[3416,24941,24942],{"class":6397}," CreateEventSourceMappingRequest\n",[3416,24944,24945],{"class":3418,"line":3574},[3416,24946,3796],{"class":3795},[3416,24948,24949,24952,24954,24957],{"class":3418,"line":3579},[3416,24950,24951],{"class":6387},"    FunctionName",[3416,24953,6391],{"class":3795},[3416,24955,24956],{"class":3808},"\"OrderStreamProcessor\"",[3416,24958,3812],{"class":3795},[3416,24960,24961,24964,24966,24968],{"class":3418,"line":3584},[3416,24962,24963],{"class":6387},"    EventSourceArn",[3416,24965,6391],{"class":3795},[3416,24967,24909],{"class":6387},[3416,24969,3812],{"class":3795},[3416,24971,24972,24975,24977,24979],{"class":3418,"line":3590},[3416,24973,24974],{"class":6387},"    BatchSize",[3416,24976,6391],{"class":3795},[3416,24978,23133],{"class":3870},[3416,24980,3812],{"class":3795},[3416,24982,24983,24986,24988,24991,24993,24995],{"class":3418,"line":3596},[3416,24984,24985],{"class":6387},"    StartingPosition",[3416,24987,6391],{"class":3795},[3416,24989,24990],{"class":6387},"EventSourcePosition",[3416,24992,4043],{"class":3795},[3416,24994,24372],{"class":6387},[3416,24996,3812],{"class":3795},[3416,24998,24999,25002,25004,25006],{"class":3418,"line":3602},[3416,25000,25001],{"class":6387},"    BisectBatchOnFunctionError",[3416,25003,6391],{"class":3795},[3416,25005,4038],{"class":4368},[3416,25007,3812],{"class":3795},[3416,25009,25010,25013,25015,25018],{"class":3418,"line":3608},[3416,25011,25012],{"class":6387},"    MaximumRetryAttempts",[3416,25014,6391],{"class":3795},[3416,25016,25017],{"class":3870},"3",[3416,25019,3812],{"class":3795},[3416,25021,25022,25025,25027,25029],{"class":3418,"line":3614},[3416,25023,25024],{"class":6387},"    FilterCriteria",[3416,25026,6391],{"class":3795},[3416,25028,6394],{"class":4368},[3416,25030,25031],{"class":6397}," FilterCriteria\n",[3416,25033,25034],{"class":3418,"line":3620},[3416,25035,6474],{"class":3795},[3416,25037,25038,25041,25043,25045,25047,25049,25052],{"class":3418,"line":3626},[3416,25039,25040],{"class":6387},"        Filters",[3416,25042,6391],{"class":3795},[3416,25044,6394],{"class":4368},[3416,25046,8640],{"class":6397},[3416,25048,5861],{"class":3795},[3416,25050,25051],{"class":6397},"Filter",[3416,25053,6469],{"class":3795},[3416,25055,25056],{"class":3418,"line":3631},[3416,25057,8611],{"class":3795},[3416,25059,25060,25063,25065,25068,25070,25073,25076,25079,25081,25083,25085,25088,25090,25092,25094,25097,25099,25102],{"class":3418,"line":3636},[3416,25061,25062],{"class":4368},"            new",[3416,25064,17546],{"class":3795},[3416,25066,25067],{"class":6387},"Pattern",[3416,25069,6391],{"class":3795},[3416,25071,25072],{"class":3808},"\"{",[3416,25074,25075],{"class":6340},"\\\"",[3416,25077,25078],{"class":3808},"eventName",[3416,25080,25075],{"class":6340},[3416,25082,4378],{"class":3808},[3416,25084,25075],{"class":6340},[3416,25086,25087],{"class":3808},"INSERT",[3416,25089,25075],{"class":6340},[3416,25091,4384],{"class":3808},[3416,25093,25075],{"class":6340},[3416,25095,25096],{"class":3808},"MODIFY",[3416,25098,25075],{"class":6340},[3416,25100,25101],{"class":3808},"]}\"",[3416,25103,8948],{"class":3795},[3416,25105,25106],{"class":3418,"line":3641},[3416,25107,8533],{"class":3795},[3416,25109,25110],{"class":3418,"line":3647},[3416,25111,4167],{"class":3795},[3416,25113,25114],{"class":3418,"line":3653},[3416,25115,6537],{"class":3795},[6311,25117,25118],{"label":6540},[3406,25119,25121],{"className":6543,"code":25120,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\nImport-Module AWS.Tools.Lambda\n\n# ── Увімкнути Streams на таблиці ─────────────────────────────────────────\n$streamSpec = [Amazon.DynamoDBv2.Model.StreamSpecification]@{\n    StreamEnabled  = $true\n    StreamViewType = 'NEW_AND_OLD_IMAGES'\n}\nUpdate-DDBTable `\n    -TableName Orders `\n    -StreamSpecification $streamSpec `\n    -Region eu-central-1\n\n# ── Отримати ARN потоку ───────────────────────────────────────────────────\n$tableDesc = Get-DDBTable -TableName Orders -Region eu-central-1\n$streamArn = $tableDesc.LatestStreamArn\nWrite-Host \"Stream ARN: $streamArn\"\n\n# ── Підключити Lambda до потоку ───────────────────────────────────────────\n$filterPattern = '{\"Filters\": [{\"Pattern\": \"{\\\"eventName\\\": [\\\"INSERT\\\", \\\"MODIFY\\\"]}\"}]}'\n$filterCriteria = [Amazon.Lambda.Model.FilterCriteria]@{\n    Filters = @([Amazon.Lambda.Model.Filter]@{ Pattern = $filterPattern })\n}\nNew-LMEventSourceMapping `\n    -FunctionName OrderStreamProcessor `\n    -EventSourceArn $streamArn `\n    -BatchSize 100 `\n    -StartingPosition LATEST `\n    -BisectBatchOnFunctionError $true `\n    -MaximumRetryAttempt 3 `\n    -FilterCriteria $filterCriteria `\n    -Region eu-central-1\n",[3413,25122,25123,25129,25136,25140,25144,25160,25169,25179,25183,25189,25193,25202,25208,25212,25216,25230,25242,25252,25256,25260,25270,25286,25316,25320,25327,25332,25341,25350,25355,25365,25374,25383],{"__ignoreMap":3411},[3416,25124,25125,25127],{"class":3418,"line":3419},[3416,25126,12967],{"class":6330},[3416,25128,12970],{"class":3795},[3416,25130,25131,25133],{"class":3418,"line":3425},[3416,25132,12967],{"class":6330},[3416,25134,25135],{"class":3795}," AWS.Tools.Lambda\n",[3416,25137,25138],{"class":3418,"line":3431},[3416,25139,3441],{"emptyLinePlaceholder":3440},[3416,25141,25142],{"class":3418,"line":3437},[3416,25143,24413],{"class":3789},[3416,25145,25146,25149,25151,25154,25156,25158],{"class":3418,"line":3444},[3416,25147,25148],{"class":6387},"$streamSpec",[3416,25150,7274],{"class":3795},[3416,25152,25153],{"class":4368},"Amazon.DynamoDBv2.Model.StreamSpecification",[3416,25155,7280],{"class":3795},[3416,25157,6561],{"class":4368},[3416,25159,3796],{"class":3795},[3416,25161,25162,25165,25167],{"class":3418,"line":3450},[3416,25163,25164],{"class":6387},"    StreamEnabled",[3416,25166,6933],{"class":3795},[3416,25168,6941],{"class":4368},[3416,25170,25171,25174,25176],{"class":3418,"line":3456},[3416,25172,25173],{"class":6387},"    StreamViewType",[3416,25175,6391],{"class":3795},[3416,25177,25178],{"class":3808},"'NEW_AND_OLD_IMAGES'\n",[3416,25180,25181],{"class":3418,"line":3462},[3416,25182,3507],{"class":3795},[3416,25184,25185,25187],{"class":3418,"line":3468},[3416,25186,18062],{"class":6330},[3416,25188,11105],{"class":3795},[3416,25190,25191],{"class":3418,"line":3474},[3416,25192,21143],{"class":3795},[3416,25194,25195,25198,25200],{"class":3418,"line":3480},[3416,25196,25197],{"class":3795},"    -StreamSpecification ",[3416,25199,25148],{"class":6387},[3416,25201,11105],{"class":3795},[3416,25203,25204,25206],{"class":3418,"line":3486},[3416,25205,21235],{"class":3795},[3416,25207,6614],{"class":3870},[3416,25209,25210],{"class":3418,"line":3492},[3416,25211,3441],{"emptyLinePlaceholder":3440},[3416,25213,25214],{"class":3418,"line":3498},[3416,25215,24461],{"class":3789},[3416,25217,25218,25221,25223,25225,25228],{"class":3418,"line":3504},[3416,25219,25220],{"class":6387},"$tableDesc",[3416,25222,6391],{"class":3795},[3416,25224,11670],{"class":6330},[3416,25226,25227],{"class":3795}," -TableName Orders -Region eu-central-",[3416,25229,6614],{"class":3870},[3416,25231,25232,25235,25237,25239],{"class":3418,"line":3510},[3416,25233,25234],{"class":6387},"$streamArn",[3416,25236,6391],{"class":3795},[3416,25238,25220],{"class":6387},[3416,25240,25241],{"class":6330},".LatestStreamArn\n",[3416,25243,25244,25246,25248,25250],{"class":3418,"line":3515},[3416,25245,11761],{"class":6330},[3416,25247,24519],{"class":3808},[3416,25249,25234],{"class":6387},[3416,25251,24525],{"class":3808},[3416,25253,25254],{"class":3418,"line":3521},[3416,25255,3441],{"emptyLinePlaceholder":3440},[3416,25257,25258],{"class":3418,"line":3527},[3416,25259,24534],{"class":3789},[3416,25261,25262,25265,25267],{"class":3418,"line":3533},[3416,25263,25264],{"class":6387},"$filterPattern",[3416,25266,6391],{"class":3795},[3416,25268,25269],{"class":3808},"'{\"Filters\": [{\"Pattern\": \"{\\\"eventName\\\": [\\\"INSERT\\\", \\\"MODIFY\\\"]}\"}]}'\n",[3416,25271,25272,25275,25277,25280,25282,25284],{"class":3418,"line":3539},[3416,25273,25274],{"class":6387},"$filterCriteria",[3416,25276,7274],{"class":3795},[3416,25278,25279],{"class":4368},"Amazon.Lambda.Model.FilterCriteria",[3416,25281,7280],{"class":3795},[3416,25283,6561],{"class":4368},[3416,25285,3796],{"class":3795},[3416,25287,25288,25291,25293,25295,25298,25301,25303,25305,25307,25309,25311,25313],{"class":3418,"line":3545},[3416,25289,25290],{"class":6387},"    Filters",[3416,25292,6391],{"class":3795},[3416,25294,6561],{"class":4368},[3416,25296,25297],{"class":3795},"([",[3416,25299,25300],{"class":4368},"Amazon.Lambda.Model.Filter",[3416,25302,7280],{"class":3795},[3416,25304,6561],{"class":4368},[3416,25306,8886],{"class":3795},[3416,25308,25067],{"class":6387},[3416,25310,6391],{"class":3795},[3416,25312,25264],{"class":6387},[3416,25314,25315],{"class":3795}," })\n",[3416,25317,25318],{"class":3418,"line":3551},[3416,25319,3507],{"class":3795},[3416,25321,25322,25325],{"class":3418,"line":3557},[3416,25323,25324],{"class":6330},"New-LMEventSourceMapping",[3416,25326,11105],{"class":3795},[3416,25328,25329],{"class":3418,"line":3563},[3416,25330,25331],{"class":3795},"    -FunctionName OrderStreamProcessor `\n",[3416,25333,25334,25337,25339],{"class":3418,"line":3569},[3416,25335,25336],{"class":3795},"    -EventSourceArn ",[3416,25338,25234],{"class":6387},[3416,25340,11105],{"class":3795},[3416,25342,25343,25346,25348],{"class":3418,"line":3574},[3416,25344,25345],{"class":3795},"    -BatchSize ",[3416,25347,23133],{"class":3870},[3416,25349,11105],{"class":3795},[3416,25351,25352],{"class":3418,"line":3579},[3416,25353,25354],{"class":3795},"    -StartingPosition LATEST `\n",[3416,25356,25357,25360,25363],{"class":3418,"line":3584},[3416,25358,25359],{"class":3795},"    -BisectBatchOnFunctionError ",[3416,25361,25362],{"class":4368},"$true",[3416,25364,11105],{"class":3795},[3416,25366,25367,25370,25372],{"class":3418,"line":3590},[3416,25368,25369],{"class":3795},"    -MaximumRetryAttempt ",[3416,25371,25017],{"class":3870},[3416,25373,11105],{"class":3795},[3416,25375,25376,25379,25381],{"class":3418,"line":3596},[3416,25377,25378],{"class":3795},"    -FilterCriteria ",[3416,25380,25274],{"class":6387},[3416,25382,11105],{"class":3795},[3416,25384,25385,25387],{"class":3418,"line":3602},[3416,25386,21235],{"class":3795},[3416,25388,6614],{"class":3870},[3720,25390],{},[3727,25392,25394],{"id":25393},"транзакції-в-dynamodb-внутрішня-механіка-та-acid-гарантії","Транзакції в DynamoDB — внутрішня механіка та ACID-гарантії",[3353,25396,25397,25398,5167,25400,25402,25403,25406],{},"Починаючи з 2018 року, Amazon DynamoDB підтримує виконання транзакційних запитів за допомогою інтерфейсів ",[3413,25399,13840],{},[3413,25401,13624],{},". Це дозволяє виконувати атомарні операції над групою до ",[3363,25404,25405],{},"100 елементів"," (або сумарним обсягом до 4 MB) в межах однієї транзакції, навіть якщо елементи розташовані в різних фізичних таблицях одного AWS-аккаунта та регіону.",[4584,25408,25410],{"id":25409},"життєвий-цикл-транзакції-та-протокол-two-phase-commit-2pc","Життєвий цикл транзакції та протокол Two-Phase Commit (2PC)",[3353,25412,25413],{},"Під капом DynamoDB використовує адаптований протокол двофазного коміту (Two-Phase Commit, 2PC), який координується внутрішньою інфраструктурою бази даних:",[3374,25415,25416,25438],{},[3377,25417,25418,25421],{},[3363,25419,25420],{},"Фаза підготовки (Prepare Phase):",[4488,25422,25423,25426,25429,25435],{},[3377,25424,25425],{},"Координатор транзакції перевіряє ліміти та права доступу.",[3377,25427,25428],{},"Надсилаються запити на вузли партицій, де зберігаються відповідні елементи.",[3377,25430,25431,25432,25434],{},"На кожному вузлі перевіряються умови ",[3413,25433,13830],{},". Якщо хоча б одна умова не виконується (або елемент заблоковано іншою транзакцією), транзакція негайно скасовується.",[3377,25436,25437],{},"Елементи тимчасово блокуються для модифікації іншими конкурентними транзакціями.",[3377,25439,25440,25443],{},[3363,25441,25442],{},"Фаза фіксації (Commit Phase):",[4488,25444,25445,25448,25451],{},[3377,25446,25447],{},"Якщо перша фаза завершилися успішно на всіх вузлах, координатор приймає рішення про фіксацію.",[3377,25449,25450],{},"Зміни застосовуються на фізичному рівні, створюються нові версії елементів і знімаються блокування.",[3377,25452,25453],{},"У разі виникнення помилки на фазі підготовки ініціюється процес відкату (Rollback), і всі проміжні блокування знімаються без внесення змін до бази даних.",[4584,25455,25457,25458,10458],{"id":25456},"специфікація-операцій-у-transactwriteitems","Специфікація операцій у ",[3413,25459,13840],{},[4488,25461,25462,25468,25474,25480],{},[3377,25463,25464,25467],{},[3413,25465,25466],{},"Put",": Запис або повна заміна елемента.",[3377,25469,25470,25473],{},[3413,25471,25472],{},"Update",": Модифікація окремих атрибутів існуючого елемента.",[3377,25475,25476,25479],{},[3413,25477,25478],{},"Delete",": Видалення елемента.",[3377,25481,25482,25485],{},[3413,25483,25484],{},"ConditionCheck",": Перевірка стану елемента без його фактичної модифікації (критично для валідації зв'язаних сутностей).",[22319,25487,25488],{},[3353,25489,25490,25493,25496,25497,25500],{},[3416,25491,25492],{},"!CAUTION",[3363,25494,25495],{},"Подвійна вартість транзакцій (Transaction Cost Penalty)","\nТранзакційні операції споживають ",[3363,25498,25499],{},"вдвічі більше"," RCU та WCU порівняно зі стандартними запитами. Наприклад, транзакційний запис об'єкта розміром 1 KB споживає 2 WCU (замість 1 WCU), а strongly consistent читання блоку 4 KB споживає 2 RCU (замість 1 RCU).",[3403,25502,25503],{},[3406,25504,25506],{"className":3408,"code":25505,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Схема транзакційного переказу балів лояльності (2PC)\n\nactor \"API Запит\" as api\n\nbox \"Атомарна транзакція DynamoDB\" #E8F4FD\n  database \"Таблиця Users\\n(Користувач А)\" as ua\n  database \"Таблиця Users\\n(Користувач Б)\" as ub\n  database \"Таблиця Transactions\\n(Журнал транзакцій)\" as tx\nend box\n\napi -> ua : \"1. ConditionCheck: balance >= 100\\n(Фаза 1: Валідація лімітів)\"\napi -> ua : \"2. Update: balance = balance - 100\\n(Фаза 1: Тимчасове блокування)\"\napi -> ub : \"3. Update: balance = balance + 100\\n(Фаза 1: Тимчасове блокування)\"\napi -> tx : \"4. Put: Запис логу переказу\\n(Фаза 1: Підготовка запису)\"\n\nalt Усі перевірки успішні (Commit)\n  api --> ua : \"Застосування змін (Фаза 2)\"\n  api --> ub : \"Застосування змін (Фаза 2)\"\n  api --> tx : \"Фіксація запису (Фаза 2)\"\n  ua --> api : \"HTTP 200 OK (Успішне завершення)\"\n  ub --> api : \"HTTP 200 OK\"\n  tx --> api : \"HTTP 200 OK\"\nelse Будь-який ConditionCheck провалився (Rollback)\n  ua --> api : \"TransactionCanceledException\\n(Усі проміжні зміни скасовано)\"\n  ub --> api : \"TransactionCanceledException\"\n  tx --> api : \"TransactionCanceledException\"\nend\n@enduml\n",[3413,25507,25508,25512,25516,25520,25524,25528,25533,25537,25542,25546,25551,25556,25561,25566,25571,25575,25580,25585,25590,25595,25599,25604,25609,25614,25619,25624,25629,25634,25639,25644,25649,25654,25659],{"__ignoreMap":3411},[3416,25509,25510],{"class":3418,"line":3419},[3416,25511,3422],{},[3416,25513,25514],{"class":3418,"line":3425},[3416,25515,16755],{},[3416,25517,25518],{"class":3418,"line":3431},[3416,25519,16760],{},[3416,25521,25522],{"class":3418,"line":3437},[3416,25523,16765],{},[3416,25525,25526],{"class":3418,"line":3444},[3416,25527,3441],{"emptyLinePlaceholder":3440},[3416,25529,25530],{"class":3418,"line":3450},[3416,25531,25532],{},"title Схема транзакційного переказу балів лояльності (2PC)\n",[3416,25534,25535],{"class":3418,"line":3456},[3416,25536,3441],{"emptyLinePlaceholder":3440},[3416,25538,25539],{"class":3418,"line":3462},[3416,25540,25541],{},"actor \"API Запит\" as api\n",[3416,25543,25544],{"class":3418,"line":3468},[3416,25545,3441],{"emptyLinePlaceholder":3440},[3416,25547,25548],{"class":3418,"line":3474},[3416,25549,25550],{},"box \"Атомарна транзакція DynamoDB\" #E8F4FD\n",[3416,25552,25553],{"class":3418,"line":3480},[3416,25554,25555],{},"  database \"Таблиця Users\\n(Користувач А)\" as ua\n",[3416,25557,25558],{"class":3418,"line":3486},[3416,25559,25560],{},"  database \"Таблиця Users\\n(Користувач Б)\" as ub\n",[3416,25562,25563],{"class":3418,"line":3492},[3416,25564,25565],{},"  database \"Таблиця Transactions\\n(Журнал транзакцій)\" as tx\n",[3416,25567,25568],{"class":3418,"line":3498},[3416,25569,25570],{},"end box\n",[3416,25572,25573],{"class":3418,"line":3504},[3416,25574,3441],{"emptyLinePlaceholder":3440},[3416,25576,25577],{"class":3418,"line":3510},[3416,25578,25579],{},"api -> ua : \"1. ConditionCheck: balance >= 100\\n(Фаза 1: Валідація лімітів)\"\n",[3416,25581,25582],{"class":3418,"line":3515},[3416,25583,25584],{},"api -> ua : \"2. Update: balance = balance - 100\\n(Фаза 1: Тимчасове блокування)\"\n",[3416,25586,25587],{"class":3418,"line":3521},[3416,25588,25589],{},"api -> ub : \"3. Update: balance = balance + 100\\n(Фаза 1: Тимчасове блокування)\"\n",[3416,25591,25592],{"class":3418,"line":3527},[3416,25593,25594],{},"api -> tx : \"4. Put: Запис логу переказу\\n(Фаза 1: Підготовка запису)\"\n",[3416,25596,25597],{"class":3418,"line":3533},[3416,25598,3441],{"emptyLinePlaceholder":3440},[3416,25600,25601],{"class":3418,"line":3539},[3416,25602,25603],{},"alt Усі перевірки успішні (Commit)\n",[3416,25605,25606],{"class":3418,"line":3545},[3416,25607,25608],{},"  api --> ua : \"Застосування змін (Фаза 2)\"\n",[3416,25610,25611],{"class":3418,"line":3551},[3416,25612,25613],{},"  api --> ub : \"Застосування змін (Фаза 2)\"\n",[3416,25615,25616],{"class":3418,"line":3557},[3416,25617,25618],{},"  api --> tx : \"Фіксація запису (Фаза 2)\"\n",[3416,25620,25621],{"class":3418,"line":3563},[3416,25622,25623],{},"  ua --> api : \"HTTP 200 OK (Успішне завершення)\"\n",[3416,25625,25626],{"class":3418,"line":3569},[3416,25627,25628],{},"  ub --> api : \"HTTP 200 OK\"\n",[3416,25630,25631],{"class":3418,"line":3574},[3416,25632,25633],{},"  tx --> api : \"HTTP 200 OK\"\n",[3416,25635,25636],{"class":3418,"line":3579},[3416,25637,25638],{},"else Будь-який ConditionCheck провалився (Rollback)\n",[3416,25640,25641],{"class":3418,"line":3584},[3416,25642,25643],{},"  ua --> api : \"TransactionCanceledException\\n(Усі проміжні зміни скасовано)\"\n",[3416,25645,25646],{"class":3418,"line":3590},[3416,25647,25648],{},"  ub --> api : \"TransactionCanceledException\"\n",[3416,25650,25651],{"class":3418,"line":3596},[3416,25652,25653],{},"  tx --> api : \"TransactionCanceledException\"\n",[3416,25655,25656],{"class":3418,"line":3602},[3416,25657,25658],{},"end\n",[3416,25660,25661],{"class":3418,"line":3608},[3416,25662,3718],{},[3727,25664,25666],{"id":25665},"практичний-сценарій-транзакційне-оформлення-замовлення-e-commerce","Практичний сценарій: Транзакційне оформлення замовлення (E-commerce)",[3353,25668,25669,25670,25672,25673,25675,25676,13590],{},"При оформленні замовлення додаток повинен гарантувати атомарність трьох дій: перевірити наявність задовільної кількості товару на складі (",[3413,25671,25484],{},"), зменшити цю кількість (",[3413,25674,25472],{},") та безпосередньо створити картку замовлення (",[3413,25677,25466],{},[6308,25679,25680,25902,26768],{},[6311,25681,25682],{"label":6313},[3406,25683,25685],{"className":6316,"code":25684,"language":6318,"meta":3411,"style":3411},"# ── Виконання транзакційного запису TransactWriteItems ──────────────────────\naws dynamodb transact-write-items \\\n    --transact-items '[\n        {\n            \"ConditionCheck\": {\n                \"TableName\": \"Inventory\",\n                \"Key\": {\"ProductId\": {\"S\": \"prod-42\"}},\n                \"ConditionExpression\": \"quantity >= :qty\",\n                \"ExpressionAttributeValues\": {\":qty\": {\"N\": \"2\"}}\n            }\n        },\n        {\n            \"Update\": {\n                \"TableName\": \"Inventory\",\n                \"Key\": {\"ProductId\": {\"S\": \"prod-42\"}},\n                \"UpdateExpression\": \"SET quantity = quantity - :qty\",\n                \"ExpressionAttributeValues\": {\":qty\": {\"N\": \"2\"}}\n            }\n        },\n        {\n            \"Put\": {\n                \"TableName\": \"Orders\",\n                \"Item\": {\n                    \"CustomerId\":  {\"S\": \"usr-001\"},\n                    \"OrderId\":     {\"S\": \"ord-2026-001\"},\n                    \"ProductId\":   {\"S\": \"prod-42\"},\n                    \"Quantity\":    {\"N\": \"2\"},\n                    \"Status\":      {\"S\": \"PENDING\"},\n                    \"CreatedAt\":   {\"S\": \"2026-06-03T12:00:00Z\"}\n                },\n                \"ConditionExpression\": \"attribute_not_exists(OrderId)\"\n            }\n        }\n    ]' \\\n    --region eu-central-1\n\n# ── Отримання кількох елементів у транзакційному режимі TransactGetItems ──────\naws dynamodb transact-get-items \\\n    --transact-items '[\n        {\"Get\": {\"TableName\": \"Orders\",    \"Key\": {\"CustomerId\": {\"S\": \"usr-001\"}, \"OrderId\": {\"S\": \"ord-2026-001\"}}}},\n        {\"Get\": {\"TableName\": \"Inventory\", \"Key\": {\"ProductId\": {\"S\": \"prod-42\"}}}}\n    ]' \\\n    --region eu-central-1\n",[3413,25686,25687,25692,25702,25708,25712,25717,25722,25727,25732,25737,25741,25745,25749,25753,25757,25761,25766,25770,25774,25778,25782,25786,25791,25795,25800,25805,25810,25815,25820,25825,25829,25834,25838,25842,25848,25854,25858,25863,25874,25880,25885,25890,25896],{"__ignoreMap":3411},[3416,25688,25689],{"class":3418,"line":3419},[3416,25690,25691],{"class":3789},"# ── Виконання транзакційного запису TransactWriteItems ──────────────────────\n",[3416,25693,25694,25696,25698,25700],{"class":3418,"line":3425},[3416,25695,6331],{"class":6330},[3416,25697,6334],{"class":3808},[3416,25699,9717],{"class":3808},[3416,25701,6341],{"class":6340},[3416,25703,25704,25706],{"class":3418,"line":3431},[3416,25705,9724],{"class":4368},[3416,25707,9727],{"class":3808},[3416,25709,25710],{"class":3418,"line":3437},[3416,25711,8611],{"class":3808},[3416,25713,25714],{"class":3418,"line":3444},[3416,25715,25716],{"class":3808},"            \"ConditionCheck\": {\n",[3416,25718,25719],{"class":3418,"line":3450},[3416,25720,25721],{"class":3808},"                \"TableName\": \"Inventory\",\n",[3416,25723,25724],{"class":3418,"line":3456},[3416,25725,25726],{"class":3808},"                \"Key\": {\"ProductId\": {\"S\": \"prod-42\"}},\n",[3416,25728,25729],{"class":3418,"line":3462},[3416,25730,25731],{"class":3808},"                \"ConditionExpression\": \"quantity >= :qty\",\n",[3416,25733,25734],{"class":3418,"line":3468},[3416,25735,25736],{"class":3808},"                \"ExpressionAttributeValues\": {\":qty\": {\"N\": \"2\"}}\n",[3416,25738,25739],{"class":3418,"line":3474},[3416,25740,8815],{"class":3808},[3416,25742,25743],{"class":3418,"line":3480},[3416,25744,9774],{"class":3808},[3416,25746,25747],{"class":3418,"line":3486},[3416,25748,8611],{"class":3808},[3416,25750,25751],{"class":3418,"line":3492},[3416,25752,9783],{"class":3808},[3416,25754,25755],{"class":3418,"line":3498},[3416,25756,25721],{"class":3808},[3416,25758,25759],{"class":3418,"line":3504},[3416,25760,25726],{"class":3808},[3416,25762,25763],{"class":3418,"line":3510},[3416,25764,25765],{"class":3808},"                \"UpdateExpression\": \"SET quantity = quantity - :qty\",\n",[3416,25767,25768],{"class":3418,"line":3515},[3416,25769,25736],{"class":3808},[3416,25771,25772],{"class":3418,"line":3521},[3416,25773,8815],{"class":3808},[3416,25775,25776],{"class":3418,"line":3527},[3416,25777,9774],{"class":3808},[3416,25779,25780],{"class":3418,"line":3533},[3416,25781,8611],{"class":3808},[3416,25783,25784],{"class":3418,"line":3539},[3416,25785,9736],{"class":3808},[3416,25787,25788],{"class":3418,"line":3545},[3416,25789,25790],{"class":3808},"                \"TableName\": \"Orders\",\n",[3416,25792,25793],{"class":3418,"line":3551},[3416,25794,9746],{"class":3808},[3416,25796,25797],{"class":3418,"line":3557},[3416,25798,25799],{"class":3808},"                    \"CustomerId\":  {\"S\": \"usr-001\"},\n",[3416,25801,25802],{"class":3418,"line":3563},[3416,25803,25804],{"class":3808},"                    \"OrderId\":     {\"S\": \"ord-2026-001\"},\n",[3416,25806,25807],{"class":3418,"line":3569},[3416,25808,25809],{"class":3808},"                    \"ProductId\":   {\"S\": \"prod-42\"},\n",[3416,25811,25812],{"class":3418,"line":3574},[3416,25813,25814],{"class":3808},"                    \"Quantity\":    {\"N\": \"2\"},\n",[3416,25816,25817],{"class":3418,"line":3579},[3416,25818,25819],{"class":3808},"                    \"Status\":      {\"S\": \"PENDING\"},\n",[3416,25821,25822],{"class":3418,"line":3584},[3416,25823,25824],{"class":3808},"                    \"CreatedAt\":   {\"S\": \"2026-06-03T12:00:00Z\"}\n",[3416,25826,25827],{"class":3418,"line":3590},[3416,25828,9344],{"class":3808},[3416,25830,25831],{"class":3418,"line":3596},[3416,25832,25833],{"class":3808},"                \"ConditionExpression\": \"attribute_not_exists(OrderId)\"\n",[3416,25835,25836],{"class":3418,"line":3602},[3416,25837,8815],{"class":3808},[3416,25839,25840],{"class":3418,"line":3608},[3416,25841,8533],{"class":3808},[3416,25843,25844,25846],{"class":3418,"line":3614},[3416,25845,9816],{"class":3808},[3416,25847,6341],{"class":6340},[3416,25849,25850,25852],{"class":3418,"line":3620},[3416,25851,6366],{"class":4368},[3416,25853,6369],{"class":3808},[3416,25855,25856],{"class":3418,"line":3626},[3416,25857,3441],{"emptyLinePlaceholder":3440},[3416,25859,25860],{"class":3418,"line":3631},[3416,25861,25862],{"class":3789},"# ── Отримання кількох елементів у транзакційному режимі TransactGetItems ──────\n",[3416,25864,25865,25867,25869,25872],{"class":3418,"line":3636},[3416,25866,6331],{"class":6330},[3416,25868,6334],{"class":3808},[3416,25870,25871],{"class":3808}," transact-get-items",[3416,25873,6341],{"class":6340},[3416,25875,25876,25878],{"class":3418,"line":3641},[3416,25877,9724],{"class":4368},[3416,25879,9727],{"class":3808},[3416,25881,25882],{"class":3418,"line":3647},[3416,25883,25884],{"class":3808},"        {\"Get\": {\"TableName\": \"Orders\",    \"Key\": {\"CustomerId\": {\"S\": \"usr-001\"}, \"OrderId\": {\"S\": \"ord-2026-001\"}}}},\n",[3416,25886,25887],{"class":3418,"line":3653},[3416,25888,25889],{"class":3808},"        {\"Get\": {\"TableName\": \"Inventory\", \"Key\": {\"ProductId\": {\"S\": \"prod-42\"}}}}\n",[3416,25891,25892,25894],{"class":3418,"line":3659},[3416,25893,9816],{"class":3808},[3416,25895,6341],{"class":6340},[3416,25897,25898,25900],{"class":3418,"line":3665},[3416,25899,6366],{"class":4368},[3416,25901,6369],{"class":3808},[6311,25903,25904],{"label":6372},[3406,25905,25907],{"className":6375,"code":25906,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nvar ddbClient = new AmazonDynamoDBClient(Amazon.RegionEndpoint.EUCentral1);\n\n\u002F\u002F ── Транзакційний запис: Зняття залишків та створення замовлення ─────────────\nawait ddbClient.TransactWriteItemsAsync(new TransactWriteItemsRequest\n{\n    TransactItems = new List\u003CTransactWriteItem>\n    {\n        new()\n        {\n            ConditionCheck = new ConditionCheck\n            {\n                TableName = \"Inventory\",\n                Key = new Dictionary\u003Cstring, AttributeValue> { { \"ProductId\", new AttributeValue { S = \"prod-42\" } } },\n                ConditionExpression = \"quantity >= :qty\",\n                ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue> { { \":qty\", new AttributeValue { N = \"2\" } } }\n            }\n        },\n        new()\n        {\n            Update = new Update\n            {\n                TableName = \"Inventory\",\n                Key = new Dictionary\u003Cstring, AttributeValue> { { \"ProductId\", new AttributeValue { S = \"prod-42\" } } },\n                UpdateExpression = \"SET quantity = quantity - :qty\",\n                ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue> { { \":qty\", new AttributeValue { N = \"2\" } } }\n            }\n        },\n        new()\n        {\n            Put = new Put\n            {\n                TableName = \"Orders\",\n                Item = new Dictionary\u003Cstring, AttributeValue>\n                {\n                    { \"CustomerId\", new AttributeValue { S = \"usr-001\" } },\n                    { \"OrderId\", new AttributeValue { S = \"ord-2026-001\" } },\n                    { \"ProductId\", new AttributeValue { S = \"prod-42\" } },\n                    { \"Quantity\", new AttributeValue { N = \"2\" } },\n                    { \"Status\", new AttributeValue { S = \"PENDING\" } },\n                    { \"CreatedAt\", new AttributeValue { S = \"2026-06-03T12:00:00Z\" } }\n                },\n                ConditionExpression = \"attribute_not_exists(OrderId)\"\n            }\n        }\n    }\n});\n\n\u002F\u002F ── Транзакційне зчитування для забезпечення узгодженості даних ──────────────\nvar transactGetResult = await ddbClient.TransactGetItemsAsync(new TransactGetItemsRequest\n{\n    TransactItems = new List\u003CTransactGetItem>\n    {\n        new()\n        {\n            Get = new Get\n            {\n                TableName = \"Orders\",\n                Key = new Dictionary\u003Cstring, AttributeValue>\n                {\n                    { \"CustomerId\", new AttributeValue { S = \"usr-001\" } },\n                    { \"OrderId\", new AttributeValue { S = \"ord-2026-001\" } }\n                }\n            }\n        },\n        new()\n        {\n            Get = new Get\n            {\n                TableName = \"Inventory\",\n                Key = new Dictionary\u003Cstring, AttributeValue> { { \"ProductId\", new AttributeValue { S = \"prod-42\" } } }\n            }\n        }\n    }\n});\n",[3413,25908,25909,25921,25937,25941,25967,25971,25976,25992,25996,26012,26016,26022,26026,26038,26042,26053,26094,26106,26146,26150,26154,26160,26164,26174,26178,26188,26226,26237,26275,26279,26283,26289,26293,26303,26307,26317,26337,26341,26363,26386,26408,26431,26453,26476,26480,26489,26493,26497,26501,26505,26509,26514,26539,26543,26560,26564,26570,26574,26586,26590,26600,26620,26624,26646,26668,26672,26676,26680,26686,26690,26700,26704,26714,26752,26756,26760,26764],{"__ignoreMap":3411},[3416,25910,25911,25913,25915,25917,25919],{"class":3418,"line":3419},[3416,25912,17433],{"class":11427},[3416,25914,17436],{"class":6397},[3416,25916,4043],{"class":3795},[3416,25918,17441],{"class":6397},[3416,25920,11594],{"class":3795},[3416,25922,25923,25925,25927,25929,25931,25933,25935],{"class":3418,"line":3425},[3416,25924,17433],{"class":11427},[3416,25926,17436],{"class":6397},[3416,25928,4043],{"class":3795},[3416,25930,17441],{"class":6397},[3416,25932,4043],{"class":3795},[3416,25934,17458],{"class":6397},[3416,25936,11594],{"class":3795},[3416,25938,25939],{"class":3418,"line":3431},[3416,25940,3441],{"emptyLinePlaceholder":3440},[3416,25942,25943,25945,25947,25949,25951,25953,25955,25957,25959,25961,25963,25965],{"class":3418,"line":3437},[3416,25944,6384],{"class":4368},[3416,25946,22796],{"class":6387},[3416,25948,6391],{"class":3795},[3416,25950,6394],{"class":4368},[3416,25952,6398],{"class":6397},[3416,25954,6423],{"class":3795},[3416,25956,22807],{"class":6387},[3416,25958,4043],{"class":3795},[3416,25960,22812],{"class":6387},[3416,25962,4043],{"class":3795},[3416,25964,22817],{"class":6387},[3416,25966,11465],{"class":3795},[3416,25968,25969],{"class":3418,"line":3444},[3416,25970,3441],{"emptyLinePlaceholder":3440},[3416,25972,25973],{"class":3418,"line":3450},[3416,25974,25975],{"class":3789},"\u002F\u002F ── Транзакційний запис: Зняття залишків та створення замовлення ─────────────\n",[3416,25977,25978,25980,25982,25984,25986,25988,25990],{"class":3418,"line":3456},[3416,25979,6413],{"class":4368},[3416,25981,22796],{"class":6387},[3416,25983,4043],{"class":3795},[3416,25985,9848],{"class":6330},[3416,25987,6423],{"class":3795},[3416,25989,6394],{"class":4368},[3416,25991,9855],{"class":6397},[3416,25993,25994],{"class":3418,"line":3462},[3416,25995,3796],{"class":3795},[3416,25997,25998,26000,26002,26004,26006,26008,26010],{"class":3418,"line":3468},[3416,25999,9864],{"class":6387},[3416,26001,6391],{"class":3795},[3416,26003,6394],{"class":4368},[3416,26005,8640],{"class":6397},[3416,26007,5861],{"class":3795},[3416,26009,9875],{"class":6397},[3416,26011,6469],{"class":3795},[3416,26013,26014],{"class":3418,"line":3474},[3416,26015,6474],{"class":3795},[3416,26017,26018,26020],{"class":3418,"line":3480},[3416,26019,9886],{"class":4368},[3416,26021,17625],{"class":3795},[3416,26023,26024],{"class":3418,"line":3486},[3416,26025,8611],{"class":3795},[3416,26027,26028,26031,26033,26035],{"class":3418,"line":3492},[3416,26029,26030],{"class":6387},"            ConditionCheck",[3416,26032,6391],{"class":3795},[3416,26034,6394],{"class":4368},[3416,26036,26037],{"class":6397}," ConditionCheck\n",[3416,26039,26040],{"class":3418,"line":3498},[3416,26041,8628],{"class":3795},[3416,26043,26044,26046,26048,26051],{"class":3418,"line":3504},[3416,26045,9914],{"class":6387},[3416,26047,6391],{"class":3795},[3416,26049,26050],{"class":3808},"\"Inventory\"",[3416,26052,3812],{"class":3795},[3416,26054,26055,26057,26059,26061,26063,26065,26067,26069,26071,26073,26076,26078,26080,26082,26084,26086,26088,26091],{"class":3418,"line":3510},[3416,26056,10067],{"class":6387},[3416,26058,6391],{"class":3795},[3416,26060,6394],{"class":4368},[3416,26062,6456],{"class":6397},[3416,26064,5861],{"class":3795},[3416,26066,6461],{"class":4368},[3416,26068,4384],{"class":3795},[3416,26070,6466],{"class":6397},[3416,26072,20772],{"class":3795},[3416,26074,26075],{"class":3808},"\"ProductId\"",[3416,26077,4384],{"class":3795},[3416,26079,6394],{"class":4368},[3416,26081,6489],{"class":6397},[3416,26083,6492],{"class":3795},[3416,26085,6495],{"class":6387},[3416,26087,6391],{"class":3795},[3416,26089,26090],{"class":3808},"\"prod-42\"",[3416,26092,26093],{"class":3795}," } } },\n",[3416,26095,26096,26099,26101,26104],{"class":3418,"line":3515},[3416,26097,26098],{"class":6387},"                ConditionExpression",[3416,26100,6391],{"class":3795},[3416,26102,26103],{"class":3808},"\"quantity >= :qty\"",[3416,26105,3812],{"class":3795},[3416,26107,26108,26110,26112,26114,26116,26118,26120,26122,26124,26126,26129,26131,26133,26135,26137,26139,26141,26144],{"class":3418,"line":3521},[3416,26109,10130],{"class":6387},[3416,26111,6391],{"class":3795},[3416,26113,6394],{"class":4368},[3416,26115,6456],{"class":6397},[3416,26117,5861],{"class":3795},[3416,26119,6461],{"class":4368},[3416,26121,4384],{"class":3795},[3416,26123,6466],{"class":6397},[3416,26125,20772],{"class":3795},[3416,26127,26128],{"class":3808},"\":qty\"",[3416,26130,4384],{"class":3795},[3416,26132,6394],{"class":4368},[3416,26134,6489],{"class":6397},[3416,26136,6492],{"class":3795},[3416,26138,10168],{"class":6387},[3416,26140,6391],{"class":3795},[3416,26142,26143],{"class":3808},"\"2\"",[3416,26145,20823],{"class":3795},[3416,26147,26148],{"class":3418,"line":3527},[3416,26149,8815],{"class":3795},[3416,26151,26152],{"class":3418,"line":3533},[3416,26153,9774],{"class":3795},[3416,26155,26156,26158],{"class":3418,"line":3539},[3416,26157,9886],{"class":4368},[3416,26159,17625],{"class":3795},[3416,26161,26162],{"class":3418,"line":3545},[3416,26163,8611],{"class":3795},[3416,26165,26166,26168,26170,26172],{"class":3418,"line":3551},[3416,26167,10040],{"class":6387},[3416,26169,6391],{"class":3795},[3416,26171,6394],{"class":4368},[3416,26173,10047],{"class":6397},[3416,26175,26176],{"class":3418,"line":3557},[3416,26177,8628],{"class":3795},[3416,26179,26180,26182,26184,26186],{"class":3418,"line":3563},[3416,26181,9914],{"class":6387},[3416,26183,6391],{"class":3795},[3416,26185,26050],{"class":3808},[3416,26187,3812],{"class":3795},[3416,26189,26190,26192,26194,26196,26198,26200,26202,26204,26206,26208,26210,26212,26214,26216,26218,26220,26222,26224],{"class":3418,"line":3569},[3416,26191,10067],{"class":6387},[3416,26193,6391],{"class":3795},[3416,26195,6394],{"class":4368},[3416,26197,6456],{"class":6397},[3416,26199,5861],{"class":3795},[3416,26201,6461],{"class":4368},[3416,26203,4384],{"class":3795},[3416,26205,6466],{"class":6397},[3416,26207,20772],{"class":3795},[3416,26209,26075],{"class":3808},[3416,26211,4384],{"class":3795},[3416,26213,6394],{"class":4368},[3416,26215,6489],{"class":6397},[3416,26217,6492],{"class":3795},[3416,26219,6495],{"class":6387},[3416,26221,6391],{"class":3795},[3416,26223,26090],{"class":3808},[3416,26225,26093],{"class":3795},[3416,26227,26228,26230,26232,26235],{"class":3418,"line":3574},[3416,26229,10118],{"class":6387},[3416,26231,6391],{"class":3795},[3416,26233,26234],{"class":3808},"\"SET quantity = quantity - :qty\"",[3416,26236,3812],{"class":3795},[3416,26238,26239,26241,26243,26245,26247,26249,26251,26253,26255,26257,26259,26261,26263,26265,26267,26269,26271,26273],{"class":3418,"line":3579},[3416,26240,10130],{"class":6387},[3416,26242,6391],{"class":3795},[3416,26244,6394],{"class":4368},[3416,26246,6456],{"class":6397},[3416,26248,5861],{"class":3795},[3416,26250,6461],{"class":4368},[3416,26252,4384],{"class":3795},[3416,26254,6466],{"class":6397},[3416,26256,20772],{"class":3795},[3416,26258,26128],{"class":3808},[3416,26260,4384],{"class":3795},[3416,26262,6394],{"class":4368},[3416,26264,6489],{"class":6397},[3416,26266,6492],{"class":3795},[3416,26268,10168],{"class":6387},[3416,26270,6391],{"class":3795},[3416,26272,26143],{"class":3808},[3416,26274,20823],{"class":3795},[3416,26276,26277],{"class":3418,"line":3584},[3416,26278,8815],{"class":3795},[3416,26280,26281],{"class":3418,"line":3590},[3416,26282,9774],{"class":3795},[3416,26284,26285,26287],{"class":3418,"line":3596},[3416,26286,9886],{"class":4368},[3416,26288,17625],{"class":3795},[3416,26290,26291],{"class":3418,"line":3602},[3416,26292,8611],{"class":3795},[3416,26294,26295,26297,26299,26301],{"class":3418,"line":3608},[3416,26296,9898],{"class":6387},[3416,26298,6391],{"class":3795},[3416,26300,6394],{"class":4368},[3416,26302,9905],{"class":6397},[3416,26304,26305],{"class":3418,"line":3614},[3416,26306,8628],{"class":3795},[3416,26308,26309,26311,26313,26315],{"class":3418,"line":3620},[3416,26310,9914],{"class":6387},[3416,26312,6391],{"class":3795},[3416,26314,19785],{"class":3808},[3416,26316,3812],{"class":3795},[3416,26318,26319,26321,26323,26325,26327,26329,26331,26333,26335],{"class":3418,"line":3626},[3416,26320,9925],{"class":6387},[3416,26322,6391],{"class":3795},[3416,26324,6394],{"class":4368},[3416,26326,6456],{"class":6397},[3416,26328,5861],{"class":3795},[3416,26330,6461],{"class":4368},[3416,26332,4384],{"class":3795},[3416,26334,6466],{"class":6397},[3416,26336,6469],{"class":3795},[3416,26338,26339],{"class":3418,"line":3631},[3416,26340,8661],{"class":3795},[3416,26342,26343,26345,26347,26349,26351,26353,26355,26357,26359,26361],{"class":3418,"line":3636},[3416,26344,9950],{"class":3795},[3416,26346,19820],{"class":3808},[3416,26348,4384],{"class":3795},[3416,26350,6394],{"class":4368},[3416,26352,6489],{"class":6397},[3416,26354,6492],{"class":3795},[3416,26356,6495],{"class":6387},[3416,26358,6391],{"class":3795},[3416,26360,6500],{"class":3808},[3416,26362,6503],{"class":3795},[3416,26364,26365,26367,26369,26371,26373,26375,26377,26379,26381,26384],{"class":3418,"line":3641},[3416,26366,9950],{"class":3795},[3416,26368,20498],{"class":3808},[3416,26370,4384],{"class":3795},[3416,26372,6394],{"class":4368},[3416,26374,6489],{"class":6397},[3416,26376,6492],{"class":3795},[3416,26378,6495],{"class":6387},[3416,26380,6391],{"class":3795},[3416,26382,26383],{"class":3808},"\"ord-2026-001\"",[3416,26385,6503],{"class":3795},[3416,26387,26388,26390,26392,26394,26396,26398,26400,26402,26404,26406],{"class":3418,"line":3647},[3416,26389,9950],{"class":3795},[3416,26391,26075],{"class":3808},[3416,26393,4384],{"class":3795},[3416,26395,6394],{"class":4368},[3416,26397,6489],{"class":6397},[3416,26399,6492],{"class":3795},[3416,26401,6495],{"class":6387},[3416,26403,6391],{"class":3795},[3416,26405,26090],{"class":3808},[3416,26407,6503],{"class":3795},[3416,26409,26410,26412,26415,26417,26419,26421,26423,26425,26427,26429],{"class":3418,"line":3653},[3416,26411,9950],{"class":3795},[3416,26413,26414],{"class":3808},"\"Quantity\"",[3416,26416,4384],{"class":3795},[3416,26418,6394],{"class":4368},[3416,26420,6489],{"class":6397},[3416,26422,6492],{"class":3795},[3416,26424,10168],{"class":6387},[3416,26426,6391],{"class":3795},[3416,26428,26143],{"class":3808},[3416,26430,6503],{"class":3795},[3416,26432,26433,26435,26437,26439,26441,26443,26445,26447,26449,26451],{"class":3418,"line":3659},[3416,26434,9950],{"class":3795},[3416,26436,11860],{"class":3808},[3416,26438,4384],{"class":3795},[3416,26440,6394],{"class":4368},[3416,26442,6489],{"class":6397},[3416,26444,6492],{"class":3795},[3416,26446,6495],{"class":6387},[3416,26448,6391],{"class":3795},[3416,26450,20536],{"class":3808},[3416,26452,6503],{"class":3795},[3416,26454,26455,26457,26459,26461,26463,26465,26467,26469,26471,26474],{"class":3418,"line":3665},[3416,26456,9950],{"class":3795},[3416,26458,6815],{"class":3808},[3416,26460,4384],{"class":3795},[3416,26462,6394],{"class":4368},[3416,26464,6489],{"class":6397},[3416,26466,6492],{"class":3795},[3416,26468,6495],{"class":6387},[3416,26470,6391],{"class":3795},[3416,26472,26473],{"class":3808},"\"2026-06-03T12:00:00Z\"",[3416,26475,6528],{"class":3795},[3416,26477,26478],{"class":3418,"line":3671},[3416,26479,9344],{"class":3795},[3416,26481,26482,26484,26486],{"class":3418,"line":3677},[3416,26483,26098],{"class":6387},[3416,26485,6391],{"class":3795},[3416,26487,26488],{"class":3808},"\"attribute_not_exists(OrderId)\"\n",[3416,26490,26491],{"class":3418,"line":3683},[3416,26492,8815],{"class":3795},[3416,26494,26495],{"class":3418,"line":3688},[3416,26496,8533],{"class":3795},[3416,26498,26499],{"class":3418,"line":3693},[3416,26500,4167],{"class":3795},[3416,26502,26503],{"class":3418,"line":3698},[3416,26504,6537],{"class":3795},[3416,26506,26507],{"class":3418,"line":3704},[3416,26508,3441],{"emptyLinePlaceholder":3440},[3416,26510,26511],{"class":3418,"line":3710},[3416,26512,26513],{"class":3789},"\u002F\u002F ── Транзакційне зчитування для забезпечення узгодженості даних ──────────────\n",[3416,26515,26516,26518,26521,26523,26525,26527,26529,26532,26534,26536],{"class":3418,"line":3715},[3416,26517,6384],{"class":4368},[3416,26519,26520],{"class":6387}," transactGetResult",[3416,26522,6391],{"class":3795},[3416,26524,6413],{"class":4368},[3416,26526,22796],{"class":6387},[3416,26528,4043],{"class":3795},[3416,26530,26531],{"class":6330},"TransactGetItemsAsync",[3416,26533,6423],{"class":3795},[3416,26535,6394],{"class":4368},[3416,26537,26538],{"class":6397}," TransactGetItemsRequest\n",[3416,26540,26541],{"class":3418,"line":12799},[3416,26542,3796],{"class":3795},[3416,26544,26545,26547,26549,26551,26553,26555,26558],{"class":3418,"line":12822},[3416,26546,9864],{"class":6387},[3416,26548,6391],{"class":3795},[3416,26550,6394],{"class":4368},[3416,26552,8640],{"class":6397},[3416,26554,5861],{"class":3795},[3416,26556,26557],{"class":6397},"TransactGetItem",[3416,26559,6469],{"class":3795},[3416,26561,26562],{"class":3418,"line":12827},[3416,26563,6474],{"class":3795},[3416,26565,26566,26568],{"class":3418,"line":12832},[3416,26567,9886],{"class":4368},[3416,26569,17625],{"class":3795},[3416,26571,26572],{"class":3418,"line":12837},[3416,26573,8611],{"class":3795},[3416,26575,26576,26579,26581,26583],{"class":3418,"line":12843},[3416,26577,26578],{"class":6387},"            Get",[3416,26580,6391],{"class":3795},[3416,26582,6394],{"class":4368},[3416,26584,26585],{"class":6397}," Get\n",[3416,26587,26588],{"class":3418,"line":12860},[3416,26589,8628],{"class":3795},[3416,26591,26592,26594,26596,26598],{"class":3418,"line":12865},[3416,26593,9914],{"class":6387},[3416,26595,6391],{"class":3795},[3416,26597,19785],{"class":3808},[3416,26599,3812],{"class":3795},[3416,26601,26602,26604,26606,26608,26610,26612,26614,26616,26618],{"class":3418,"line":12876},[3416,26603,10067],{"class":6387},[3416,26605,6391],{"class":3795},[3416,26607,6394],{"class":4368},[3416,26609,6456],{"class":6397},[3416,26611,5861],{"class":3795},[3416,26613,6461],{"class":4368},[3416,26615,4384],{"class":3795},[3416,26617,6466],{"class":6397},[3416,26619,6469],{"class":3795},[3416,26621,26622],{"class":3418,"line":12897},[3416,26623,8661],{"class":3795},[3416,26625,26626,26628,26630,26632,26634,26636,26638,26640,26642,26644],{"class":3418,"line":12902},[3416,26627,9950],{"class":3795},[3416,26629,19820],{"class":3808},[3416,26631,4384],{"class":3795},[3416,26633,6394],{"class":4368},[3416,26635,6489],{"class":6397},[3416,26637,6492],{"class":3795},[3416,26639,6495],{"class":6387},[3416,26641,6391],{"class":3795},[3416,26643,6500],{"class":3808},[3416,26645,6503],{"class":3795},[3416,26647,26648,26650,26652,26654,26656,26658,26660,26662,26664,26666],{"class":3418,"line":12925},[3416,26649,9950],{"class":3795},[3416,26651,20498],{"class":3808},[3416,26653,4384],{"class":3795},[3416,26655,6394],{"class":4368},[3416,26657,6489],{"class":6397},[3416,26659,6492],{"class":3795},[3416,26661,6495],{"class":6387},[3416,26663,6391],{"class":3795},[3416,26665,26383],{"class":3808},[3416,26667,6528],{"class":3795},[3416,26669,26670],{"class":3418,"line":12948},[3416,26671,8810],{"class":3795},[3416,26673,26674],{"class":3418,"line":12953},[3416,26675,8815],{"class":3795},[3416,26677,26678],{"class":3418,"line":20609},[3416,26679,9774],{"class":3795},[3416,26681,26682,26684],{"class":3418,"line":20614},[3416,26683,9886],{"class":4368},[3416,26685,17625],{"class":3795},[3416,26687,26688],{"class":3418,"line":20619},[3416,26689,8611],{"class":3795},[3416,26691,26692,26694,26696,26698],{"class":3418,"line":20624},[3416,26693,26578],{"class":6387},[3416,26695,6391],{"class":3795},[3416,26697,6394],{"class":4368},[3416,26699,26585],{"class":6397},[3416,26701,26702],{"class":3418,"line":20630},[3416,26703,8628],{"class":3795},[3416,26705,26706,26708,26710,26712],{"class":3418,"line":20647},[3416,26707,9914],{"class":6387},[3416,26709,6391],{"class":3795},[3416,26711,26050],{"class":3808},[3416,26713,3812],{"class":3795},[3416,26715,26716,26718,26720,26722,26724,26726,26728,26730,26732,26734,26736,26738,26740,26742,26744,26746,26748,26750],{"class":3418,"line":20652},[3416,26717,10067],{"class":6387},[3416,26719,6391],{"class":3795},[3416,26721,6394],{"class":4368},[3416,26723,6456],{"class":6397},[3416,26725,5861],{"class":3795},[3416,26727,6461],{"class":4368},[3416,26729,4384],{"class":3795},[3416,26731,6466],{"class":6397},[3416,26733,20772],{"class":3795},[3416,26735,26075],{"class":3808},[3416,26737,4384],{"class":3795},[3416,26739,6394],{"class":4368},[3416,26741,6489],{"class":6397},[3416,26743,6492],{"class":3795},[3416,26745,6495],{"class":6387},[3416,26747,6391],{"class":3795},[3416,26749,26090],{"class":3808},[3416,26751,20823],{"class":3795},[3416,26753,26754],{"class":3418,"line":20663},[3416,26755,8815],{"class":3795},[3416,26757,26758],{"class":3418,"line":20684},[3416,26759,8533],{"class":3795},[3416,26761,26762],{"class":3418,"line":20689},[3416,26763,4167],{"class":3795},[3416,26765,26766],{"class":3418,"line":20712},[3416,26767,6537],{"class":3795},[6311,26769,26770],{"label":6540},[3406,26771,26773],{"className":6543,"code":26772,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n# ── Опис перевірки залишків товару на складі ─────────────────────────────\n$condCheck = [Amazon.DynamoDBv2.Model.ConditionCheck]@{\n    TableName           = 'Inventory'\n    Key                 = @{ ProductId = New-DDBEntry -S 'prod-42' }\n    ConditionExpression = 'quantity >= :qty'\n    ExpressionAttributeValues = @{ ':qty' = New-DDBEntry -N '2' }\n}\n\n# ── Опис операції оновлення складу (зменшення кількості) ─────────────────\n$updateInventory = [Amazon.DynamoDBv2.Model.Update]@{\n    TableName        = 'Inventory'\n    Key              = @{ ProductId = New-DDBEntry -S 'prod-42' }\n    UpdateExpression = 'SET quantity = quantity - :qty'\n    ExpressionAttributeValues = @{ ':qty' = New-DDBEntry -N '2' }\n}\n\n# ── Опис створення запису нового замовлення ──────────────────────────────\n$putOrder = [Amazon.DynamoDBv2.Model.Put]@{\n    TableName           = 'Orders'\n    ConditionExpression = 'attribute_not_exists(OrderId)'\n    Item                = @{\n        CustomerId = New-DDBEntry -S 'usr-001'\n        OrderId    = New-DDBEntry -S 'ord-2026-001'\n        ProductId  = New-DDBEntry -S 'prod-42'\n        Quantity   = New-DDBEntry -N '2'\n        Status     = New-DDBEntry -S 'PENDING'\n        CreatedAt  = New-DDBEntry -S '2026-06-03T12:00:00Z'\n    }\n}\n\n# ── Об'єднання в єдину транзакційну структуру та виклик API ─────────────────\n$txItems = @(\n    [Amazon.DynamoDBv2.Model.TransactWriteItem]@{ ConditionCheck = $condCheck },\n    [Amazon.DynamoDBv2.Model.TransactWriteItem]@{ Update         = $updateInventory },\n    [Amazon.DynamoDBv2.Model.TransactWriteItem]@{ Put            = $putOrder }\n)\nInvoke-DDBTransactWrite -TransactItems $txItems -Region eu-central-1\n\n# ── Отримання стану замовлення та складу через TransactGet ────────────────────\n$getOrder = [Amazon.DynamoDBv2.Model.Get]@{\n    TableName = 'Orders'\n    Key       = @{ CustomerId = New-DDBEntry -S 'usr-001'; OrderId = New-DDBEntry -S 'ord-2026-001' }\n}\n$getInventory = [Amazon.DynamoDBv2.Model.Get]@{\n    TableName = 'Inventory'\n    Key       = @{ ProductId = New-DDBEntry -S 'prod-42' }\n}\n$getItems = @(\n    [Amazon.DynamoDBv2.Model.TransactGetItem]@{ Get = $getOrder },\n    [Amazon.DynamoDBv2.Model.TransactGetItem]@{ Get = $getInventory }\n)\nInvoke-DDBTransactGet -TransactItems $getItems -Region eu-central-1\n",[3413,26774,26775,26781,26785,26790,26806,26816,26840,26850,26874,26878,26882,26887,26903,26911,26933,26942,26964,26968,26972,26977,26993,27001,27010,27021,27034,27048,27062,27076,27090,27104,27108,27112,27116,27121,27132,27152,27173,27194,27198,27212,27216,27221,27237,27245,27280,27284,27299,27307,27329,27333,27344,27366,27386,27390],{"__ignoreMap":3411},[3416,26776,26777,26779],{"class":3418,"line":3419},[3416,26778,12967],{"class":6330},[3416,26780,12970],{"class":3795},[3416,26782,26783],{"class":3418,"line":3425},[3416,26784,3441],{"emptyLinePlaceholder":3440},[3416,26786,26787],{"class":3418,"line":3431},[3416,26788,26789],{"class":3789},"# ── Опис перевірки залишків товару на складі ─────────────────────────────\n",[3416,26791,26792,26795,26797,26800,26802,26804],{"class":3418,"line":3437},[3416,26793,26794],{"class":6387},"$condCheck",[3416,26796,7274],{"class":3795},[3416,26798,26799],{"class":4368},"Amazon.DynamoDBv2.Model.ConditionCheck",[3416,26801,7280],{"class":3795},[3416,26803,6561],{"class":4368},[3416,26805,3796],{"class":3795},[3416,26807,26808,26810,26813],{"class":3418,"line":3444},[3416,26809,6437],{"class":6387},[3416,26811,26812],{"class":3795},"           = ",[3416,26814,26815],{"class":3808},"'Inventory'\n",[3416,26817,26818,26820,26822,26824,26826,26829,26831,26833,26835,26838],{"class":3418,"line":3450},[3416,26819,6449],{"class":6387},[3416,26821,13181],{"class":3795},[3416,26823,6561],{"class":4368},[3416,26825,8886],{"class":3795},[3416,26827,26828],{"class":6387},"ProductId",[3416,26830,6391],{"class":3795},[3416,26832,6574],{"class":6330},[3416,26834,6577],{"class":3795},[3416,26836,26837],{"class":3808},"'prod-42'",[3416,26839,8948],{"class":3795},[3416,26841,26842,26845,26847],{"class":3418,"line":3456},[3416,26843,26844],{"class":6387},"    ConditionExpression",[3416,26846,6391],{"class":3795},[3416,26848,26849],{"class":3808},"'quantity >= :qty'\n",[3416,26851,26852,26854,26856,26858,26860,26863,26865,26867,26869,26872],{"class":3418,"line":3462},[3416,26853,7179],{"class":6387},[3416,26855,6391],{"class":3795},[3416,26857,6561],{"class":4368},[3416,26859,8886],{"class":3795},[3416,26861,26862],{"class":3808},"':qty'",[3416,26864,6391],{"class":3795},[3416,26866,6574],{"class":6330},[3416,26868,10395],{"class":3795},[3416,26870,26871],{"class":3808},"'2'",[3416,26873,8948],{"class":3795},[3416,26875,26876],{"class":3418,"line":3468},[3416,26877,3507],{"class":3795},[3416,26879,26880],{"class":3418,"line":3474},[3416,26881,3441],{"emptyLinePlaceholder":3440},[3416,26883,26884],{"class":3418,"line":3480},[3416,26885,26886],{"class":3789},"# ── Опис операції оновлення складу (зменшення кількості) ─────────────────\n",[3416,26888,26889,26892,26894,26897,26899,26901],{"class":3418,"line":3486},[3416,26890,26891],{"class":6387},"$updateInventory",[3416,26893,7274],{"class":3795},[3416,26895,26896],{"class":4368},"Amazon.DynamoDBv2.Model.Update",[3416,26898,7280],{"class":3795},[3416,26900,6561],{"class":4368},[3416,26902,3796],{"class":3795},[3416,26904,26905,26907,26909],{"class":3418,"line":3492},[3416,26906,6437],{"class":6387},[3416,26908,7923],{"class":3795},[3416,26910,26815],{"class":3808},[3416,26912,26913,26915,26917,26919,26921,26923,26925,26927,26929,26931],{"class":3418,"line":3498},[3416,26914,6449],{"class":6387},[3416,26916,13271],{"class":3795},[3416,26918,6561],{"class":4368},[3416,26920,8886],{"class":3795},[3416,26922,26828],{"class":6387},[3416,26924,6391],{"class":3795},[3416,26926,6574],{"class":6330},[3416,26928,6577],{"class":3795},[3416,26930,26837],{"class":3808},[3416,26932,8948],{"class":3795},[3416,26934,26935,26937,26939],{"class":3418,"line":3504},[3416,26936,7167],{"class":6387},[3416,26938,6391],{"class":3795},[3416,26940,26941],{"class":3808},"'SET quantity = quantity - :qty'\n",[3416,26943,26944,26946,26948,26950,26952,26954,26956,26958,26960,26962],{"class":3418,"line":3510},[3416,26945,7179],{"class":6387},[3416,26947,6391],{"class":3795},[3416,26949,6561],{"class":4368},[3416,26951,8886],{"class":3795},[3416,26953,26862],{"class":3808},[3416,26955,6391],{"class":3795},[3416,26957,6574],{"class":6330},[3416,26959,10395],{"class":3795},[3416,26961,26871],{"class":3808},[3416,26963,8948],{"class":3795},[3416,26965,26966],{"class":3418,"line":3515},[3416,26967,3507],{"class":3795},[3416,26969,26970],{"class":3418,"line":3521},[3416,26971,3441],{"emptyLinePlaceholder":3440},[3416,26973,26974],{"class":3418,"line":3527},[3416,26975,26976],{"class":3789},"# ── Опис створення запису нового замовлення ──────────────────────────────\n",[3416,26978,26979,26982,26984,26987,26989,26991],{"class":3418,"line":3533},[3416,26980,26981],{"class":6387},"$putOrder",[3416,26983,7274],{"class":3795},[3416,26985,26986],{"class":4368},"Amazon.DynamoDBv2.Model.Put",[3416,26988,7280],{"class":3795},[3416,26990,6561],{"class":4368},[3416,26992,3796],{"class":3795},[3416,26994,26995,26997,26999],{"class":3418,"line":3539},[3416,26996,6437],{"class":6387},[3416,26998,26812],{"class":3795},[3416,27000,21270],{"class":3808},[3416,27002,27003,27005,27007],{"class":3418,"line":3545},[3416,27004,26844],{"class":6387},[3416,27006,6391],{"class":3795},[3416,27008,27009],{"class":3808},"'attribute_not_exists(OrderId)'\n",[3416,27011,27012,27014,27017,27019],{"class":3418,"line":3551},[3416,27013,6744],{"class":6387},[3416,27015,27016],{"class":3795},"                = ",[3416,27018,6561],{"class":4368},[3416,27020,3796],{"class":3795},[3416,27022,27023,27026,27028,27030,27032],{"class":3418,"line":3557},[3416,27024,27025],{"class":6387},"        CustomerId",[3416,27027,6391],{"class":3795},[3416,27029,6574],{"class":6330},[3416,27031,6577],{"class":3795},[3416,27033,6580],{"class":3808},[3416,27035,27036,27039,27041,27043,27045],{"class":3418,"line":3563},[3416,27037,27038],{"class":6387},"        OrderId",[3416,27040,6571],{"class":3795},[3416,27042,6574],{"class":6330},[3416,27044,6577],{"class":3795},[3416,27046,27047],{"class":3808},"'ord-2026-001'\n",[3416,27049,27050,27053,27055,27057,27059],{"class":3418,"line":3569},[3416,27051,27052],{"class":6387},"        ProductId",[3416,27054,6933],{"class":3795},[3416,27056,6574],{"class":6330},[3416,27058,6577],{"class":3795},[3416,27060,27061],{"class":3808},"'prod-42'\n",[3416,27063,27064,27067,27069,27071,27073],{"class":3418,"line":3574},[3416,27065,27066],{"class":6387},"        Quantity",[3416,27068,7374],{"class":3795},[3416,27070,6574],{"class":6330},[3416,27072,10395],{"class":3795},[3416,27074,27075],{"class":3808},"'2'\n",[3416,27077,27078,27081,27084,27086,27088],{"class":3418,"line":3579},[3416,27079,27080],{"class":6387},"        Status",[3416,27082,27083],{"class":3795},"     = ",[3416,27085,6574],{"class":6330},[3416,27087,6577],{"class":3795},[3416,27089,21065],{"class":3808},[3416,27091,27092,27095,27097,27099,27101],{"class":3418,"line":3584},[3416,27093,27094],{"class":6387},"        CreatedAt",[3416,27096,6933],{"class":3795},[3416,27098,6574],{"class":6330},[3416,27100,6577],{"class":3795},[3416,27102,27103],{"class":3808},"'2026-06-03T12:00:00Z'\n",[3416,27105,27106],{"class":3418,"line":3590},[3416,27107,4167],{"class":3795},[3416,27109,27110],{"class":3418,"line":3596},[3416,27111,3507],{"class":3795},[3416,27113,27114],{"class":3418,"line":3602},[3416,27115,3441],{"emptyLinePlaceholder":3440},[3416,27117,27118],{"class":3418,"line":3608},[3416,27119,27120],{"class":3789},"# ── Об'єднання в єдину транзакційну структуру та виклик API ─────────────────\n",[3416,27122,27123,27126,27128,27130],{"class":3418,"line":3614},[3416,27124,27125],{"class":6387},"$txItems",[3416,27127,6391],{"class":3795},[3416,27129,6561],{"class":4368},[3416,27131,8878],{"class":3795},[3416,27133,27134,27136,27138,27140,27142,27144,27146,27148,27150],{"class":3418,"line":3620},[3416,27135,9496],{"class":3795},[3416,27137,10225],{"class":4368},[3416,27139,7280],{"class":3795},[3416,27141,6561],{"class":4368},[3416,27143,8886],{"class":3795},[3416,27145,25484],{"class":6387},[3416,27147,6391],{"class":3795},[3416,27149,26794],{"class":6387},[3416,27151,8915],{"class":3795},[3416,27153,27154,27156,27158,27160,27162,27164,27166,27169,27171],{"class":3418,"line":3626},[3416,27155,9496],{"class":3795},[3416,27157,10225],{"class":4368},[3416,27159,7280],{"class":3795},[3416,27161,6561],{"class":4368},[3416,27163,8886],{"class":3795},[3416,27165,25472],{"class":6387},[3416,27167,27168],{"class":3795},"         = ",[3416,27170,26891],{"class":6387},[3416,27172,8915],{"class":3795},[3416,27174,27175,27177,27179,27181,27183,27185,27187,27190,27192],{"class":3418,"line":3631},[3416,27176,9496],{"class":3795},[3416,27178,10225],{"class":4368},[3416,27180,7280],{"class":3795},[3416,27182,6561],{"class":4368},[3416,27184,8886],{"class":3795},[3416,27186,25466],{"class":6387},[3416,27188,27189],{"class":3795},"            = ",[3416,27191,26981],{"class":6387},[3416,27193,8948],{"class":3795},[3416,27195,27196],{"class":3418,"line":3636},[3416,27197,9656],{"class":3795},[3416,27199,27200,27203,27206,27208,27210],{"class":3418,"line":3641},[3416,27201,27202],{"class":6330},"Invoke-DDBTransactWrite",[3416,27204,27205],{"class":3795}," -TransactItems ",[3416,27207,27125],{"class":6387},[3416,27209,6611],{"class":3795},[3416,27211,6614],{"class":3870},[3416,27213,27214],{"class":3418,"line":3647},[3416,27215,3441],{"emptyLinePlaceholder":3440},[3416,27217,27218],{"class":3418,"line":3653},[3416,27219,27220],{"class":3789},"# ── Отримання стану замовлення та складу через TransactGet ────────────────────\n",[3416,27222,27223,27226,27228,27231,27233,27235],{"class":3418,"line":3659},[3416,27224,27225],{"class":6387},"$getOrder",[3416,27227,7274],{"class":3795},[3416,27229,27230],{"class":4368},"Amazon.DynamoDBv2.Model.Get",[3416,27232,7280],{"class":3795},[3416,27234,6561],{"class":4368},[3416,27236,3796],{"class":3795},[3416,27238,27239,27241,27243],{"class":3418,"line":3665},[3416,27240,6437],{"class":6387},[3416,27242,6391],{"class":3795},[3416,27244,21270],{"class":3808},[3416,27246,27247,27249,27251,27253,27255,27257,27259,27261,27263,27265,27267,27269,27271,27273,27275,27278],{"class":3418,"line":3671},[3416,27248,6449],{"class":6387},[3416,27250,21045],{"class":3795},[3416,27252,6561],{"class":4368},[3416,27254,8886],{"class":3795},[3416,27256,19086],{"class":6387},[3416,27258,6391],{"class":3795},[3416,27260,6574],{"class":6330},[3416,27262,6577],{"class":3795},[3416,27264,8897],{"class":3808},[3416,27266,8900],{"class":3795},[3416,27268,5123],{"class":6387},[3416,27270,6391],{"class":3795},[3416,27272,6574],{"class":6330},[3416,27274,6577],{"class":3795},[3416,27276,27277],{"class":3808},"'ord-2026-001'",[3416,27279,8948],{"class":3795},[3416,27281,27282],{"class":3418,"line":3677},[3416,27283,3507],{"class":3795},[3416,27285,27286,27289,27291,27293,27295,27297],{"class":3418,"line":3683},[3416,27287,27288],{"class":6387},"$getInventory",[3416,27290,7274],{"class":3795},[3416,27292,27230],{"class":4368},[3416,27294,7280],{"class":3795},[3416,27296,6561],{"class":4368},[3416,27298,3796],{"class":3795},[3416,27300,27301,27303,27305],{"class":3418,"line":3688},[3416,27302,6437],{"class":6387},[3416,27304,6391],{"class":3795},[3416,27306,26815],{"class":3808},[3416,27308,27309,27311,27313,27315,27317,27319,27321,27323,27325,27327],{"class":3418,"line":3693},[3416,27310,6449],{"class":6387},[3416,27312,21045],{"class":3795},[3416,27314,6561],{"class":4368},[3416,27316,8886],{"class":3795},[3416,27318,26828],{"class":6387},[3416,27320,6391],{"class":3795},[3416,27322,6574],{"class":6330},[3416,27324,6577],{"class":3795},[3416,27326,26837],{"class":3808},[3416,27328,8948],{"class":3795},[3416,27330,27331],{"class":3418,"line":3698},[3416,27332,3507],{"class":3795},[3416,27334,27335,27338,27340,27342],{"class":3418,"line":3704},[3416,27336,27337],{"class":6387},"$getItems",[3416,27339,6391],{"class":3795},[3416,27341,6561],{"class":4368},[3416,27343,8878],{"class":3795},[3416,27345,27346,27348,27351,27353,27355,27357,27360,27362,27364],{"class":3418,"line":3710},[3416,27347,9496],{"class":3795},[3416,27349,27350],{"class":4368},"Amazon.DynamoDBv2.Model.TransactGetItem",[3416,27352,7280],{"class":3795},[3416,27354,6561],{"class":4368},[3416,27356,8886],{"class":3795},[3416,27358,27359],{"class":6387},"Get",[3416,27361,6391],{"class":3795},[3416,27363,27225],{"class":6387},[3416,27365,8915],{"class":3795},[3416,27367,27368,27370,27372,27374,27376,27378,27380,27382,27384],{"class":3418,"line":3715},[3416,27369,9496],{"class":3795},[3416,27371,27350],{"class":4368},[3416,27373,7280],{"class":3795},[3416,27375,6561],{"class":4368},[3416,27377,8886],{"class":3795},[3416,27379,27359],{"class":6387},[3416,27381,6391],{"class":3795},[3416,27383,27288],{"class":6387},[3416,27385,8948],{"class":3795},[3416,27387,27388],{"class":3418,"line":12799},[3416,27389,9656],{"class":3795},[3416,27391,27392,27395,27397,27399,27401],{"class":3418,"line":12822},[3416,27393,27394],{"class":6330},"Invoke-DDBTransactGet",[3416,27396,27205],{"class":3795},[3416,27398,27337],{"class":6387},[3416,27400,6611],{"class":3795},[3416,27402,6614],{"class":3870},[3348,27404,27406],{"id":27405},"частина-5-ttl-global-tables-та-best-practices","Частина 5: TTL, Global Tables та Best Practices",[3727,27408,27410],{"id":27409},"time-to-live-ttl-автоматичне-очищення-застарілих-даних","Time to Live (TTL) — автоматичне очищення застарілих даних",[3353,27412,27413,27416,27417,27419],{},[3363,27414,27415],{},"Time to Live (TTL)"," — це вбудований безкоштовний механізм автоматичного видалення застарілих елементів з таблиці DynamoDB. Для роботи TTL розробник визначає спеціальний атрибут таблиці (наприклад, ",[3413,27418,14370],{},"), що зберігає часову мітку Unix Timestamp у секундах. Фоновий сервіс DynamoDB постійно сканує таблиці та асинхронно видаляє елементи, у яких термін придатності минув.",[4584,27421,27423],{"id":27422},"особливості-функціонування-та-архітектурний-вплив","Особливості функціонування та архітектурний вплив:",[3374,27425,27426,27436,27457],{},[3377,27427,27428,27431,27432,27435],{},[3363,27429,27430],{},"Економічність:"," Процес видалення елементів за допомогою TTL є абсолютно безкоштовним — він ",[3363,27433,27434],{},"не споживає WCU"," (Write Capacity Units) основної таблиці, що дозволяє суттєво економити бюджет на операціях очищення.",[3377,27437,27438,27441,27442,27445,27446],{},[3363,27439,27440],{},"Тимчасовий лаг видалення:"," Видалення за допомогою TTL відбувається асинхронно. AWS гарантує очищення елемента ",[3363,27443,27444],{},"протягом 48 годин"," після настання вказаного часу. У цей проміжок часу прострочений елемент все ще може відображатися в таблиці.",[22319,27447,27448],{},[3353,27449,27450,27453,27454],{},[3416,27451,27452],{},"!IMPORTANT","\nОскільки видалення не є миттєвим, клієнтський додаток повинен самостійно фільтрувати expired елементи в бізнес-сценаріях. Завжди додавайте у вирази фільтрації (FilterExpression) або бізнес-логіку умову:\n",[3413,27455,27456],{},"ExpiresAt > :currentTimestamp",[3377,27458,27459,27462,27463,27466,27467,5167,27470,4043],{},[3363,27460,27461],{},"Інтеграція з DynamoDB Streams:"," Коли TTL видаляє елемент, ця подія реєструється в потоці змін Streams як подія ",[3413,27464,27465],{},"REMOVE",". Для ідентифікації того, що запис видалено саме сервісом TTL, а не користувачем, метадані події в Streams містять прапорець ",[3413,27468,27469],{},"userIdentity.type = 'Service'",[3413,27471,27472],{},"userIdentity.principalId = 'dynamodb.amazonaws.com'",[3403,27474,27475],{},[3406,27476,27478],{"className":3408,"code":27477,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Схема роботи фонового процесу TTL\n\nrectangle \"Таблиця UserSessions\" as table #E8F4FD {\n  rectangle \"UserId: usr-001\\nExpiresAt: 1748000000\\n(Минулий час)\" as exp #F8CECC\n  rectangle \"UserId: usr-002\\nExpiresAt: 1890000000\\n(Майбутній час)\" as act #D5E8D4\n}\n\nrectangle \"TTL Background Process\\n(Фоновий очищувач AWS)\" as worker #FFF2CC\nrectangle \"DynamoDB Streams\" as streams #F0E6FF\n\nworker -> exp : \"1. Виявлено expired запис\\n(ExpiresAt \u003C поточний час)\"\nworker -> table : \"2. Видалення об'єкта (без витрат WCU)\"\ntable -> streams : \"3. Подія REMOVE\\n(type: 'Service')\"\n\nnote right of worker\n  * Латентність видалення: до 48 годин\n  * Додаток має фільтрувати expired дані\nend note\n@enduml\n",[3413,27479,27480,27484,27488,27492,27496,27500,27505,27509,27514,27519,27524,27528,27532,27537,27542,27546,27551,27556,27561,27565,27570,27575,27580,27584],{"__ignoreMap":3411},[3416,27481,27482],{"class":3418,"line":3419},[3416,27483,3422],{},[3416,27485,27486],{"class":3418,"line":3425},[3416,27487,16755],{},[3416,27489,27490],{"class":3418,"line":3431},[3416,27491,16760],{},[3416,27493,27494],{"class":3418,"line":3437},[3416,27495,16765],{},[3416,27497,27498],{"class":3418,"line":3444},[3416,27499,3441],{"emptyLinePlaceholder":3440},[3416,27501,27502],{"class":3418,"line":3450},[3416,27503,27504],{},"title Схема роботи фонового процесу TTL\n",[3416,27506,27507],{"class":3418,"line":3456},[3416,27508,3441],{"emptyLinePlaceholder":3440},[3416,27510,27511],{"class":3418,"line":3462},[3416,27512,27513],{},"rectangle \"Таблиця UserSessions\" as table #E8F4FD {\n",[3416,27515,27516],{"class":3418,"line":3468},[3416,27517,27518],{},"  rectangle \"UserId: usr-001\\nExpiresAt: 1748000000\\n(Минулий час)\" as exp #F8CECC\n",[3416,27520,27521],{"class":3418,"line":3474},[3416,27522,27523],{},"  rectangle \"UserId: usr-002\\nExpiresAt: 1890000000\\n(Майбутній час)\" as act #D5E8D4\n",[3416,27525,27526],{"class":3418,"line":3480},[3416,27527,3507],{},[3416,27529,27530],{"class":3418,"line":3486},[3416,27531,3441],{"emptyLinePlaceholder":3440},[3416,27533,27534],{"class":3418,"line":3492},[3416,27535,27536],{},"rectangle \"TTL Background Process\\n(Фоновий очищувач AWS)\" as worker #FFF2CC\n",[3416,27538,27539],{"class":3418,"line":3498},[3416,27540,27541],{},"rectangle \"DynamoDB Streams\" as streams #F0E6FF\n",[3416,27543,27544],{"class":3418,"line":3504},[3416,27545,3441],{"emptyLinePlaceholder":3440},[3416,27547,27548],{"class":3418,"line":3510},[3416,27549,27550],{},"worker -> exp : \"1. Виявлено expired запис\\n(ExpiresAt \u003C поточний час)\"\n",[3416,27552,27553],{"class":3418,"line":3515},[3416,27554,27555],{},"worker -> table : \"2. Видалення об'єкта (без витрат WCU)\"\n",[3416,27557,27558],{"class":3418,"line":3521},[3416,27559,27560],{},"table -> streams : \"3. Подія REMOVE\\n(type: 'Service')\"\n",[3416,27562,27563],{"class":3418,"line":3527},[3416,27564,3441],{"emptyLinePlaceholder":3440},[3416,27566,27567],{"class":3418,"line":3533},[3416,27568,27569],{},"note right of worker\n",[3416,27571,27572],{"class":3418,"line":3539},[3416,27573,27574],{},"  * Латентність видалення: до 48 годин\n",[3416,27576,27577],{"class":3418,"line":3545},[3416,27578,27579],{},"  * Додаток має фільтрувати expired дані\n",[3416,27581,27582],{"class":3418,"line":3551},[3416,27583,5088],{},[3416,27585,27586],{"class":3418,"line":3557},[3416,27587,3718],{},[4584,27589,27591],{"id":27590},"практичне-налаштування-та-робота-з-ttl","Практичне налаштування та робота з TTL",[6308,27593,27594,27873,28437],{},[6311,27595,27596],{"label":6313},[3406,27597,27599],{"className":6316,"code":27598,"language":6318,"meta":3411,"style":3411},"# ── Активація TTL на таблиці UserSessions за атрибутом ExpiresAt ─────────────\naws dynamodb update-time-to-live \\\n    --table-name UserSessions \\\n    --time-to-live-specification Enabled=true,AttributeName=ExpiresAt \\\n    --region eu-central-1\n\n# ── Запис сесії користувача з терміном дії 8 годин від поточного часу ──────────\nEXPIRES=$(date -d \"+8 hours\" +%s 2>\u002Fdev\u002Fnull || date -v+8H +%s)\naws dynamodb put-item \\\n    --table-name UserSessions \\\n    --item '{\n        \"UserId\":    {\"S\": \"usr-001\"},\n        \"SessionId\": {\"S\": \"sess-new-001\"},\n        \"CreatedAt\": {\"S\": \"2026-06-03T12:00:00Z\"},\n        \"ExpiresAt\": {\"N\": \"'\"$EXPIRES\"'\"},\n        \"IsActive\":  {\"BOOL\": true}\n    }' \\\n    --region eu-central-1\n\n# ── Перевірка конфігурації TTL таблиці ──────────────────────────────────────\naws dynamodb describe-time-to-live \\\n    --table-name UserSessions \\\n    --region eu-central-1\n\n# ── Сканування таблиці з виключенням застарілих елементів ─────────────────────\naws dynamodb scan \\\n    --table-name UserSessions \\\n    --filter-expression \"ExpiresAt > :now\" \\\n    --expression-attribute-values \"{\\\":now\\\": {\\\"N\\\": \\\"$(date +%s)\\\"}}\" \\\n    --region eu-central-1\n",[3413,27600,27601,27606,27617,27625,27640,27646,27650,27655,27692,27702,27710,27716,27720,27725,27730,27741,27745,27751,27757,27761,27766,27777,27785,27791,27795,27800,27810,27818,27827,27867],{"__ignoreMap":3411},[3416,27602,27603],{"class":3418,"line":3419},[3416,27604,27605],{"class":3789},"# ── Активація TTL на таблиці UserSessions за атрибутом ExpiresAt ─────────────\n",[3416,27607,27608,27610,27612,27615],{"class":3418,"line":3425},[3416,27609,6331],{"class":6330},[3416,27611,6334],{"class":3808},[3416,27613,27614],{"class":3808}," update-time-to-live",[3416,27616,6341],{"class":6340},[3416,27618,27619,27621,27623],{"class":3418,"line":3431},[3416,27620,6346],{"class":4368},[3416,27622,6349],{"class":3808},[3416,27624,6341],{"class":6340},[3416,27626,27627,27630,27633,27635,27638],{"class":3418,"line":3437},[3416,27628,27629],{"class":4368},"    --time-to-live-specification",[3416,27631,27632],{"class":3808}," Enabled=",[3416,27634,4038],{"class":4368},[3416,27636,27637],{"class":3808},",AttributeName=ExpiresAt",[3416,27639,6341],{"class":6340},[3416,27641,27642,27644],{"class":3418,"line":3444},[3416,27643,6366],{"class":4368},[3416,27645,6369],{"class":3808},[3416,27647,27648],{"class":3418,"line":3450},[3416,27649,3441],{"emptyLinePlaceholder":3440},[3416,27651,27652],{"class":3418,"line":3456},[3416,27653,27654],{"class":3789},"# ── Запис сесії користувача з терміном дії 8 годин від поточного часу ──────────\n",[3416,27656,27657,27660,27662,27665,27668,27671,27674,27677,27680,27683,27685,27688,27690],{"class":3418,"line":3462},[3416,27658,27659],{"class":6387},"EXPIRES",[3416,27661,24469],{"class":3795},[3416,27663,27664],{"class":6330},"date",[3416,27666,27667],{"class":4368}," -d",[3416,27669,27670],{"class":3808}," \"+8 hours\"",[3416,27672,27673],{"class":3808}," +%s",[3416,27675,27676],{"class":3795}," 2>",[3416,27678,27679],{"class":3808},"\u002Fdev\u002Fnull",[3416,27681,27682],{"class":3795}," || ",[3416,27684,27664],{"class":6330},[3416,27686,27687],{"class":4368}," -v+8H",[3416,27689,27673],{"class":3808},[3416,27691,9656],{"class":3795},[3416,27693,27694,27696,27698,27700],{"class":3418,"line":3468},[3416,27695,6331],{"class":6330},[3416,27697,6334],{"class":3808},[3416,27699,6643],{"class":3808},[3416,27701,6341],{"class":6340},[3416,27703,27704,27706,27708],{"class":3418,"line":3474},[3416,27705,6346],{"class":4368},[3416,27707,6349],{"class":3808},[3416,27709,6341],{"class":6340},[3416,27711,27712,27714],{"class":3418,"line":3480},[3416,27713,6658],{"class":4368},[3416,27715,6661],{"class":3808},[3416,27717,27718],{"class":3418,"line":3486},[3416,27719,6666],{"class":3808},[3416,27721,27722],{"class":3418,"line":3492},[3416,27723,27724],{"class":3808},"        \"SessionId\": {\"S\": \"sess-new-001\"},\n",[3416,27726,27727],{"class":3418,"line":3498},[3416,27728,27729],{"class":3808},"        \"CreatedAt\": {\"S\": \"2026-06-03T12:00:00Z\"},\n",[3416,27731,27732,27735,27738],{"class":3418,"line":3504},[3416,27733,27734],{"class":3808},"        \"ExpiresAt\": {\"N\": \"'\"",[3416,27736,27737],{"class":6387},"$EXPIRES",[3416,27739,27740],{"class":3808},"\"'\"},\n",[3416,27742,27743],{"class":3418,"line":3510},[3416,27744,6681],{"class":3808},[3416,27746,27747,27749],{"class":3418,"line":3515},[3416,27748,6686],{"class":3808},[3416,27750,6341],{"class":6340},[3416,27752,27753,27755],{"class":3418,"line":3521},[3416,27754,6366],{"class":4368},[3416,27756,6369],{"class":3808},[3416,27758,27759],{"class":3418,"line":3527},[3416,27760,3441],{"emptyLinePlaceholder":3440},[3416,27762,27763],{"class":3418,"line":3533},[3416,27764,27765],{"class":3789},"# ── Перевірка конфігурації TTL таблиці ──────────────────────────────────────\n",[3416,27767,27768,27770,27772,27775],{"class":3418,"line":3539},[3416,27769,6331],{"class":6330},[3416,27771,6334],{"class":3808},[3416,27773,27774],{"class":3808}," describe-time-to-live",[3416,27776,6341],{"class":6340},[3416,27778,27779,27781,27783],{"class":3418,"line":3545},[3416,27780,6346],{"class":4368},[3416,27782,6349],{"class":3808},[3416,27784,6341],{"class":6340},[3416,27786,27787,27789],{"class":3418,"line":3551},[3416,27788,6366],{"class":4368},[3416,27790,6369],{"class":3808},[3416,27792,27793],{"class":3418,"line":3557},[3416,27794,3441],{"emptyLinePlaceholder":3440},[3416,27796,27797],{"class":3418,"line":3563},[3416,27798,27799],{"class":3789},"# ── Сканування таблиці з виключенням застарілих елементів ─────────────────────\n",[3416,27801,27802,27804,27806,27808],{"class":3418,"line":3569},[3416,27803,6331],{"class":6330},[3416,27805,6334],{"class":3808},[3416,27807,7997],{"class":3808},[3416,27809,6341],{"class":6340},[3416,27811,27812,27814,27816],{"class":3418,"line":3574},[3416,27813,6346],{"class":4368},[3416,27815,6349],{"class":3808},[3416,27817,6341],{"class":6340},[3416,27819,27820,27822,27825],{"class":3418,"line":3579},[3416,27821,8012],{"class":4368},[3416,27823,27824],{"class":3808}," \"ExpiresAt > :now\"",[3416,27826,6341],{"class":6340},[3416,27828,27829,27831,27834,27836,27839,27841,27843,27845,27847,27849,27851,27853,27855,27857,27860,27862,27865],{"class":3418,"line":3584},[3416,27830,7021],{"class":4368},[3416,27832,27833],{"class":3808}," \"{",[3416,27835,25075],{"class":6340},[3416,27837,27838],{"class":3808},":now",[3416,27840,25075],{"class":6340},[3416,27842,11187],{"class":3808},[3416,27844,25075],{"class":6340},[3416,27846,10168],{"class":3808},[3416,27848,25075],{"class":6340},[3416,27850,3805],{"class":3808},[3416,27852,25075],{"class":6340},[3416,27854,11712],{"class":3808},[3416,27856,27664],{"class":6330},[3416,27858,27859],{"class":3808}," +%s)",[3416,27861,25075],{"class":6340},[3416,27863,27864],{"class":3808},"}}\"",[3416,27866,6341],{"class":6340},[3416,27868,27869,27871],{"class":3418,"line":3590},[3416,27870,6366],{"class":4368},[3416,27872,6369],{"class":3808},[6311,27874,27875],{"label":6372},[3406,27876,27878],{"className":6375,"code":27877,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nvar ddbClient = new AmazonDynamoDBClient(Amazon.RegionEndpoint.EUCentral1);\n\n\u002F\u002F ── Активація TTL на таблиці UserSessions за атрибутом ExpiresAt ─────────────\nawait ddbClient.UpdateTimeToLiveAsync(new UpdateTimeToLiveRequest\n{\n    TableName = \"UserSessions\",\n    TimeToLiveSpecification = new TimeToLiveSpecification\n    {\n        Enabled = true,\n        AttributeName = \"ExpiresAt\"\n    }\n});\n\n\u002F\u002F ── Запис елемента з часом життя 8 годин ──────────────────────────────────\nlong expiresAt = DateTimeOffset.UtcNow.AddHours(8).ToUnixTimeSeconds();\nawait ddbClient.PutItemAsync(new PutItemRequest\n{\n    TableName = \"UserSessions\",\n    Item = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \"UserId\", new AttributeValue { S = \"usr-001\" } },\n        { \"SessionId\", new AttributeValue { S = \"sess-new-001\" } },\n        { \"CreatedAt\", new AttributeValue { S = \"2026-06-03T12:00:00Z\" } },\n        { \"ExpiresAt\", new AttributeValue { N = expiresAt.ToString() } },\n        { \"IsActive\", new AttributeValue { BOOL = true } }\n    }\n});\n\n\u002F\u002F ── Перевірка конфігурації TTL ──────────────────────────────────────────────\nvar ttlDescription = await ddbClient.DescribeTimeToLiveAsync(new DescribeTimeToLiveRequest\n{\n    TableName = \"UserSessions\"\n});\n\n\u002F\u002F ── Зчитування даних із фільтрацією прострочених сесій ─────────────────────────\nlong nowTs = DateTimeOffset.UtcNow.ToUnixTimeSeconds();\nvar scanResult = await ddbClient.ScanAsync(new ScanRequest\n{\n    TableName = \"UserSessions\",\n    FilterExpression = \"ExpiresAt > :now\",\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":now\", new AttributeValue { N = nowTs.ToString() } }\n    }\n});\n",[3413,27879,27880,27892,27908,27912,27938,27942,27947,27965,27969,27979,27991,27995,28006,28016,28020,28024,28028,28033,28068,28084,28088,28098,28118,28122,28144,28167,28189,28218,28240,28244,28248,28252,28257,28282,28286,28295,28299,28303,28308,28329,28352,28356,28366,28377,28397,28401,28429,28433],{"__ignoreMap":3411},[3416,27881,27882,27884,27886,27888,27890],{"class":3418,"line":3419},[3416,27883,17433],{"class":11427},[3416,27885,17436],{"class":6397},[3416,27887,4043],{"class":3795},[3416,27889,17441],{"class":6397},[3416,27891,11594],{"class":3795},[3416,27893,27894,27896,27898,27900,27902,27904,27906],{"class":3418,"line":3425},[3416,27895,17433],{"class":11427},[3416,27897,17436],{"class":6397},[3416,27899,4043],{"class":3795},[3416,27901,17441],{"class":6397},[3416,27903,4043],{"class":3795},[3416,27905,17458],{"class":6397},[3416,27907,11594],{"class":3795},[3416,27909,27910],{"class":3418,"line":3431},[3416,27911,3441],{"emptyLinePlaceholder":3440},[3416,27913,27914,27916,27918,27920,27922,27924,27926,27928,27930,27932,27934,27936],{"class":3418,"line":3437},[3416,27915,6384],{"class":4368},[3416,27917,22796],{"class":6387},[3416,27919,6391],{"class":3795},[3416,27921,6394],{"class":4368},[3416,27923,6398],{"class":6397},[3416,27925,6423],{"class":3795},[3416,27927,22807],{"class":6387},[3416,27929,4043],{"class":3795},[3416,27931,22812],{"class":6387},[3416,27933,4043],{"class":3795},[3416,27935,22817],{"class":6387},[3416,27937,11465],{"class":3795},[3416,27939,27940],{"class":3418,"line":3444},[3416,27941,3441],{"emptyLinePlaceholder":3440},[3416,27943,27944],{"class":3418,"line":3450},[3416,27945,27946],{"class":3789},"\u002F\u002F ── Активація TTL на таблиці UserSessions за атрибутом ExpiresAt ─────────────\n",[3416,27948,27949,27951,27953,27955,27958,27960,27962],{"class":3418,"line":3456},[3416,27950,6413],{"class":4368},[3416,27952,22796],{"class":6387},[3416,27954,4043],{"class":3795},[3416,27956,27957],{"class":6330},"UpdateTimeToLiveAsync",[3416,27959,6423],{"class":3795},[3416,27961,6394],{"class":4368},[3416,27963,27964],{"class":6397}," UpdateTimeToLiveRequest\n",[3416,27966,27967],{"class":3418,"line":3462},[3416,27968,3796],{"class":3795},[3416,27970,27971,27973,27975,27977],{"class":3418,"line":3468},[3416,27972,6437],{"class":6387},[3416,27974,6391],{"class":3795},[3416,27976,6442],{"class":3808},[3416,27978,3812],{"class":3795},[3416,27980,27981,27984,27986,27988],{"class":3418,"line":3474},[3416,27982,27983],{"class":6387},"    TimeToLiveSpecification",[3416,27985,6391],{"class":3795},[3416,27987,6394],{"class":4368},[3416,27989,27990],{"class":6397}," TimeToLiveSpecification\n",[3416,27992,27993],{"class":3418,"line":3480},[3416,27994,6474],{"class":3795},[3416,27996,27997,28000,28002,28004],{"class":3418,"line":3486},[3416,27998,27999],{"class":6387},"        Enabled",[3416,28001,6391],{"class":3795},[3416,28003,4038],{"class":4368},[3416,28005,3812],{"class":3795},[3416,28007,28008,28011,28013],{"class":3418,"line":3492},[3416,28009,28010],{"class":6387},"        AttributeName",[3416,28012,6391],{"class":3795},[3416,28014,28015],{"class":3808},"\"ExpiresAt\"\n",[3416,28017,28018],{"class":3418,"line":3498},[3416,28019,4167],{"class":3795},[3416,28021,28022],{"class":3418,"line":3504},[3416,28023,6537],{"class":3795},[3416,28025,28026],{"class":3418,"line":3510},[3416,28027,3441],{"emptyLinePlaceholder":3440},[3416,28029,28030],{"class":3418,"line":3515},[3416,28031,28032],{"class":3789},"\u002F\u002F ── Запис елемента з часом життя 8 годин ──────────────────────────────────\n",[3416,28034,28035,28038,28041,28043,28046,28048,28051,28053,28056,28058,28061,28063,28066],{"class":3418,"line":3521},[3416,28036,28037],{"class":4368},"long",[3416,28039,28040],{"class":6387}," expiresAt",[3416,28042,6391],{"class":3795},[3416,28044,28045],{"class":6387},"DateTimeOffset",[3416,28047,4043],{"class":3795},[3416,28049,28050],{"class":6387},"UtcNow",[3416,28052,4043],{"class":3795},[3416,28054,28055],{"class":6330},"AddHours",[3416,28057,6423],{"class":3795},[3416,28059,28060],{"class":3870},"8",[3416,28062,13590],{"class":3795},[3416,28064,28065],{"class":6330},"ToUnixTimeSeconds",[3416,28067,6401],{"class":3795},[3416,28069,28070,28072,28074,28076,28078,28080,28082],{"class":3418,"line":3527},[3416,28071,6413],{"class":4368},[3416,28073,22796],{"class":6387},[3416,28075,4043],{"class":3795},[3416,28077,6718],{"class":6330},[3416,28079,6423],{"class":3795},[3416,28081,6394],{"class":4368},[3416,28083,6725],{"class":6397},[3416,28085,28086],{"class":3418,"line":3533},[3416,28087,3796],{"class":3795},[3416,28089,28090,28092,28094,28096],{"class":3418,"line":3539},[3416,28091,6437],{"class":6387},[3416,28093,6391],{"class":3795},[3416,28095,6442],{"class":3808},[3416,28097,3812],{"class":3795},[3416,28099,28100,28102,28104,28106,28108,28110,28112,28114,28116],{"class":3418,"line":3545},[3416,28101,6744],{"class":6387},[3416,28103,6391],{"class":3795},[3416,28105,6394],{"class":4368},[3416,28107,6456],{"class":6397},[3416,28109,5861],{"class":3795},[3416,28111,6461],{"class":4368},[3416,28113,4384],{"class":3795},[3416,28115,6466],{"class":6397},[3416,28117,6469],{"class":3795},[3416,28119,28120],{"class":3418,"line":3551},[3416,28121,6474],{"class":3795},[3416,28123,28124,28126,28128,28130,28132,28134,28136,28138,28140,28142],{"class":3418,"line":3557},[3416,28125,6479],{"class":3795},[3416,28127,6482],{"class":3808},[3416,28129,4384],{"class":3795},[3416,28131,6394],{"class":4368},[3416,28133,6489],{"class":6397},[3416,28135,6492],{"class":3795},[3416,28137,6495],{"class":6387},[3416,28139,6391],{"class":3795},[3416,28141,6500],{"class":3808},[3416,28143,6503],{"class":3795},[3416,28145,28146,28148,28150,28152,28154,28156,28158,28160,28162,28165],{"class":3418,"line":3563},[3416,28147,6479],{"class":3795},[3416,28149,6510],{"class":3808},[3416,28151,4384],{"class":3795},[3416,28153,6394],{"class":4368},[3416,28155,6489],{"class":6397},[3416,28157,6492],{"class":3795},[3416,28159,6495],{"class":6387},[3416,28161,6391],{"class":3795},[3416,28163,28164],{"class":3808},"\"sess-new-001\"",[3416,28166,6503],{"class":3795},[3416,28168,28169,28171,28173,28175,28177,28179,28181,28183,28185,28187],{"class":3418,"line":3569},[3416,28170,6479],{"class":3795},[3416,28172,6815],{"class":3808},[3416,28174,4384],{"class":3795},[3416,28176,6394],{"class":4368},[3416,28178,6489],{"class":6397},[3416,28180,6492],{"class":3795},[3416,28182,6495],{"class":6387},[3416,28184,6391],{"class":3795},[3416,28186,26473],{"class":3808},[3416,28188,6503],{"class":3795},[3416,28190,28191,28193,28195,28197,28199,28201,28203,28205,28207,28210,28212,28215],{"class":3418,"line":3574},[3416,28192,6479],{"class":3795},[3416,28194,12322],{"class":3808},[3416,28196,4384],{"class":3795},[3416,28198,6394],{"class":4368},[3416,28200,6489],{"class":6397},[3416,28202,6492],{"class":3795},[3416,28204,10168],{"class":6387},[3416,28206,6391],{"class":3795},[3416,28208,28209],{"class":6387},"expiresAt",[3416,28211,4043],{"class":3795},[3416,28213,28214],{"class":6330},"ToString",[3416,28216,28217],{"class":3795},"() } },\n",[3416,28219,28220,28222,28224,28226,28228,28230,28232,28234,28236,28238],{"class":3418,"line":3579},[3416,28221,6479],{"class":3795},[3416,28223,6839],{"class":3808},[3416,28225,4384],{"class":3795},[3416,28227,6394],{"class":4368},[3416,28229,6489],{"class":6397},[3416,28231,6492],{"class":3795},[3416,28233,6850],{"class":6387},[3416,28235,6391],{"class":3795},[3416,28237,4038],{"class":4368},[3416,28239,6528],{"class":3795},[3416,28241,28242],{"class":3418,"line":3584},[3416,28243,4167],{"class":3795},[3416,28245,28246],{"class":3418,"line":3590},[3416,28247,6537],{"class":3795},[3416,28249,28250],{"class":3418,"line":3596},[3416,28251,3441],{"emptyLinePlaceholder":3440},[3416,28253,28254],{"class":3418,"line":3602},[3416,28255,28256],{"class":3789},"\u002F\u002F ── Перевірка конфігурації TTL ──────────────────────────────────────────────\n",[3416,28258,28259,28261,28264,28266,28268,28270,28272,28275,28277,28279],{"class":3418,"line":3608},[3416,28260,6384],{"class":4368},[3416,28262,28263],{"class":6387}," ttlDescription",[3416,28265,6391],{"class":3795},[3416,28267,6413],{"class":4368},[3416,28269,22796],{"class":6387},[3416,28271,4043],{"class":3795},[3416,28273,28274],{"class":6330},"DescribeTimeToLiveAsync",[3416,28276,6423],{"class":3795},[3416,28278,6394],{"class":4368},[3416,28280,28281],{"class":6397}," DescribeTimeToLiveRequest\n",[3416,28283,28284],{"class":3418,"line":3614},[3416,28285,3796],{"class":3795},[3416,28287,28288,28290,28292],{"class":3418,"line":3620},[3416,28289,6437],{"class":6387},[3416,28291,6391],{"class":3795},[3416,28293,28294],{"class":3808},"\"UserSessions\"\n",[3416,28296,28297],{"class":3418,"line":3626},[3416,28298,6537],{"class":3795},[3416,28300,28301],{"class":3418,"line":3631},[3416,28302,3441],{"emptyLinePlaceholder":3440},[3416,28304,28305],{"class":3418,"line":3636},[3416,28306,28307],{"class":3789},"\u002F\u002F ── Зчитування даних із фільтрацією прострочених сесій ─────────────────────────\n",[3416,28309,28310,28312,28315,28317,28319,28321,28323,28325,28327],{"class":3418,"line":3641},[3416,28311,28037],{"class":4368},[3416,28313,28314],{"class":6387}," nowTs",[3416,28316,6391],{"class":3795},[3416,28318,28045],{"class":6387},[3416,28320,4043],{"class":3795},[3416,28322,28050],{"class":6387},[3416,28324,4043],{"class":3795},[3416,28326,28065],{"class":6330},[3416,28328,6401],{"class":3795},[3416,28330,28331,28333,28336,28338,28340,28342,28344,28346,28348,28350],{"class":3418,"line":3647},[3416,28332,6384],{"class":4368},[3416,28334,28335],{"class":6387}," scanResult",[3416,28337,6391],{"class":3795},[3416,28339,6413],{"class":4368},[3416,28341,22796],{"class":6387},[3416,28343,4043],{"class":3795},[3416,28345,8056],{"class":6330},[3416,28347,6423],{"class":3795},[3416,28349,6394],{"class":4368},[3416,28351,8063],{"class":6397},[3416,28353,28354],{"class":3418,"line":3653},[3416,28355,3796],{"class":3795},[3416,28357,28358,28360,28362,28364],{"class":3418,"line":3659},[3416,28359,6437],{"class":6387},[3416,28361,6391],{"class":3795},[3416,28363,6442],{"class":3808},[3416,28365,3812],{"class":3795},[3416,28367,28368,28370,28372,28375],{"class":3418,"line":3665},[3416,28369,8082],{"class":6387},[3416,28371,6391],{"class":3795},[3416,28373,28374],{"class":3808},"\"ExpiresAt > :now\"",[3416,28376,3812],{"class":3795},[3416,28378,28379,28381,28383,28385,28387,28389,28391,28393,28395],{"class":3418,"line":3671},[3416,28380,7179],{"class":6387},[3416,28382,6391],{"class":3795},[3416,28384,6394],{"class":4368},[3416,28386,6456],{"class":6397},[3416,28388,5861],{"class":3795},[3416,28390,6461],{"class":4368},[3416,28392,4384],{"class":3795},[3416,28394,6466],{"class":6397},[3416,28396,6469],{"class":3795},[3416,28398,28399],{"class":3418,"line":3677},[3416,28400,6474],{"class":3795},[3416,28402,28403,28405,28407,28409,28411,28413,28415,28417,28419,28422,28424,28426],{"class":3418,"line":3683},[3416,28404,6479],{"class":3795},[3416,28406,7229],{"class":3808},[3416,28408,4384],{"class":3795},[3416,28410,6394],{"class":4368},[3416,28412,6489],{"class":6397},[3416,28414,6492],{"class":3795},[3416,28416,10168],{"class":6387},[3416,28418,6391],{"class":3795},[3416,28420,28421],{"class":6387},"nowTs",[3416,28423,4043],{"class":3795},[3416,28425,28214],{"class":6330},[3416,28427,28428],{"class":3795},"() } }\n",[3416,28430,28431],{"class":3418,"line":3688},[3416,28432,4167],{"class":3795},[3416,28434,28435],{"class":3418,"line":3693},[3416,28436,6537],{"class":3795},[6311,28438,28439],{"label":6540},[3406,28440,28442],{"className":6543,"code":28441,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n# ── Активація TTL на таблиці ──────────────────────────────────────────────────\n$ttlSpec = [Amazon.DynamoDBv2.Model.TimeToLiveSpecification]@{\n    Enabled       = $true\n    AttributeName = 'ExpiresAt'\n}\nUpdate-DDBTimeToLive -TableName UserSessions -TimeToLiveSpecification $ttlSpec -Region eu-central-1\n\n# ── Запис сесії з часом життя 8 годин ──────────────────────────────────────────\n$expiresAt = [int][double]::Parse(\n    (Get-Date).AddHours(8).ToUniversalTime().Subtract([datetime]'1970-01-01').TotalSeconds\n)\n$item = @{\n    UserId    = New-DDBEntry -S 'usr-001'\n    SessionId = New-DDBEntry -S 'sess-new-001'\n    CreatedAt = New-DDBEntry -S '2026-06-03T12:00:00Z'\n    ExpiresAt = New-DDBEntry -N \"$expiresAt\"\n    IsActive  = New-DDBEntry -BOOL $true\n}\nSet-DDBItem -TableName UserSessions -Item $item -Region eu-central-1\n\n# ── Запит активних сесій з фільтрацією за часом ──────────────────────────────\n$nowTs = [int][double]::Parse(\n    (Get-Date).ToUniversalTime().Subtract([datetime]'1970-01-01').TotalSeconds\n)\n$scanRequest = [Amazon.DynamoDBv2.Model.ScanRequest]@{\n    TableName        = 'UserSessions'\n    FilterExpression = 'ExpiresAt > :now'\n    ExpressionAttributeValues = @{ ':now' = New-DDBEntry -N \"$nowTs\" }\n}\nInvoke-DDBScan -ScanRequest $scanRequest -Region eu-central-1\n",[3413,28443,28444,28450,28454,28459,28475,28484,28494,28498,28512,28516,28521,28540,28567,28571,28581,28593,28606,28618,28634,28646,28650,28662,28666,28671,28686,28702,28706,28720,28728,28737,28764,28768],{"__ignoreMap":3411},[3416,28445,28446,28448],{"class":3418,"line":3419},[3416,28447,12967],{"class":6330},[3416,28449,12970],{"class":3795},[3416,28451,28452],{"class":3418,"line":3425},[3416,28453,3441],{"emptyLinePlaceholder":3440},[3416,28455,28456],{"class":3418,"line":3431},[3416,28457,28458],{"class":3789},"# ── Активація TTL на таблиці ──────────────────────────────────────────────────\n",[3416,28460,28461,28464,28466,28469,28471,28473],{"class":3418,"line":3437},[3416,28462,28463],{"class":6387},"$ttlSpec",[3416,28465,7274],{"class":3795},[3416,28467,28468],{"class":4368},"Amazon.DynamoDBv2.Model.TimeToLiveSpecification",[3416,28470,7280],{"class":3795},[3416,28472,6561],{"class":4368},[3416,28474,3796],{"class":3795},[3416,28476,28477,28480,28482],{"class":3418,"line":3444},[3416,28478,28479],{"class":6387},"    Enabled",[3416,28481,21045],{"class":3795},[3416,28483,6941],{"class":4368},[3416,28485,28486,28489,28491],{"class":3418,"line":3450},[3416,28487,28488],{"class":6387},"    AttributeName",[3416,28490,6391],{"class":3795},[3416,28492,28493],{"class":3808},"'ExpiresAt'\n",[3416,28495,28496],{"class":3418,"line":3456},[3416,28497,3507],{"class":3795},[3416,28499,28500,28503,28506,28508,28510],{"class":3418,"line":3462},[3416,28501,28502],{"class":6330},"Update-DDBTimeToLive",[3416,28504,28505],{"class":3795}," -TableName UserSessions -TimeToLiveSpecification ",[3416,28507,28463],{"class":6387},[3416,28509,6611],{"class":3795},[3416,28511,6614],{"class":3870},[3416,28513,28514],{"class":3418,"line":3468},[3416,28515,3441],{"emptyLinePlaceholder":3440},[3416,28517,28518],{"class":3418,"line":3474},[3416,28519,28520],{"class":3789},"# ── Запис сесії з часом життя 8 годин ──────────────────────────────────────────\n",[3416,28522,28523,28526,28528,28531,28534,28537],{"class":3418,"line":3480},[3416,28524,28525],{"class":6387},"$expiresAt",[3416,28527,7274],{"class":3795},[3416,28529,28530],{"class":4368},"int",[3416,28532,28533],{"class":3795},"][",[3416,28535,28536],{"class":4368},"double",[3416,28538,28539],{"class":3795},"]::Parse(\n",[3416,28541,28542,28545,28548,28551,28553,28556,28559,28561,28564],{"class":3418,"line":3486},[3416,28543,28544],{"class":3795},"    (",[3416,28546,28547],{"class":6330},"Get-Date",[3416,28549,28550],{"class":3795},").AddHours(",[3416,28552,28060],{"class":3870},[3416,28554,28555],{"class":3795},").ToUniversalTime().Subtract([",[3416,28557,28558],{"class":4368},"datetime",[3416,28560,7280],{"class":3795},[3416,28562,28563],{"class":3808},"'1970-01-01'",[3416,28565,28566],{"class":3795},").TotalSeconds\n",[3416,28568,28569],{"class":3418,"line":3492},[3416,28570,9656],{"class":3795},[3416,28572,28573,28575,28577,28579],{"class":3418,"line":3498},[3416,28574,6881],{"class":6387},[3416,28576,6391],{"class":3795},[3416,28578,6561],{"class":4368},[3416,28580,3796],{"class":3795},[3416,28582,28583,28585,28587,28589,28591],{"class":3418,"line":3504},[3416,28584,6568],{"class":6387},[3416,28586,6571],{"class":3795},[3416,28588,6574],{"class":6330},[3416,28590,6577],{"class":3795},[3416,28592,6580],{"class":3808},[3416,28594,28595,28597,28599,28601,28603],{"class":3418,"line":3510},[3416,28596,6585],{"class":6387},[3416,28598,6391],{"class":3795},[3416,28600,6574],{"class":6330},[3416,28602,6577],{"class":3795},[3416,28604,28605],{"class":3808},"'sess-new-001'\n",[3416,28607,28608,28610,28612,28614,28616],{"class":3418,"line":3515},[3416,28609,6916],{"class":6387},[3416,28611,6391],{"class":3795},[3416,28613,6574],{"class":6330},[3416,28615,6577],{"class":3795},[3416,28617,27103],{"class":3808},[3416,28619,28620,28622,28624,28626,28628,28630,28632],{"class":3418,"line":3521},[3416,28621,13029],{"class":6387},[3416,28623,6391],{"class":3795},[3416,28625,6574],{"class":6330},[3416,28627,10395],{"class":3795},[3416,28629,24569],{"class":3808},[3416,28631,28525],{"class":6387},[3416,28633,24525],{"class":3808},[3416,28635,28636,28638,28640,28642,28644],{"class":3418,"line":3527},[3416,28637,6930],{"class":6387},[3416,28639,6933],{"class":3795},[3416,28641,6574],{"class":6330},[3416,28643,6938],{"class":3795},[3416,28645,6941],{"class":4368},[3416,28647,28648],{"class":3418,"line":3533},[3416,28649,3507],{"class":3795},[3416,28651,28652,28654,28656,28658,28660],{"class":3418,"line":3539},[3416,28653,6950],{"class":6330},[3416,28655,6953],{"class":3795},[3416,28657,6881],{"class":6387},[3416,28659,6611],{"class":3795},[3416,28661,6614],{"class":3870},[3416,28663,28664],{"class":3418,"line":3545},[3416,28665,3441],{"emptyLinePlaceholder":3440},[3416,28667,28668],{"class":3418,"line":3551},[3416,28669,28670],{"class":3789},"# ── Запит активних сесій з фільтрацією за часом ──────────────────────────────\n",[3416,28672,28673,28676,28678,28680,28682,28684],{"class":3418,"line":3557},[3416,28674,28675],{"class":6387},"$nowTs",[3416,28677,7274],{"class":3795},[3416,28679,28530],{"class":4368},[3416,28681,28533],{"class":3795},[3416,28683,28536],{"class":4368},[3416,28685,28539],{"class":3795},[3416,28687,28688,28690,28692,28694,28696,28698,28700],{"class":3418,"line":3563},[3416,28689,28544],{"class":3795},[3416,28691,28547],{"class":6330},[3416,28693,28555],{"class":3795},[3416,28695,28558],{"class":4368},[3416,28697,7280],{"class":3795},[3416,28699,28563],{"class":3808},[3416,28701,28566],{"class":3795},[3416,28703,28704],{"class":3418,"line":3569},[3416,28705,9656],{"class":3795},[3416,28707,28708,28710,28712,28714,28716,28718],{"class":3418,"line":3574},[3416,28709,8161],{"class":6387},[3416,28711,7274],{"class":3795},[3416,28713,8166],{"class":4368},[3416,28715,7280],{"class":3795},[3416,28717,6561],{"class":4368},[3416,28719,3796],{"class":3795},[3416,28721,28722,28724,28726],{"class":3418,"line":3579},[3416,28723,6437],{"class":6387},[3416,28725,7923],{"class":3795},[3416,28727,7293],{"class":3808},[3416,28729,28730,28732,28734],{"class":3418,"line":3584},[3416,28731,8082],{"class":6387},[3416,28733,6391],{"class":3795},[3416,28735,28736],{"class":3808},"'ExpiresAt > :now'\n",[3416,28738,28739,28741,28743,28745,28747,28750,28752,28754,28756,28758,28760,28762],{"class":3418,"line":3590},[3416,28740,7179],{"class":6387},[3416,28742,6391],{"class":3795},[3416,28744,6561],{"class":4368},[3416,28746,8886],{"class":3795},[3416,28748,28749],{"class":3808},"':now'",[3416,28751,6391],{"class":3795},[3416,28753,6574],{"class":6330},[3416,28755,10395],{"class":3795},[3416,28757,24569],{"class":3808},[3416,28759,28675],{"class":6387},[3416,28761,24569],{"class":3808},[3416,28763,8948],{"class":3795},[3416,28765,28766],{"class":3418,"line":3596},[3416,28767,3507],{"class":3795},[3416,28769,28770,28772,28774,28776,28778],{"class":3418,"line":3602},[3416,28771,8225],{"class":6330},[3416,28773,8228],{"class":3795},[3416,28775,8161],{"class":6387},[3416,28777,6611],{"class":3795},[3416,28779,6614],{"class":3870},[3720,28781],{},[3727,28783,28785],{"id":28784},"global-tables-мультирегіональна-реплікація-active-active","Global Tables — мультирегіональна реплікація Active-Active",[3353,28787,28788,28791],{},[3363,28789,28790],{},"DynamoDB Global Tables"," — це повністю кероване рішення для забезпечення географічного розподілу та стійкості систем до відмови на рівні цілих регіонів AWS. Воно реалізує двонаправлену мультиактивну (Active-Active) реплікацію даних між обраними регіонами.",[4584,28793,28795],{"id":28794},"архітектурні-засади-та-гарантії","Архітектурні засади та гарантії:",[3374,28797,28798,28807,28817],{},[3377,28799,28800,28803,28804,4043],{},[3363,28801,28802],{},"Асинхронна реплікація:"," Запис у будь-яку копію таблиці (replica) в одному регіоні автоматично реплікується в усі інші підключені регіони. Час реплікації зазвичай не перевищує ",[3363,28805,28806],{},"однієї секунди",[3377,28808,28809,28812,28813,28816],{},[3363,28810,28811],{},"Конфлікти та Last Writer Wins (LWW):"," Оскільки запис може відбуватися одночасно в різних регіонах, при конфлікті оновлення одного елемента DynamoDB застосовує стратегію вирішення конфліктів ",[4091,28814,28815],{},"Last Writer Wins"," на основі внутрішніх таймстемпів операцій.",[3377,28818,28819,28822,28835],{},[3363,28820,28821],{},"Технічні передумови:",[4488,28823,28824,28832],{},[3377,28825,28826,28827,28829,28830,4043],{},"Для створення Global Tables на таблиці обов'язково повинен бути увімкнений потік змін ",[3363,28828,24041],{}," із представленням ",[3413,28831,24331],{},[3377,28833,28834],{},"Режими ємності RCU\u002FWCU повинні бути ідентично налаштовані в усіх регіонах реплікації.",[22319,28836,28837],{},[3353,28838,28839,28841,28842,28844],{},[3416,28840,22325],{},"\nРеплікація даних споживає ",[3363,28843,21637],{}," у кожному цільовому регіоні. Якщо ви виконуєте 10 записів за секунду в регіоні eu-central-1, і у вас налаштована реплікація в us-east-1, ці записи спишуть відповідну кількість WCU в обох регіонах.",[3403,28846,28847],{},[3406,28848,28850],{"className":3408,"code":28849,"language":3410,"meta":3411,"style":3411},"@startuml\n!theme plain\nskinparam backgroundColor #FAFAFA\nskinparam defaultFontName \"DejaVu Sans\"\n\ntitle Мультирегіональна Active-Active реплікація Global Tables\n\nrectangle \"eu-central-1 (Франкфурт)\" as reg1 #D5E8D4 {\n  database \"Таблиця Orders (Replica)\" as db1\n  actor \"Користувачі ЄС\" as client1\n}\n\nrectangle \"us-east-1 (Вірджинія)\" as reg2 #E8F4FD {\n  database \"Таблиця Orders (Replica)\" as db2\n  actor \"Користувачі США\" as client2\n}\n\nrectangle \"ap-southeast-1 (Сінгапур)\" as reg3 #FFF2CC {\n  database \"Таблиця Orders (Replica)\" as db3\n  actor \"Користувачі Азії\" as client3\n}\n\nclient1 --> db1 : \"Локальний запис (RTT: ~10ms)\"\nclient2 --> db2 : \"Локальний запис (RTT: ~15ms)\"\nclient3 --> db3 : \"Локальний запис (RTT: ~8ms)\"\n\ndb1 \u003C--> db2 : \"Асинхронна реплікація (\u003C 1 сек)\"\ndb2 \u003C--> db3 : \"Асинхронна реплікація (\u003C 1 сек)\"\ndb1 \u003C--> db3 : \"Асинхронна реплікація (\u003C 1 сек)\"\n@enduml\n",[3413,28851,28852,28856,28860,28864,28868,28872,28877,28881,28886,28891,28896,28900,28904,28909,28914,28919,28923,28927,28932,28937,28942,28946,28950,28955,28960,28965,28969,28974,28979,28984],{"__ignoreMap":3411},[3416,28853,28854],{"class":3418,"line":3419},[3416,28855,3422],{},[3416,28857,28858],{"class":3418,"line":3425},[3416,28859,16755],{},[3416,28861,28862],{"class":3418,"line":3431},[3416,28863,16760],{},[3416,28865,28866],{"class":3418,"line":3437},[3416,28867,16765],{},[3416,28869,28870],{"class":3418,"line":3444},[3416,28871,3441],{"emptyLinePlaceholder":3440},[3416,28873,28874],{"class":3418,"line":3450},[3416,28875,28876],{},"title Мультирегіональна Active-Active реплікація Global Tables\n",[3416,28878,28879],{"class":3418,"line":3456},[3416,28880,3441],{"emptyLinePlaceholder":3440},[3416,28882,28883],{"class":3418,"line":3462},[3416,28884,28885],{},"rectangle \"eu-central-1 (Франкфурт)\" as reg1 #D5E8D4 {\n",[3416,28887,28888],{"class":3418,"line":3468},[3416,28889,28890],{},"  database \"Таблиця Orders (Replica)\" as db1\n",[3416,28892,28893],{"class":3418,"line":3474},[3416,28894,28895],{},"  actor \"Користувачі ЄС\" as client1\n",[3416,28897,28898],{"class":3418,"line":3480},[3416,28899,3507],{},[3416,28901,28902],{"class":3418,"line":3486},[3416,28903,3441],{"emptyLinePlaceholder":3440},[3416,28905,28906],{"class":3418,"line":3492},[3416,28907,28908],{},"rectangle \"us-east-1 (Вірджинія)\" as reg2 #E8F4FD {\n",[3416,28910,28911],{"class":3418,"line":3498},[3416,28912,28913],{},"  database \"Таблиця Orders (Replica)\" as db2\n",[3416,28915,28916],{"class":3418,"line":3504},[3416,28917,28918],{},"  actor \"Користувачі США\" as client2\n",[3416,28920,28921],{"class":3418,"line":3510},[3416,28922,3507],{},[3416,28924,28925],{"class":3418,"line":3515},[3416,28926,3441],{"emptyLinePlaceholder":3440},[3416,28928,28929],{"class":3418,"line":3521},[3416,28930,28931],{},"rectangle \"ap-southeast-1 (Сінгапур)\" as reg3 #FFF2CC {\n",[3416,28933,28934],{"class":3418,"line":3527},[3416,28935,28936],{},"  database \"Таблиця Orders (Replica)\" as db3\n",[3416,28938,28939],{"class":3418,"line":3533},[3416,28940,28941],{},"  actor \"Користувачі Азії\" as client3\n",[3416,28943,28944],{"class":3418,"line":3539},[3416,28945,3507],{},[3416,28947,28948],{"class":3418,"line":3545},[3416,28949,3441],{"emptyLinePlaceholder":3440},[3416,28951,28952],{"class":3418,"line":3551},[3416,28953,28954],{},"client1 --> db1 : \"Локальний запис (RTT: ~10ms)\"\n",[3416,28956,28957],{"class":3418,"line":3557},[3416,28958,28959],{},"client2 --> db2 : \"Локальний запис (RTT: ~15ms)\"\n",[3416,28961,28962],{"class":3418,"line":3563},[3416,28963,28964],{},"client3 --> db3 : \"Локальний запис (RTT: ~8ms)\"\n",[3416,28966,28967],{"class":3418,"line":3569},[3416,28968,3441],{"emptyLinePlaceholder":3440},[3416,28970,28971],{"class":3418,"line":3574},[3416,28972,28973],{},"db1 \u003C--> db2 : \"Асинхронна реплікація (\u003C 1 сек)\"\n",[3416,28975,28976],{"class":3418,"line":3579},[3416,28977,28978],{},"db2 \u003C--> db3 : \"Асинхронна реплікація (\u003C 1 сек)\"\n",[3416,28980,28981],{"class":3418,"line":3584},[3416,28982,28983],{},"db1 \u003C--> db3 : \"Асинхронна реплікація (\u003C 1 сек)\"\n",[3416,28985,28986],{"class":3418,"line":3590},[3416,28987,3718],{},[4584,28989,28991],{"id":28990},"налаштування-global-tables","Налаштування Global Tables",[6308,28993,28994,29184,29695],{},[6311,28995,28996],{"label":6313},[3406,28997,28999],{"className":6316,"code":28998,"language":6318,"meta":3411,"style":3411},"# ── Крок 1: Створення базової таблиці з увімкненим потоком Streams ───────────\naws dynamodb create-table \\\n    --table-name Orders \\\n    --attribute-definitions \\\n        AttributeName=CustomerId,AttributeType=S \\\n        AttributeName=OrderId,AttributeType=S \\\n    --key-schema \\\n        AttributeName=CustomerId,KeyType=HASH \\\n        AttributeName=OrderId,KeyType=RANGE \\\n    --billing-mode PAY_PER_REQUEST \\\n    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \\\n    --region eu-central-1\n\n# ── Крок 2: Додавання реплік у регіони us-east-1 та ap-southeast-1 ───────────\naws dynamodb update-table \\\n    --table-name Orders \\\n    --replica-updates '[\n        {\"Create\": {\"RegionName\": \"us-east-1\"}},\n        {\"Create\": {\"RegionName\": \"ap-southeast-1\"}}\n    ]' \\\n    --region eu-central-1\n\n# ── Отримання статусу реплікації ─────────────────────────────────────────────\naws dynamodb describe-table \\\n    --table-name Orders \\\n    --query \"Table.Replicas\" \\\n    --region eu-central-1\n",[3413,29000,29001,29006,29016,29024,29030,29036,29042,29048,29054,29060,29068,29080,29086,29090,29095,29105,29113,29120,29125,29130,29136,29142,29146,29151,29161,29169,29178],{"__ignoreMap":3411},[3416,29002,29003],{"class":3418,"line":3419},[3416,29004,29005],{"class":3789},"# ── Крок 1: Створення базової таблиці з увімкненим потоком Streams ───────────\n",[3416,29007,29008,29010,29012,29014],{"class":3418,"line":3425},[3416,29009,6331],{"class":6330},[3416,29011,6334],{"class":3808},[3416,29013,10696],{"class":3808},[3416,29015,6341],{"class":6340},[3416,29017,29018,29020,29022],{"class":3418,"line":3431},[3416,29019,6346],{"class":4368},[3416,29021,19317],{"class":3808},[3416,29023,6341],{"class":6340},[3416,29025,29026,29028],{"class":3418,"line":3437},[3416,29027,10711],{"class":4368},[3416,29029,6341],{"class":6340},[3416,29031,29032,29034],{"class":3418,"line":3444},[3416,29033,19330],{"class":3808},[3416,29035,6341],{"class":6340},[3416,29037,29038,29040],{"class":3418,"line":3450},[3416,29039,22413],{"class":3808},[3416,29041,6341],{"class":6340},[3416,29043,29044,29046],{"class":3418,"line":3456},[3416,29045,10732],{"class":4368},[3416,29047,6341],{"class":6340},[3416,29049,29050,29052],{"class":3418,"line":3462},[3416,29051,19364],{"class":3808},[3416,29053,6341],{"class":6340},[3416,29055,29056,29058],{"class":3418,"line":3468},[3416,29057,22432],{"class":3808},[3416,29059,6341],{"class":6340},[3416,29061,29062,29064,29066],{"class":3418,"line":3474},[3416,29063,10753],{"class":4368},[3416,29065,10756],{"class":3808},[3416,29067,6341],{"class":6340},[3416,29069,29070,29072,29074,29076,29078],{"class":3418,"line":3480},[3416,29071,24436],{"class":4368},[3416,29073,24439],{"class":3808},[3416,29075,4038],{"class":4368},[3416,29077,24444],{"class":3808},[3416,29079,6341],{"class":6340},[3416,29081,29082,29084],{"class":3418,"line":3486},[3416,29083,6366],{"class":4368},[3416,29085,6369],{"class":3808},[3416,29087,29088],{"class":3418,"line":3492},[3416,29089,3441],{"emptyLinePlaceholder":3440},[3416,29091,29092],{"class":3418,"line":3498},[3416,29093,29094],{"class":3789},"# ── Крок 2: Додавання реплік у регіони us-east-1 та ap-southeast-1 ───────────\n",[3416,29096,29097,29099,29101,29103],{"class":3418,"line":3504},[3416,29098,6331],{"class":6330},[3416,29100,6334],{"class":3808},[3416,29102,17279],{"class":3808},[3416,29104,6341],{"class":6340},[3416,29106,29107,29109,29111],{"class":3418,"line":3510},[3416,29108,6346],{"class":4368},[3416,29110,19317],{"class":3808},[3416,29112,6341],{"class":6340},[3416,29114,29115,29118],{"class":3418,"line":3515},[3416,29116,29117],{"class":4368},"    --replica-updates",[3416,29119,9727],{"class":3808},[3416,29121,29122],{"class":3418,"line":3521},[3416,29123,29124],{"class":3808},"        {\"Create\": {\"RegionName\": \"us-east-1\"}},\n",[3416,29126,29127],{"class":3418,"line":3527},[3416,29128,29129],{"class":3808},"        {\"Create\": {\"RegionName\": \"ap-southeast-1\"}}\n",[3416,29131,29132,29134],{"class":3418,"line":3533},[3416,29133,9816],{"class":3808},[3416,29135,6341],{"class":6340},[3416,29137,29138,29140],{"class":3418,"line":3539},[3416,29139,6366],{"class":4368},[3416,29141,6369],{"class":3808},[3416,29143,29144],{"class":3418,"line":3545},[3416,29145,3441],{"emptyLinePlaceholder":3440},[3416,29147,29148],{"class":3418,"line":3551},[3416,29149,29150],{"class":3789},"# ── Отримання статусу реплікації ─────────────────────────────────────────────\n",[3416,29152,29153,29155,29157,29159],{"class":3418,"line":3557},[3416,29154,6331],{"class":6330},[3416,29156,6334],{"class":3808},[3416,29158,11374],{"class":3808},[3416,29160,6341],{"class":6340},[3416,29162,29163,29165,29167],{"class":3418,"line":3563},[3416,29164,6346],{"class":4368},[3416,29166,19317],{"class":3808},[3416,29168,6341],{"class":6340},[3416,29170,29171,29173,29176],{"class":3418,"line":3569},[3416,29172,11398],{"class":4368},[3416,29174,29175],{"class":3808}," \"Table.Replicas\"",[3416,29177,6341],{"class":6340},[3416,29179,29180,29182],{"class":3418,"line":3574},[3416,29181,6366],{"class":4368},[3416,29183,6369],{"class":3808},[6311,29185,29186],{"label":6372},[3406,29187,29189],{"className":6375,"code":29188,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nvar ddbClient = new AmazonDynamoDBClient(Amazon.RegionEndpoint.EUCentral1);\n\n\u002F\u002F ── Крок 1: Створення таблиці в eu-central-1 з активацією Streams ───────────\nawait ddbClient.CreateTableAsync(new CreateTableRequest\n{\n    TableName = \"Orders\",\n    AttributeDefinitions = new List\u003CAttributeDefinition>\n    {\n        new() { AttributeName = \"CustomerId\", AttributeType = ScalarAttributeType.S },\n        new() { AttributeName = \"OrderId\", AttributeType = ScalarAttributeType.S }\n    },\n    KeySchema = new List\u003CKeySchemaElement>\n    {\n        new() { AttributeName = \"CustomerId\", KeyType = KeyType.HASH },\n        new() { AttributeName = \"OrderId\", KeyType = KeyType.RANGE }\n    },\n    BillingMode = BillingMode.PAY_PER_REQUEST,\n    StreamSpecification = new StreamSpecification\n    {\n        StreamEnabled = true,\n        StreamViewType = StreamViewType.NEW_AND_OLD_IMAGES\n    }\n});\n\n\u002F\u002F ── Крок 2: Додавання реплік у регіони us-east-1 та ap-southeast-1 ───────────\nawait ddbClient.UpdateTableAsync(new UpdateTableRequest\n{\n    TableName = \"Orders\",\n    ReplicaUpdates = new List\u003CReplicationGroupUpdate>\n    {\n        new()\n        {\n            Create = new CreateReplicationGroupMemberAction { RegionName = \"us-east-1\" }\n        },\n        new()\n        {\n            Create = new CreateReplicationGroupMemberAction { RegionName = \"ap-southeast-1\" }\n        }\n    }\n});\n\n\u002F\u002F ── Отримання статусу реплікації таблиці ────────────────────────────────────\nvar tableDesc = await ddbClient.DescribeTableAsync(\"Orders\");\nvar replicas = tableDesc.Table.Replicas;\n",[3413,29190,29191,29203,29219,29223,29249,29253,29258,29274,29278,29288,29304,29308,29334,29360,29364,29380,29384,29410,29436,29440,29455,29465,29469,29479,29491,29495,29499,29503,29508,29524,29528,29538,29556,29560,29566,29570,29593,29597,29603,29607,29628,29632,29636,29640,29644,29649,29672],{"__ignoreMap":3411},[3416,29192,29193,29195,29197,29199,29201],{"class":3418,"line":3419},[3416,29194,17433],{"class":11427},[3416,29196,17436],{"class":6397},[3416,29198,4043],{"class":3795},[3416,29200,17441],{"class":6397},[3416,29202,11594],{"class":3795},[3416,29204,29205,29207,29209,29211,29213,29215,29217],{"class":3418,"line":3425},[3416,29206,17433],{"class":11427},[3416,29208,17436],{"class":6397},[3416,29210,4043],{"class":3795},[3416,29212,17441],{"class":6397},[3416,29214,4043],{"class":3795},[3416,29216,17458],{"class":6397},[3416,29218,11594],{"class":3795},[3416,29220,29221],{"class":3418,"line":3431},[3416,29222,3441],{"emptyLinePlaceholder":3440},[3416,29224,29225,29227,29229,29231,29233,29235,29237,29239,29241,29243,29245,29247],{"class":3418,"line":3437},[3416,29226,6384],{"class":4368},[3416,29228,22796],{"class":6387},[3416,29230,6391],{"class":3795},[3416,29232,6394],{"class":4368},[3416,29234,6398],{"class":6397},[3416,29236,6423],{"class":3795},[3416,29238,22807],{"class":6387},[3416,29240,4043],{"class":3795},[3416,29242,22812],{"class":6387},[3416,29244,4043],{"class":3795},[3416,29246,22817],{"class":6387},[3416,29248,11465],{"class":3795},[3416,29250,29251],{"class":3418,"line":3444},[3416,29252,3441],{"emptyLinePlaceholder":3440},[3416,29254,29255],{"class":3418,"line":3450},[3416,29256,29257],{"class":3789},"\u002F\u002F ── Крок 1: Створення таблиці в eu-central-1 з активацією Streams ───────────\n",[3416,29259,29260,29262,29264,29266,29268,29270,29272],{"class":3418,"line":3456},[3416,29261,6413],{"class":4368},[3416,29263,22796],{"class":6387},[3416,29265,4043],{"class":3795},[3416,29267,10802],{"class":6330},[3416,29269,6423],{"class":3795},[3416,29271,6394],{"class":4368},[3416,29273,10809],{"class":6397},[3416,29275,29276],{"class":3418,"line":3462},[3416,29277,3796],{"class":3795},[3416,29279,29280,29282,29284,29286],{"class":3418,"line":3468},[3416,29281,6437],{"class":6387},[3416,29283,6391],{"class":3795},[3416,29285,19785],{"class":3808},[3416,29287,3812],{"class":3795},[3416,29289,29290,29292,29294,29296,29298,29300,29302],{"class":3418,"line":3474},[3416,29291,10828],{"class":6387},[3416,29293,6391],{"class":3795},[3416,29295,6394],{"class":4368},[3416,29297,8640],{"class":6397},[3416,29299,5861],{"class":3795},[3416,29301,10839],{"class":6397},[3416,29303,6469],{"class":3795},[3416,29305,29306],{"class":3418,"line":3480},[3416,29307,6474],{"class":3795},[3416,29309,29310,29312,29314,29316,29318,29320,29322,29324,29326,29328,29330,29332],{"class":3418,"line":3486},[3416,29311,9886],{"class":4368},[3416,29313,17546],{"class":3795},[3416,29315,10857],{"class":6387},[3416,29317,6391],{"class":3795},[3416,29319,19820],{"class":3808},[3416,29321,4384],{"class":3795},[3416,29323,10866],{"class":6387},[3416,29325,6391],{"class":3795},[3416,29327,10871],{"class":6387},[3416,29329,4043],{"class":3795},[3416,29331,6495],{"class":6387},[3416,29333,8915],{"class":3795},[3416,29335,29336,29338,29340,29342,29344,29346,29348,29350,29352,29354,29356,29358],{"class":3418,"line":3492},[3416,29337,9886],{"class":4368},[3416,29339,17546],{"class":3795},[3416,29341,10857],{"class":6387},[3416,29343,6391],{"class":3795},[3416,29345,20498],{"class":3808},[3416,29347,4384],{"class":3795},[3416,29349,10866],{"class":6387},[3416,29351,6391],{"class":3795},[3416,29353,10871],{"class":6387},[3416,29355,4043],{"class":3795},[3416,29357,6495],{"class":6387},[3416,29359,8948],{"class":3795},[3416,29361,29362],{"class":3418,"line":3498},[3416,29363,4442],{"class":3795},[3416,29365,29366,29368,29370,29372,29374,29376,29378],{"class":3418,"line":3504},[3416,29367,10914],{"class":6387},[3416,29369,6391],{"class":3795},[3416,29371,6394],{"class":4368},[3416,29373,8640],{"class":6397},[3416,29375,5861],{"class":3795},[3416,29377,10925],{"class":6397},[3416,29379,6469],{"class":3795},[3416,29381,29382],{"class":3418,"line":3510},[3416,29383,6474],{"class":3795},[3416,29385,29386,29388,29390,29392,29394,29396,29398,29400,29402,29404,29406,29408],{"class":3418,"line":3515},[3416,29387,9886],{"class":4368},[3416,29389,17546],{"class":3795},[3416,29391,10857],{"class":6387},[3416,29393,6391],{"class":3795},[3416,29395,19820],{"class":3808},[3416,29397,4384],{"class":3795},[3416,29399,10951],{"class":6387},[3416,29401,6391],{"class":3795},[3416,29403,10951],{"class":6387},[3416,29405,4043],{"class":3795},[3416,29407,10960],{"class":6387},[3416,29409,8915],{"class":3795},[3416,29411,29412,29414,29416,29418,29420,29422,29424,29426,29428,29430,29432,29434],{"class":3418,"line":3521},[3416,29413,9886],{"class":4368},[3416,29415,17546],{"class":3795},[3416,29417,10857],{"class":6387},[3416,29419,6391],{"class":3795},[3416,29421,20498],{"class":3808},[3416,29423,4384],{"class":3795},[3416,29425,10951],{"class":6387},[3416,29427,6391],{"class":3795},[3416,29429,10951],{"class":6387},[3416,29431,4043],{"class":3795},[3416,29433,10989],{"class":6387},[3416,29435,8948],{"class":3795},[3416,29437,29438],{"class":3418,"line":3527},[3416,29439,4442],{"class":3795},[3416,29441,29442,29444,29446,29448,29450,29453],{"class":3418,"line":3533},[3416,29443,11000],{"class":6387},[3416,29445,6391],{"class":3795},[3416,29447,11005],{"class":6387},[3416,29449,4043],{"class":3795},[3416,29451,29452],{"class":6387},"PAY_PER_REQUEST",[3416,29454,3812],{"class":3795},[3416,29456,29457,29459,29461,29463],{"class":3418,"line":3539},[3416,29458,24790],{"class":6387},[3416,29460,6391],{"class":3795},[3416,29462,6394],{"class":4368},[3416,29464,24797],{"class":6397},[3416,29466,29467],{"class":3418,"line":3545},[3416,29468,6474],{"class":3795},[3416,29470,29471,29473,29475,29477],{"class":3418,"line":3551},[3416,29472,24806],{"class":6387},[3416,29474,6391],{"class":3795},[3416,29476,4038],{"class":4368},[3416,29478,3812],{"class":3795},[3416,29480,29481,29483,29485,29487,29489],{"class":3418,"line":3557},[3416,29482,24817],{"class":6387},[3416,29484,6391],{"class":3795},[3416,29486,24822],{"class":6387},[3416,29488,4043],{"class":3795},[3416,29490,24827],{"class":6387},[3416,29492,29493],{"class":3418,"line":3563},[3416,29494,4167],{"class":3795},[3416,29496,29497],{"class":3418,"line":3569},[3416,29498,6537],{"class":3795},[3416,29500,29501],{"class":3418,"line":3574},[3416,29502,3441],{"emptyLinePlaceholder":3440},[3416,29504,29505],{"class":3418,"line":3579},[3416,29506,29507],{"class":3789},"\u002F\u002F ── Крок 2: Додавання реплік у регіони us-east-1 та ap-southeast-1 ───────────\n",[3416,29509,29510,29512,29514,29516,29518,29520,29522],{"class":3418,"line":3584},[3416,29511,6413],{"class":4368},[3416,29513,22796],{"class":6387},[3416,29515,4043],{"class":3795},[3416,29517,17498],{"class":6330},[3416,29519,6423],{"class":3795},[3416,29521,6394],{"class":4368},[3416,29523,17505],{"class":6397},[3416,29525,29526],{"class":3418,"line":3590},[3416,29527,3796],{"class":3795},[3416,29529,29530,29532,29534,29536],{"class":3418,"line":3596},[3416,29531,6437],{"class":6387},[3416,29533,6391],{"class":3795},[3416,29535,19785],{"class":3808},[3416,29537,3812],{"class":3795},[3416,29539,29540,29543,29545,29547,29549,29551,29554],{"class":3418,"line":3602},[3416,29541,29542],{"class":6387},"    ReplicaUpdates",[3416,29544,6391],{"class":3795},[3416,29546,6394],{"class":4368},[3416,29548,8640],{"class":6397},[3416,29550,5861],{"class":3795},[3416,29552,29553],{"class":6397},"ReplicationGroupUpdate",[3416,29555,6469],{"class":3795},[3416,29557,29558],{"class":3418,"line":3608},[3416,29559,6474],{"class":3795},[3416,29561,29562,29564],{"class":3418,"line":3614},[3416,29563,9886],{"class":4368},[3416,29565,17625],{"class":3795},[3416,29567,29568],{"class":3418,"line":3620},[3416,29569,8611],{"class":3795},[3416,29571,29572,29574,29576,29578,29581,29583,29586,29588,29591],{"class":3418,"line":3626},[3416,29573,17634],{"class":6387},[3416,29575,6391],{"class":3795},[3416,29577,6394],{"class":4368},[3416,29579,29580],{"class":6397}," CreateReplicationGroupMemberAction",[3416,29582,6492],{"class":3795},[3416,29584,29585],{"class":6387},"RegionName",[3416,29587,6391],{"class":3795},[3416,29589,29590],{"class":3808},"\"us-east-1\"",[3416,29592,8948],{"class":3795},[3416,29594,29595],{"class":3418,"line":3631},[3416,29596,9774],{"class":3795},[3416,29598,29599,29601],{"class":3418,"line":3636},[3416,29600,9886],{"class":4368},[3416,29602,17625],{"class":3795},[3416,29604,29605],{"class":3418,"line":3641},[3416,29606,8611],{"class":3795},[3416,29608,29609,29611,29613,29615,29617,29619,29621,29623,29626],{"class":3418,"line":3647},[3416,29610,17634],{"class":6387},[3416,29612,6391],{"class":3795},[3416,29614,6394],{"class":4368},[3416,29616,29580],{"class":6397},[3416,29618,6492],{"class":3795},[3416,29620,29585],{"class":6387},[3416,29622,6391],{"class":3795},[3416,29624,29625],{"class":3808},"\"ap-southeast-1\"",[3416,29627,8948],{"class":3795},[3416,29629,29630],{"class":3418,"line":3653},[3416,29631,8533],{"class":3795},[3416,29633,29634],{"class":3418,"line":3659},[3416,29635,4167],{"class":3795},[3416,29637,29638],{"class":3418,"line":3665},[3416,29639,6537],{"class":3795},[3416,29641,29642],{"class":3418,"line":3671},[3416,29643,3441],{"emptyLinePlaceholder":3440},[3416,29645,29646],{"class":3418,"line":3677},[3416,29647,29648],{"class":3789},"\u002F\u002F ── Отримання статусу реплікації таблиці ────────────────────────────────────\n",[3416,29650,29651,29653,29656,29658,29660,29662,29664,29666,29668,29670],{"class":3418,"line":3683},[3416,29652,6384],{"class":4368},[3416,29654,29655],{"class":6387}," tableDesc",[3416,29657,6391],{"class":3795},[3416,29659,6413],{"class":4368},[3416,29661,22796],{"class":6387},[3416,29663,4043],{"class":3795},[3416,29665,11458],{"class":6330},[3416,29667,6423],{"class":3795},[3416,29669,19785],{"class":3808},[3416,29671,11465],{"class":3795},[3416,29673,29674,29676,29679,29681,29684,29686,29688,29690,29693],{"class":3418,"line":3688},[3416,29675,6384],{"class":4368},[3416,29677,29678],{"class":6387}," replicas",[3416,29680,6391],{"class":3795},[3416,29682,29683],{"class":6387},"tableDesc",[3416,29685,4043],{"class":3795},[3416,29687,11480],{"class":6387},[3416,29689,4043],{"class":3795},[3416,29691,29692],{"class":6387},"Replicas",[3416,29694,11594],{"class":3795},[6311,29696,29697],{"label":6540},[3406,29698,29700],{"className":6543,"code":29699,"language":6545,"meta":3411,"style":3411},"Import-Module AWS.Tools.DynamoDBv2\n\n# ── Крок 1: Створення базової таблиці Orders ──────────────────────────────────\n$attrDefs = @(\n    New-DDBAttributeDefinition -AttributeName CustomerId -AttributeType S\n    New-DDBAttributeDefinition -AttributeName OrderId    -AttributeType S\n)\n$keySchema = @(\n    New-DDBKeySchemaElement -AttributeName CustomerId -KeyType HASH\n    New-DDBKeySchemaElement -AttributeName OrderId    -KeyType RANGE\n)\n$streamSpec = [Amazon.DynamoDBv2.Model.StreamSpecification]@{\n    StreamEnabled  = $true\n    StreamViewType = 'NEW_AND_OLD_IMAGES'\n}\nNew-DDBTable `\n    -TableName Orders `\n    -AttributeDefinition $attrDefs `\n    -KeySchema $keySchema `\n    -BillingMode PAY_PER_REQUEST `\n    -StreamSpecification $streamSpec `\n    -Region eu-central-1\n\n# ── Крок 2: Налаштування реплік у регіони США та Азії ──────────────────────────\n$replicaUpdates = @(\n    [Amazon.DynamoDBv2.Model.ReplicationGroupUpdate]@{\n        Create = [Amazon.DynamoDBv2.Model.CreateReplicationGroupMemberAction]@{\n            RegionName = 'us-east-1'\n        }\n    },\n    [Amazon.DynamoDBv2.Model.ReplicationGroupUpdate]@{\n        Create = [Amazon.DynamoDBv2.Model.CreateReplicationGroupMemberAction]@{\n            RegionName = 'ap-southeast-1'\n        }\n    }\n)\nUpdate-DDBTable -TableName Orders -ReplicaUpdates $replicaUpdates -Region eu-central-1\n",[3413,29701,29702,29708,29712,29717,29727,29733,29739,29743,29753,29759,29765,29769,29783,29791,29799,29803,29809,29813,29821,29829,29833,29841,29847,29851,29856,29867,29880,29896,29906,29910,29914,29926,29940,29949,29953,29957,29961],{"__ignoreMap":3411},[3416,29703,29704,29706],{"class":3418,"line":3419},[3416,29705,12967],{"class":6330},[3416,29707,12970],{"class":3795},[3416,29709,29710],{"class":3418,"line":3425},[3416,29711,3441],{"emptyLinePlaceholder":3440},[3416,29713,29714],{"class":3418,"line":3431},[3416,29715,29716],{"class":3789},"# ── Крок 1: Створення базової таблиці Orders ──────────────────────────────────\n",[3416,29718,29719,29721,29723,29725],{"class":3418,"line":3437},[3416,29720,23512],{"class":6387},[3416,29722,6391],{"class":3795},[3416,29724,6561],{"class":4368},[3416,29726,8878],{"class":3795},[3416,29728,29729,29731],{"class":3418,"line":3444},[3416,29730,23523],{"class":6330},[3416,29732,23526],{"class":3795},[3416,29734,29735,29737],{"class":3418,"line":3450},[3416,29736,23523],{"class":6330},[3416,29738,23533],{"class":3795},[3416,29740,29741],{"class":3418,"line":3456},[3416,29742,9656],{"class":3795},[3416,29744,29745,29747,29749,29751],{"class":3418,"line":3462},[3416,29746,23542],{"class":6387},[3416,29748,6391],{"class":3795},[3416,29750,6561],{"class":4368},[3416,29752,8878],{"class":3795},[3416,29754,29755,29757],{"class":3418,"line":3468},[3416,29756,23553],{"class":6330},[3416,29758,23556],{"class":3795},[3416,29760,29761,29763],{"class":3418,"line":3474},[3416,29762,23553],{"class":6330},[3416,29764,23563],{"class":3795},[3416,29766,29767],{"class":3418,"line":3480},[3416,29768,9656],{"class":3795},[3416,29770,29771,29773,29775,29777,29779,29781],{"class":3418,"line":3486},[3416,29772,25148],{"class":6387},[3416,29774,7274],{"class":3795},[3416,29776,25153],{"class":4368},[3416,29778,7280],{"class":3795},[3416,29780,6561],{"class":4368},[3416,29782,3796],{"class":3795},[3416,29784,29785,29787,29789],{"class":3418,"line":3492},[3416,29786,25164],{"class":6387},[3416,29788,6933],{"class":3795},[3416,29790,6941],{"class":4368},[3416,29792,29793,29795,29797],{"class":3418,"line":3498},[3416,29794,25173],{"class":6387},[3416,29796,6391],{"class":3795},[3416,29798,25178],{"class":3808},[3416,29800,29801],{"class":3418,"line":3504},[3416,29802,3507],{"class":3795},[3416,29804,29805,29807],{"class":3418,"line":3510},[3416,29806,11102],{"class":6330},[3416,29808,11105],{"class":3795},[3416,29810,29811],{"class":3418,"line":3515},[3416,29812,21143],{"class":3795},[3416,29814,29815,29817,29819],{"class":3418,"line":3521},[3416,29816,11115],{"class":3795},[3416,29818,23512],{"class":6387},[3416,29820,11105],{"class":3795},[3416,29822,29823,29825,29827],{"class":3418,"line":3527},[3416,29824,23590],{"class":3795},[3416,29826,23542],{"class":6387},[3416,29828,11105],{"class":3795},[3416,29830,29831],{"class":3418,"line":3533},[3416,29832,11150],{"class":3795},[3416,29834,29835,29837,29839],{"class":3418,"line":3539},[3416,29836,25197],{"class":3795},[3416,29838,25148],{"class":6387},[3416,29840,11105],{"class":3795},[3416,29842,29843,29845],{"class":3418,"line":3545},[3416,29844,21235],{"class":3795},[3416,29846,6614],{"class":3870},[3416,29848,29849],{"class":3418,"line":3551},[3416,29850,3441],{"emptyLinePlaceholder":3440},[3416,29852,29853],{"class":3418,"line":3557},[3416,29854,29855],{"class":3789},"# ── Крок 2: Налаштування реплік у регіони США та Азії ──────────────────────────\n",[3416,29857,29858,29861,29863,29865],{"class":3418,"line":3563},[3416,29859,29860],{"class":6387},"$replicaUpdates",[3416,29862,6391],{"class":3795},[3416,29864,6561],{"class":4368},[3416,29866,8878],{"class":3795},[3416,29868,29869,29871,29874,29876,29878],{"class":3418,"line":3569},[3416,29870,9496],{"class":3795},[3416,29872,29873],{"class":4368},"Amazon.DynamoDBv2.Model.ReplicationGroupUpdate",[3416,29875,7280],{"class":3795},[3416,29877,6561],{"class":4368},[3416,29879,3796],{"class":3795},[3416,29881,29882,29885,29887,29890,29892,29894],{"class":3418,"line":3574},[3416,29883,29884],{"class":6387},"        Create",[3416,29886,7274],{"class":3795},[3416,29888,29889],{"class":4368},"Amazon.DynamoDBv2.Model.CreateReplicationGroupMemberAction",[3416,29891,7280],{"class":3795},[3416,29893,6561],{"class":4368},[3416,29895,3796],{"class":3795},[3416,29897,29898,29901,29903],{"class":3418,"line":3579},[3416,29899,29900],{"class":6387},"            RegionName",[3416,29902,6391],{"class":3795},[3416,29904,29905],{"class":3808},"'us-east-1'\n",[3416,29907,29908],{"class":3418,"line":3584},[3416,29909,8533],{"class":3795},[3416,29911,29912],{"class":3418,"line":3590},[3416,29913,4442],{"class":3795},[3416,29915,29916,29918,29920,29922,29924],{"class":3418,"line":3596},[3416,29917,9496],{"class":3795},[3416,29919,29873],{"class":4368},[3416,29921,7280],{"class":3795},[3416,29923,6561],{"class":4368},[3416,29925,3796],{"class":3795},[3416,29927,29928,29930,29932,29934,29936,29938],{"class":3418,"line":3602},[3416,29929,29884],{"class":6387},[3416,29931,7274],{"class":3795},[3416,29933,29889],{"class":4368},[3416,29935,7280],{"class":3795},[3416,29937,6561],{"class":4368},[3416,29939,3796],{"class":3795},[3416,29941,29942,29944,29946],{"class":3418,"line":3608},[3416,29943,29900],{"class":6387},[3416,29945,6391],{"class":3795},[3416,29947,29948],{"class":3808},"'ap-southeast-1'\n",[3416,29950,29951],{"class":3418,"line":3614},[3416,29952,8533],{"class":3795},[3416,29954,29955],{"class":3418,"line":3620},[3416,29956,4167],{"class":3795},[3416,29958,29959],{"class":3418,"line":3626},[3416,29960,9656],{"class":3795},[3416,29962,29963,29965,29968,29970,29972],{"class":3418,"line":3631},[3416,29964,18062],{"class":6330},[3416,29966,29967],{"class":3795}," -TableName Orders -ReplicaUpdates ",[3416,29969,29860],{"class":6387},[3416,29971,6611],{"class":3795},[3416,29973,6614],{"class":3870},[3720,29975],{},[3727,29977,29979],{"id":29978},"best-practices-ефективне-проектування-схем-та-запитів","Best Practices: Ефективне проектування схем та запитів",[3353,29981,29982],{},"Для забезпечення масштабованості, передбачуваності затримок (Latency) та мінімізації фінансових витрат при роботі з Amazon DynamoDB розробник повинен дотримуватися наступних кращих практик:",[4584,29984,29986],{"id":29985},"_1-уникнення-проблеми-гарячих-партицій-hot-partitions","1. Уникнення проблеми гарячих партицій (Hot Partitions)",[3353,29988,29989,29990,29993],{},"Якщо значення Partition Key розподілені нерівномірно (наприклад, більшість запитів надсилається до одного ключа ",[3413,29991,29992],{},"Status = PENDING","), вся ємність RCU\u002FWCU для конкретної фізичної партиції може бути вичерпана, що викличе Throttling для інших клієнтів.",[3353,29995,29996,29999],{},[3363,29997,29998],{},"Рішення — Розподіл записів за допомогою солі (Write Sharding \u002F Salting):","\nДо Partition Key при записі додається випадковий суфікс (сіль) із фіксованого діапазону:",[3406,30001,30006],{"className":30002,"code":30004,"language":30005},[30003],"language-text","# Запис: PK = \"STATUS#PENDING#\" + Random(1, N)\n# Приклад: \"STATUS#PENDING#3\", \"STATUS#PENDING#12\"\n","text",[3413,30007,30004],{"__ignoreMap":3411},[3353,30009,30010,30011,30013],{},"При читанні додаток виконує N паралельних запитів (",[3413,30012,4887],{},") для кожного можливого суфікса та об'єднує результати в пам'яті.",[4584,30015,30017],{"id":30016},"_2-query-проти-scan","2. Query проти Scan",[4488,30019,30020,30026],{},[3377,30021,30022,30025],{},[3363,30023,30024],{},"Scan:"," Повністю зчитує всю таблицю, проходячи по всіх фізичних партиціях. Це операція зі складністю O(N). Вона споживає величезну кількість RCU, блокує інші запити і повинна використовуватися виключно у фонових аналітичних задачах.",[3377,30027,30028,30031],{},[3363,30029,30030],{},"Query:"," Виконує локальний пошук у межах конкретної партиції за Partition Key (складність O(1) або O(log N)). Це найбільш ефективний спосіб читання даних, який мінімізує витрати RCU.",[4584,30033,30035],{"id":30034},"_3-оптимістичне-блокування-за-допомогою-conditional-writes","3. Оптимістичне блокування за допомогою Conditional Writes",[3353,30037,30038,30039,4043],{},"Оскільки DynamoDB не підтримує класичні блокування рядків на час транзакції, для запобігання перезапису конкурентними процесами використовується оптимістичне блокування (Optimistic Locking) через атрибут версійності та ",[3413,30040,13830],{},[3406,30042,30044],{"className":6316,"code":30043,"language":6318,"meta":3411,"style":3411},"# Оновлення запису продукту лише якщо його версія збігається з очікуваною\naws dynamodb update-item \\\n    --table-name Products \\\n    --key '{\"ProductId\": {\"S\": \"prod-42\"}}' \\\n    --update-expression \"SET price = :newPrice, version = :newVer\" \\\n    --condition-expression \"version = :expectedVer\" \\\n    --expression-attribute-values '{\n        \":newPrice\": {\"N\": \"89.99\"},\n        \":newVer\": {\"N\": \"3\"},\n        \":expectedVer\": {\"N\": \"2\"}\n    }' \\\n    --region eu-central-1\n",[3413,30045,30046,30051,30061,30070,30079,30088,30098,30104,30109,30114,30119,30125],{"__ignoreMap":3411},[3416,30047,30048],{"class":3418,"line":3419},[3416,30049,30050],{"class":3789},"# Оновлення запису продукту лише якщо його версія збігається з очікуваною\n",[3416,30052,30053,30055,30057,30059],{"class":3418,"line":3425},[3416,30054,6331],{"class":6330},[3416,30056,6334],{"class":3808},[3416,30058,6988],{"class":3808},[3416,30060,6341],{"class":6340},[3416,30062,30063,30065,30068],{"class":3418,"line":3431},[3416,30064,6346],{"class":4368},[3416,30066,30067],{"class":3808}," Products",[3416,30069,6341],{"class":6340},[3416,30071,30072,30074,30077],{"class":3418,"line":3437},[3416,30073,6356],{"class":4368},[3416,30075,30076],{"class":3808}," '{\"ProductId\": {\"S\": \"prod-42\"}}'",[3416,30078,6341],{"class":6340},[3416,30080,30081,30083,30086],{"class":3418,"line":3444},[3416,30082,7011],{"class":4368},[3416,30084,30085],{"class":3808}," \"SET price = :newPrice, version = :newVer\"",[3416,30087,6341],{"class":6340},[3416,30089,30090,30093,30096],{"class":3418,"line":3450},[3416,30091,30092],{"class":4368},"    --condition-expression",[3416,30094,30095],{"class":3808}," \"version = :expectedVer\"",[3416,30097,6341],{"class":6340},[3416,30099,30100,30102],{"class":3418,"line":3456},[3416,30101,7021],{"class":4368},[3416,30103,6661],{"class":3808},[3416,30105,30106],{"class":3418,"line":3462},[3416,30107,30108],{"class":3808},"        \":newPrice\": {\"N\": \"89.99\"},\n",[3416,30110,30111],{"class":3418,"line":3468},[3416,30112,30113],{"class":3808},"        \":newVer\": {\"N\": \"3\"},\n",[3416,30115,30116],{"class":3418,"line":3474},[3416,30117,30118],{"class":3808},"        \":expectedVer\": {\"N\": \"2\"}\n",[3416,30120,30121,30123],{"class":3418,"line":3480},[3416,30122,6686],{"class":3808},[3416,30124,6341],{"class":6340},[3416,30126,30127,30129],{"class":3418,"line":3486},[3416,30128,6366],{"class":4368},[3416,30130,6369],{"class":3808},[3353,30132,30133,30134,30137],{},"Якщо інший потік змінив запис першим (версія стала 3), операція поверне ",[3413,30135,30136],{},"ConditionalCheckFailedException",", сигналізуючи про необхідність повторного зчитування та спроби оновлення.",[3348,30139,30141],{"id":30140},"частина-6-інтеграція-з-net-aws-sdk","Частина 6: Інтеграція з .NET (AWS SDK)",[3353,30143,30144,30145,30148],{},"Офіційне AWS SDK для .NET (",[3413,30146,30147],{},"AWSSDK.DynamoDBv2",") є основним інструментом для взаємодії з Amazon DynamoDB у середовищі C# та .NET. Воно розроблене з урахуванням високої продуктивності, асинхронності та підтримує різноманітні рівні абстракції, дозволяючи розробникам балансувати між швидкістю розробки та низькорівневим контролем над мережевим трафіком і структурами даних.",[3353,30150,30151],{},"У цій частині ми детально вивчимо всі складові частини SDK, починаючи від інсталяції та життєвого циклу клієнтів у контейнері DI, завершуючи складними транзакціями та обробкою потоків змін у безсерверних функціях AWS Lambda.",[3720,30153],{},[3727,30155,30157],{"id":30156},"_1-архітектурні-рівні-aws-sdk-для-net","1. Архітектурні рівні AWS SDK для .NET",[3353,30159,30160],{},"AWS SDK надає три взаємодоповнюючі моделі програмування. Кожна з них орієнтована на конкретні сценарії використання:",[30162,30163,30164],"mermaid",{},[3406,30165,30168],{"className":30166,"code":30167,"language":30162,"meta":3411,"style":3411},"language-mermaid shiki shiki-themes light-plus dark-plus dark-plus","graph TD\n    Client[\"AmazonDynamoDBClient\u003Cbr\u002F>(Low-Level API)\"]\n    DocModel[\"Table & Document\u003Cbr\u002F>(Document Model)\"]\n    OPM[\"DynamoDBContext\u003Cbr\u002F>(Object Persistence Model \u002F ORM)\"]\n\n    Client -->|Керує низькорівневими запитами| DynamoDB[(Amazon DynamoDB)]\n    DocModel -->|Обгортає клієнт| Client\n    OPM -->|Використовує під капотом| Client\n    OPM -.->|Може інтегруватися| DocModel\n",[3413,30169,30170,30175,30180,30185,30190,30194,30199,30204,30209],{"__ignoreMap":3411},[3416,30171,30172],{"class":3418,"line":3419},[3416,30173,30174],{},"graph TD\n",[3416,30176,30177],{"class":3418,"line":3425},[3416,30178,30179],{},"    Client[\"AmazonDynamoDBClient\u003Cbr\u002F>(Low-Level API)\"]\n",[3416,30181,30182],{"class":3418,"line":3431},[3416,30183,30184],{},"    DocModel[\"Table & Document\u003Cbr\u002F>(Document Model)\"]\n",[3416,30186,30187],{"class":3418,"line":3437},[3416,30188,30189],{},"    OPM[\"DynamoDBContext\u003Cbr\u002F>(Object Persistence Model \u002F ORM)\"]\n",[3416,30191,30192],{"class":3418,"line":3444},[3416,30193,3441],{"emptyLinePlaceholder":3440},[3416,30195,30196],{"class":3418,"line":3450},[3416,30197,30198],{},"    Client -->|Керує низькорівневими запитами| DynamoDB[(Amazon DynamoDB)]\n",[3416,30200,30201],{"class":3418,"line":3456},[3416,30202,30203],{},"    DocModel -->|Обгортає клієнт| Client\n",[3416,30205,30206],{"class":3418,"line":3462},[3416,30207,30208],{},"    OPM -->|Використовує під капотом| Client\n",[3416,30210,30211],{"class":3418,"line":3468},[3416,30212,30213],{},"    OPM -.->|Може інтегруватися| DocModel\n",[4001,30215,30216,30242,30270],{},[4004,30217,30221,10466,30224,30227,30229,30232,30233,4043,30236,30238,30241],{"icon":30218,"title":30219,"color":30220},"i-heroicons-cpu-chip","Low-Level API","primary",[3363,30222,30223],{},"Клас:",[3413,30225,30226],{},"AmazonDynamoDBClient",[4628,30228],{},[3363,30230,30231],{},"Суть:"," Найближчий до HTTP-протоколу рівень. Усі типу даних та структури передаються у вигляді сирих словників ",[3413,30234,30235],{},"Dictionary\u003Cstring, AttributeValue>",[4628,30237],{},[3363,30239,30240],{},"Переваги:"," Повний контроль, нульовий оверхед, доступ до 100% можливостей API (транзакції, batch-операції, тюнінг запитів).",[4004,30243,30247,10466,30249,14345,30251,30254,30256,30258,30259,30261,30262,30264,30265,30267,30269],{"icon":30244,"title":30245,"color":30246},"i-heroicons-document-text","Document Model","neutral",[3363,30248,30223],{},[3413,30250,11480],{},[3413,30252,30253],{},"Document",[4628,30255],{},[3363,30257,30231],{}," Проміжний безсхемний (schemaless) рівень. Замість явного використання ",[3413,30260,6466],{}," робота відбувається з динамічними об'єктами ",[3413,30263,30253],{},", що спрощує зчитування та запис.",[4628,30266],{},[3363,30268,30240],{}," Швидка JSON-серіалізація, легка робота з динамічними даними без опису C# класів.",[4004,30271,30275,10466,30277,30280,30282,30284,30285,30287,30289],{"icon":30272,"title":30273,"color":30274},"i-heroicons-cube","Object Persistence Model","amber",[3363,30276,30223],{},[3413,30278,30279],{},"DynamoDBContext",[4628,30281],{},[3363,30283,30231],{}," Декларативний ORM-подібний рівень. SDK автоматично перетворює POCO (Plain Old CLR Objects) на записи таблиць на основі атрибутів класу.",[4628,30286],{},[3363,30288,30240],{}," Декларативне проектування, мінімум коду, висока типізація та безпека типів на рівні компіляції.",[4584,30291,30293],{"id":30292},"порівняльна-матриця-рівнів-абстракції","Порівняльна матриця рівнів абстракції",[3756,30295,30296,30309],{},[4617,30297,30298],{},[4620,30299,30300,30302,30304,30306],{},[4623,30301,6186],{"align":4625},[4623,30303,30219],{"align":4625},[4623,30305,30245],{"align":4625},[4623,30307,30308],{"align":4625},"Object Persistence Model (OPM)",[4657,30310,30311,30327,30343,30366,30382,30397],{},[4620,30312,30313,30318,30321,30324],{},[4662,30314,30315],{"align":4625},[3363,30316,30317],{},"Швидкість розробки",[4662,30319,30320],{"align":4625},"Низька (багато бойлерплейту)",[4662,30322,30323],{"align":4625},"Середня",[4662,30325,30326],{"align":4625},"Висока (декларативний підхід)",[4620,30328,30329,30334,30337,30340],{},[4662,30330,30331],{"align":4625},[3363,30332,30333],{},"Продуктивність",[4662,30335,30336],{"align":4625},"Максимальна (без додаткового мапінгу)",[4662,30338,30339],{"align":4625},"Висока",[4662,30341,30342],{"align":4625},"Злегка знижена через рефлексію",[4620,30344,30345,30350,30355,30363],{},[4662,30346,30347],{"align":4625},[3363,30348,30349],{},"Типізація",[4662,30351,30352,30353],{"align":4625},"Словники та ",[3413,30354,6466],{},[4662,30356,30357,30358,4384,30360,6259],{"align":4625},"Динамічні типи (",[3413,30359,30253],{},[3413,30361,30362],{},"Primitive",[4662,30364,30365],{"align":4625},"Строга типізація (POCO класи)",[4620,30367,30368,30373,30376,30379],{},[4662,30369,30370],{"align":4625},[3363,30371,30372],{},"Контроль запитів",[4662,30374,30375],{"align":4625},"Повний контроль над схемами та фільтрами",[4662,30377,30378],{"align":4625},"Частковий контроль",[4662,30380,30381],{"align":4625},"Обмежений абстракціями контексту",[4620,30383,30384,30388,30391,30394],{},[4662,30385,30386],{"align":4625},[3363,30387,2770],{},[4662,30389,30390],{"align":4625},"Підтримуються повністю",[4662,30392,30393],{"align":4625},"Не підтримуються напряму",[4662,30395,30396],{"align":4625},"Підтримуються обмежено",[4620,30398,30399,30404,30407,30410],{},[4662,30400,30401],{"align":4625},[3363,30402,30403],{},"Ідеально для...",[4662,30405,30406],{"align":4625},"Системних утиліт, складних запитів",[4662,30408,30409],{"align":4625},"JSON API, динамічних схем",[4662,30411,30412],{"align":4625},"Бізнес-сутностей та CRUD-сервісів",[3720,30414],{},[3727,30416,30418],{"id":30417},"_2-встановлення-конфігурація-та-dependency-injection","2. Встановлення, конфігурація та Dependency Injection",[3353,30420,30421],{},"Перед початком роботи необхідно підключити відповідні інструменти з екосистеми NuGet.",[4584,30423,30425],{"id":30424},"крок-1-встановлення-nuget-пакетів","Крок 1: Встановлення NuGet-пакетів",[3353,30427,30428],{},"Для роботи з клієнтом та DI у сучасних .NET 8+ додатках потрібні такі пакети:",[3406,30430,30433],{"className":6316,"code":30431,"language":6318,"meta":30432,"style":3411},"# Основна бібліотека клієнта DynamoDB\ndotnet add package AWSSDK.DynamoDBv2\n\n# Розширення для інтеграції з .NET Core Dependency Injection\ndotnet add package AWSSDK.Extensions.NETCore.Setup\n","showLineNumbers",[3413,30434,30435,30440,30454,30458,30463],{"__ignoreMap":3411},[3416,30436,30437],{"class":3418,"line":3419},[3416,30438,30439],{"class":3789},"# Основна бібліотека клієнта DynamoDB\n",[3416,30441,30442,30445,30448,30451],{"class":3418,"line":3425},[3416,30443,30444],{"class":6330},"dotnet",[3416,30446,30447],{"class":3808}," add",[3416,30449,30450],{"class":3808}," package",[3416,30452,30453],{"class":3808}," AWSSDK.DynamoDBv2\n",[3416,30455,30456],{"class":3418,"line":3431},[3416,30457,3441],{"emptyLinePlaceholder":3440},[3416,30459,30460],{"class":3418,"line":3437},[3416,30461,30462],{"class":3789},"# Розширення для інтеграції з .NET Core Dependency Injection\n",[3416,30464,30465,30467,30469,30471],{"class":3418,"line":3444},[3416,30466,30444],{"class":6330},[3416,30468,30447],{"class":3808},[3416,30470,30450],{"class":3808},[3416,30472,30473],{"class":3808}," AWSSDK.Extensions.NETCore.Setup\n",[4584,30475,30477,30478],{"id":30476},"крок-2-налаштування-файлу-конфігурації-appsettingsjson","Крок 2: Налаштування файлу конфігурації ",[3413,30479,30480],{},"appsettings.json",[3353,30482,30483,30484,30487],{},"Параметри доступу до хмари AWS зазвичай зберігаються у конфігураційному файлі. Розділ ",[3413,30485,30486],{},"\"AWS\""," зчитується автоматично розширенням SDK:",[3406,30489,30491],{"className":3780,"code":30490,"language":3782,"meta":30432,"style":3411},"{\n  \"AWS\": {\n    \"Region\": \"eu-central-1\",\n    \"Profile\": \"default\"\n  }\n}\n",[3413,30492,30493,30497,30504,30516,30526,30531],{"__ignoreMap":3411},[3416,30494,30495],{"class":3418,"line":3419},[3416,30496,3796],{"class":3795},[3416,30498,30499,30502],{"class":3418,"line":3425},[3416,30500,30501],{"class":3801},"  \"AWS\"",[3416,30503,4403],{"class":3795},[3416,30505,30506,30509,30511,30514],{"class":3418,"line":3431},[3416,30507,30508],{"class":3801},"    \"Region\"",[3416,30510,3805],{"class":3795},[3416,30512,30513],{"class":3808},"\"eu-central-1\"",[3416,30515,3812],{"class":3795},[3416,30517,30518,30521,30523],{"class":3418,"line":3437},[3416,30519,30520],{"class":3801},"    \"Profile\"",[3416,30522,3805],{"class":3795},[3416,30524,30525],{"class":3808},"\"default\"\n",[3416,30527,30528],{"class":3418,"line":3444},[3416,30529,30530],{"class":3795},"  }\n",[3416,30532,30533],{"class":3418,"line":3450},[3416,30534,3507],{"class":3795},[22319,30536,30537],{},[3353,30538,30539,30542,30543,30546,30547,4039,30550,4043],{},[3416,30540,30541],{},"!NOTE","\nУ хмарному середовищі AWS (наприклад, у контейнерах ECS\u002FEKS або Lambda-функціях) вказувати ",[3413,30544,30545],{},"Profile"," не потрібно. SDK автоматично отримає тимчасові Credentials через механізм ",[3363,30548,30549],{},"IAM Roles for Tasks",[3363,30551,30552],{},"Execution Role",[4584,30554,30556],{"id":30555},"крок-3-реєстрація-у-контейнері-dependency-injection-di","Крок 3: Реєстрація у контейнері Dependency Injection (DI)",[3353,30558,30559,30560,10458],{},"Для правильного керування життєвим циклом підключень клієнтські сервіси реєструються у ",[3413,30561,30562],{},"Program.cs",[3406,30564,30566],{"className":6375,"code":30565,"language":6377,"meta":30432,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.DataModel;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n\u002F\u002F 1. Зчитування та реєстрація опцій AWS\nvar awsOptions = builder.Configuration.GetAWSOptions();\nbuilder.Services.AddDefaultAWSOptions(awsOptions);\n\n\u002F\u002F 2. Реєстрація IAmazonDynamoDB (Singleton за замовчуванням)\nbuilder.Services.AddAWSService\u003CIAmazonDynamoDB>();\n\n\u002F\u002F 3. Реєстрація IDynamoDBContext (ORM контекст - зазвичай Scoped)\nbuilder.Services.AddScoped\u003CIDynamoDBContext, DynamoDBContext>();\n",[3413,30567,30568,30580,30597,30601,30625,30629,30634,30658,30679,30683,30688,30709,30713,30718],{"__ignoreMap":3411},[3416,30569,30570,30572,30574,30576,30578],{"class":3418,"line":3419},[3416,30571,17433],{"class":11427},[3416,30573,17436],{"class":6397},[3416,30575,4043],{"class":3795},[3416,30577,17441],{"class":6397},[3416,30579,11594],{"class":3795},[3416,30581,30582,30584,30586,30588,30590,30592,30595],{"class":3418,"line":3425},[3416,30583,17433],{"class":11427},[3416,30585,17436],{"class":6397},[3416,30587,4043],{"class":3795},[3416,30589,17441],{"class":6397},[3416,30591,4043],{"class":3795},[3416,30593,30594],{"class":6397},"DataModel",[3416,30596,11594],{"class":3795},[3416,30598,30599],{"class":3418,"line":3431},[3416,30600,3441],{"emptyLinePlaceholder":3440},[3416,30602,30603,30605,30608,30610,30613,30615,30618,30620,30623],{"class":3418,"line":3437},[3416,30604,6384],{"class":4368},[3416,30606,30607],{"class":6387}," builder",[3416,30609,6391],{"class":3795},[3416,30611,30612],{"class":6387},"WebApplication",[3416,30614,4043],{"class":3795},[3416,30616,30617],{"class":6330},"CreateBuilder",[3416,30619,6423],{"class":3795},[3416,30621,30622],{"class":6387},"args",[3416,30624,11465],{"class":3795},[3416,30626,30627],{"class":3418,"line":3444},[3416,30628,3441],{"emptyLinePlaceholder":3440},[3416,30630,30631],{"class":3418,"line":3450},[3416,30632,30633],{"class":3789},"\u002F\u002F 1. Зчитування та реєстрація опцій AWS\n",[3416,30635,30636,30638,30641,30643,30646,30648,30651,30653,30656],{"class":3418,"line":3456},[3416,30637,6384],{"class":4368},[3416,30639,30640],{"class":6387}," awsOptions",[3416,30642,6391],{"class":3795},[3416,30644,30645],{"class":6387},"builder",[3416,30647,4043],{"class":3795},[3416,30649,30650],{"class":6387},"Configuration",[3416,30652,4043],{"class":3795},[3416,30654,30655],{"class":6330},"GetAWSOptions",[3416,30657,6401],{"class":3795},[3416,30659,30660,30662,30664,30667,30669,30672,30674,30677],{"class":3418,"line":3462},[3416,30661,30645],{"class":6387},[3416,30663,4043],{"class":3795},[3416,30665,30666],{"class":6387},"Services",[3416,30668,4043],{"class":3795},[3416,30670,30671],{"class":6330},"AddDefaultAWSOptions",[3416,30673,6423],{"class":3795},[3416,30675,30676],{"class":6387},"awsOptions",[3416,30678,11465],{"class":3795},[3416,30680,30681],{"class":3418,"line":3468},[3416,30682,3441],{"emptyLinePlaceholder":3440},[3416,30684,30685],{"class":3418,"line":3474},[3416,30686,30687],{"class":3789},"\u002F\u002F 2. Реєстрація IAmazonDynamoDB (Singleton за замовчуванням)\n",[3416,30689,30690,30692,30694,30696,30698,30701,30703,30706],{"class":3418,"line":3480},[3416,30691,30645],{"class":6387},[3416,30693,4043],{"class":3795},[3416,30695,30666],{"class":6387},[3416,30697,4043],{"class":3795},[3416,30699,30700],{"class":6330},"AddAWSService",[3416,30702,5861],{"class":3795},[3416,30704,30705],{"class":6397},"IAmazonDynamoDB",[3416,30707,30708],{"class":3795},">();\n",[3416,30710,30711],{"class":3418,"line":3486},[3416,30712,3441],{"emptyLinePlaceholder":3440},[3416,30714,30715],{"class":3418,"line":3492},[3416,30716,30717],{"class":3789},"\u002F\u002F 3. Реєстрація IDynamoDBContext (ORM контекст - зазвичай Scoped)\n",[3416,30719,30720,30722,30724,30726,30728,30731,30733,30736,30738,30740],{"class":3418,"line":3498},[3416,30721,30645],{"class":6387},[3416,30723,4043],{"class":3795},[3416,30725,30666],{"class":6387},[3416,30727,4043],{"class":3795},[3416,30729,30730],{"class":6330},"AddScoped",[3416,30732,5861],{"class":3795},[3416,30734,30735],{"class":6397},"IDynamoDBContext",[3416,30737,4384],{"class":3795},[3416,30739,30279],{"class":6397},[3416,30741,30708],{"class":3795},[22319,30743,30744],{},[3353,30745,30746,30748,30749,30751,30752,30755,30756,30759,30760,30763,30764,30766,30767,4039,30770,4043],{},[3416,30747,27452],{},"\nКлієнт ",[3413,30750,30226],{}," реалізує ",[3413,30753,30754],{},"IDisposable"," та утримує внутрішній пул з'єднань (",[3413,30757,30758],{},"HttpClient","). Його обов'язково потрібно реєструвати як ",[3363,30761,30762],{},"Singleton",", оскільки створення нового клієнта на кожен запит призведе до вичерпання TCP-сокетів під навантаженням (Socket Exhaustion). Контекст ",[3413,30765,30279],{}," є легкою обгорткою над клієнтом і реєструється як ",[3363,30768,30769],{},"Scoped",[3363,30771,30772],{},"Transient",[4584,30774,30776],{"id":30775},"крок-4-локальна-розробка-та-перевизначення-serviceurl","Крок 4: Локальна розробка та перевизначення ServiceURL",[3353,30778,30779,30780,4039,30783,30786],{},"При використанні локального емулятора (наприклад, ",[3363,30781,30782],{},"LocalStack",[3363,30784,30785],{},"DynamoDB Local",") необхідно обійти стандартну маршрутизацію AWS:",[3406,30788,30790],{"className":6375,"code":30789,"language":6377,"meta":30432,"style":3411},"if (builder.Environment.IsDevelopment())\n{\n    builder.Services.AddSingleton\u003CIAmazonDynamoDB>(sp =>\n    {\n        var config = new AmazonDynamoDBConfig\n        {\n            ServiceURL = \"http:\u002F\u002Flocalhost:8000\", \u002F\u002F Стандартний порт DynamoDB Local\n            UseHttp = true\n        };\n        return new AmazonDynamoDBClient(config);\n    });\n}\n",[3413,30791,30792,30814,30818,30845,30849,30864,30868,30883,30893,30898,30915,30920],{"__ignoreMap":3411},[3416,30793,30794,30797,30799,30801,30803,30806,30808,30811],{"class":3418,"line":3419},[3416,30795,30796],{"class":11427},"if",[3416,30798,11431],{"class":3795},[3416,30800,30645],{"class":6387},[3416,30802,4043],{"class":3795},[3416,30804,30805],{"class":6387},"Environment",[3416,30807,4043],{"class":3795},[3416,30809,30810],{"class":6330},"IsDevelopment",[3416,30812,30813],{"class":3795},"())\n",[3416,30815,30816],{"class":3418,"line":3425},[3416,30817,3796],{"class":3795},[3416,30819,30820,30823,30825,30827,30829,30832,30834,30836,30839,30842],{"class":3418,"line":3431},[3416,30821,30822],{"class":6387},"    builder",[3416,30824,4043],{"class":3795},[3416,30826,30666],{"class":6387},[3416,30828,4043],{"class":3795},[3416,30830,30831],{"class":6330},"AddSingleton",[3416,30833,5861],{"class":3795},[3416,30835,30705],{"class":6397},[3416,30837,30838],{"class":3795},">(",[3416,30840,30841],{"class":6387},"sp",[3416,30843,30844],{"class":3795}," =>\n",[3416,30846,30847],{"class":3418,"line":3437},[3416,30848,6474],{"class":3795},[3416,30850,30851,30854,30857,30859,30861],{"class":3418,"line":3444},[3416,30852,30853],{"class":4368},"        var",[3416,30855,30856],{"class":6387}," config",[3416,30858,6391],{"class":3795},[3416,30860,6394],{"class":4368},[3416,30862,30863],{"class":6397}," AmazonDynamoDBConfig\n",[3416,30865,30866],{"class":3418,"line":3450},[3416,30867,8611],{"class":3795},[3416,30869,30870,30873,30875,30878,30880],{"class":3418,"line":3456},[3416,30871,30872],{"class":6387},"            ServiceURL",[3416,30874,6391],{"class":3795},[3416,30876,30877],{"class":3808},"\"http:\u002F\u002Flocalhost:8000\"",[3416,30879,4384],{"class":3795},[3416,30881,30882],{"class":3789},"\u002F\u002F Стандартний порт DynamoDB Local\n",[3416,30884,30885,30888,30890],{"class":3418,"line":3462},[3416,30886,30887],{"class":6387},"            UseHttp",[3416,30889,6391],{"class":3795},[3416,30891,30892],{"class":4368},"true\n",[3416,30894,30895],{"class":3418,"line":3468},[3416,30896,30897],{"class":3795},"        };\n",[3416,30899,30900,30903,30906,30908,30910,30913],{"class":3418,"line":3474},[3416,30901,30902],{"class":11427},"        return",[3416,30904,30905],{"class":4368}," new",[3416,30907,6398],{"class":6397},[3416,30909,6423],{"class":3795},[3416,30911,30912],{"class":6387},"config",[3416,30914,11465],{"class":3795},[3416,30916,30917],{"class":3418,"line":3480},[3416,30918,30919],{"class":3795},"    });\n",[3416,30921,30922],{"class":3418,"line":3486},[3416,30923,3507],{"class":3795},[4584,30925,30927],{"id":30926},"конфігурація-клієнта-amazondynamodbconfig","Конфігурація клієнта (AmazonDynamoDBConfig)",[3353,30929,30930,30931,30934,30935,30938],{},"Клас ",[3413,30932,30933],{},"AmazonDynamoDBConfig"," (успадкований від ",[3413,30936,30937],{},"AmazonServiceClientConfig",") дозволяє гнучко налаштувати поведінку HTTP-клієнта та правила взаємодії з AWS.",[24357,30940,30941,30946,30955,30963,30967,30971],{},[24360,30942,30945],{"name":30943,"type":6461,"default":30944},"ServiceURL","null","Дозволяє перевизначити базову URL-адресу для запитів. Корисно для підключення до локальних емуляторів (LocalStack, DynamoDB Local).",[24360,30947,30948,30949,30952,30953,4043],{"name":22812,"type":22812,"default":30944},"Вказує географічний регіон AWS (наприклад, ",[3413,30950,30951],{},"RegionEndpoint.EUCentral1","), до якого надсилатимуться запити, якщо не вказано ",[3413,30954,30943],{},[24360,30956,30959,30960,30962],{"name":30957,"type":30958,"default":4042},"UseHttp","bool","Якщо встановлено ",[3413,30961,4038],{},", SDK використовуватиме протокол HTTP замість HTTPS (корисно для локального тестування).",[24360,30964,30966],{"name":30965,"type":28530,"default":25017},"MaxErrorRetry","Максимальна кількість автоматичних повторних спроб (retries) при отриманні тимчасових помилок від DynamoDB або проблем із мережею.",[24360,30968,30970],{"name":30969,"type":28530,"default":17819},"ConnectionLimit","Максимальна кількість одночасних TCP-з'єднань, які HTTP-клієнт може відкривати до DynamoDB. Рекомендується збільшувати для високонавантажених систем.",[24360,30972,30976],{"name":30973,"type":30974,"default":30975},"Timeout","TimeSpan","100 seconds","Максимальний час очікування відповіді на HTTP-запит.",[3720,30978],{},[3727,30980,30982],{"id":30981},"_3-low-level-api-робота-на-рівні-байтів-та-протоколу","3. Low-Level API: Робота на рівні байтів та протоколу",[3353,30984,30985,30987,30988,30990,30991,30993],{},[3363,30986,30219],{}," надає прямий доступ до викликів JSON-інтерфейсу DynamoDB через клас ",[3413,30989,30226],{},". Основною структурою даних тут є ",[3413,30992,6466],{},", яка реалізує паттерн Union Type для опису типів колонок БД.",[4584,30995,30997],{"id":30996},"ключовий-клас-amazondynamodbclient","Ключовий клас: AmazonDynamoDBClient",[3353,30999,31000,31001,4043],{},"Це центральний клас низькорівневого доступу, який безпосередньо надсилає HTTP-запити до AWS API. Усі методи є асинхронними та приймають відповідний об'єкт ",[3413,31002,31003],{},"*Request",[24357,31005,31006,31017,31023,31029,31035,31041,31047,31053,31059,31065],{},[24360,31007,31009,31010,31013,31014,4043],{"name":6420,"type":31008},"Method","Отримує один елемент за його точним первинним ключем (HASH або HASH+RANGE). Приймає ",[3413,31011,31012],{},"GetItemRequest"," та повертає ",[3413,31015,31016],{},"GetItemResponse",[24360,31018,31019,31020,4043],{"name":6718,"type":31008},"Записує новий елемент або повністю перезаписує існуючий. Приймає ",[3413,31021,31022],{},"PutItemRequest",[24360,31024,31025,31026,4043],{"name":7069,"type":31008},"Модифікує окремі атрибути існуючого елемента без повного перезапису сутності. Підтримує умовні вирази. Приймає ",[3413,31027,31028],{},"UpdateItemRequest",[24360,31030,31031,31032,4043],{"name":7480,"type":31008},"Видаляє елемент за первинним ключем. Приймає ",[3413,31033,31034],{},"DeleteItemRequest",[24360,31036,31037,31038,4043],{"name":7748,"type":31008},"Шукає елементи в межах однієї партиції (Partition Key). Дозволяє фільтрувати за сортувальним ключем (Sort Key). Приймає ",[3413,31039,31040],{},"QueryRequest",[24360,31042,31043,31044,4043],{"name":8056,"type":31008},"Повністю сканує всю таблицю, проходячи по всіх фізичних партиціях. Вкрай неефективний для великих таблиць. Приймає ",[3413,31045,31046],{},"ScanRequest",[24360,31048,31049,31050,4043],{"name":8569,"type":31008},"Пакетне зчитування до 100 елементів за один виклик. Приймає ",[3413,31051,31052],{},"BatchGetItemRequest",[24360,31054,31055,31056,4043],{"name":9143,"type":31008},"Пакетний запис або видалення до 25 елементів за один виклик. Приймає ",[3413,31057,31058],{},"BatchWriteItemRequest",[24360,31060,31061,31062,4043],{"name":26531,"type":31008},"Транзакційне читання кількох елементів з гарантіями ACID. Приймає ",[3413,31063,31064],{},"TransactGetItemsRequest",[24360,31066,31067,31068,4043],{"name":9848,"type":31008},"Транзакційний запис\u002Fоновлення\u002Fвидалення з гарантіями ACID (до 100 елементів). Приймає ",[3413,31069,31070],{},"TransactWriteItemsRequest",[4584,31072,31074,31075],{"id":31073},"опис-властивостей-класу-attributevalue","Опис властивостей класу ",[3413,31076,6466],{},[3353,31078,30930,31079,31081],{},[3413,31080,6466],{}," містить властивості для кожного підтримуваного типу даних DynamoDB. На рівні SDK це виглядає так:",[24357,31083,31084,31087,31090,31097,31105,31110,31114,31119,31123,31128],{},[24360,31085,31086],{"name":6495,"type":6461,"default":30944},"Рядковий тип даних (String). Зберігає текстові дані (наприклад, UUID, дати у форматі ISO 8601).",[24360,31088,31089],{"name":10168,"type":6461,"default":30944},"Числовий тип даних (Number). Передається виключно як рядок C# для запобігання втрати точності чисел з плаваючою крапкою.",[24360,31091,31092,31093,4039,31095,4043],{"name":6850,"type":30958,"default":4042},"Логічний тип (Boolean). Приймає ",[3413,31094,4038],{},[3413,31096,4042],{},[24360,31098,31101,31102,31104],{"name":31099,"type":31100,"default":30944},"B","MemoryStream","Бінарні дані (Binary). Приймає потік байтів ",[3413,31103,31100],{}," (наприклад, для серіалізованих protobuf-файлів).",[24360,31106,31109],{"name":31107,"type":31108,"default":30944},"SS","List\u003Cstring>","Набір рядків (String Set). Список унікальних текстових значень.",[24360,31111,31113],{"name":31112,"type":31108,"default":30944},"NS","Набір чисел (Number Set). Список унікальних чисел у форматі рядків C#.",[24360,31115,31118],{"name":31116,"type":31117,"default":30944},"BS","List\u003CMemoryStream>","Набір бінарних даних (Binary Set).",[24360,31120,31122],{"name":31121,"type":30235,"default":30944},"M","Карта\u002FСловник (Map). Дозволяє створювати глибокі ієрархічні структури (JSON-подібні).",[24360,31124,31127],{"name":31125,"type":31126,"default":30944},"L","List\u003CAttributeValue>","Список (List). Впорядкований масив елементів будь-яких типів.",[24360,31129,31131],{"name":31130,"type":30958,"default":4042},"NULL","Визначає пусте значення (Null).",[4584,31133,31135],{"id":31134},"crud-операції-через-low-level-api","CRUD-операції через Low-Level API",[3353,31137,31138],{},"Розглянемо приклад реалізації записів, зчитування та оновлення через прямі HTTP-запити:",[3406,31140,31142],{"className":6375,"code":31141,"language":6377,"meta":30432,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\npublic class LowLevelRepository\n{\n    private readonly IAmazonDynamoDB _client;\n    private const string TableName = \"Products\";\n\n    public LowLevelRepository(IAmazonDynamoDB client) => _client = client;\n\n    \u002F\u002F ── PutItem: Запис нового елемента ──────────────────────────────────────────\n    public async Task CreateProductAsync(string categoryId, string sku, string name, decimal price)\n    {\n        var request = new PutItemRequest\n        {\n            TableName = TableName,\n            Item = new Dictionary\u003Cstring, AttributeValue>\n            {\n                { \"CategoryId\", new AttributeValue { S = categoryId } },\n                { \"Sku\", new AttributeValue { S = sku } },\n                { \"Name\", new AttributeValue { S = name } },\n                { \"Price\", new AttributeValue { N = price.ToString(\"F2\") } },\n                { \"IsAvailable\", new AttributeValue { BOOL = true } }\n            }\n        };\n\n        await _client.PutItemAsync(request);\n    }\n\n    \u002F\u002F ── GetItem: Точкове зчитування елемента за HASH та RANGE ─────────────────────\n    public async Task\u003CDictionary\u003Cstring, AttributeValue>?> GetProductAsync(string categoryId, string sku)\n    {\n        var request = new GetItemRequest\n        {\n            TableName = TableName,\n            Key = new Dictionary\u003Cstring, AttributeValue>\n            {\n                { \"CategoryId\", new AttributeValue { S = categoryId } },\n                { \"Sku\", new AttributeValue { S = sku } }\n            },\n            ConsistentRead = true \u002F\u002F Strongly Consistent Read\n        };\n\n        var response = await _client.GetItemAsync(request);\n        return response.IsItemSet ? response.Item : null;\n    }\n\n    \u002F\u002F ── UpdateItem: Оновлення окремого атрибута за виразом (Update Expression) ───\n    public async Task UpdatePriceAsync(string categoryId, string sku, decimal newPrice)\n    {\n        var request = new UpdateItemRequest\n        {\n            TableName = TableName,\n            Key = new Dictionary\u003Cstring, AttributeValue>\n            {\n                { \"CategoryId\", new AttributeValue { S = categoryId } },\n                { \"Sku\", new AttributeValue { S = sku } }\n            },\n            \u002F\u002F Вираз оновлення: встановлюємо нову ціну та дату\n            UpdateExpression = \"SET Price = :newPrice, UpdatedAt = :ts\",\n            ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n            {\n                { \":newPrice\", new AttributeValue { N = newPrice.ToString(\"F2\") } },\n                { \":ts\", new AttributeValue { S = DateTime.UtcNow.ToString(\"O\") } }\n            }\n        };\n\n        await _client.UpdateItemAsync(request);\n    }\n}\n",[3413,31143,31144,31156,31172,31176,31187,31191,31207,31227,31231,31258,31262,31267,31310,31314,31327,31331,31342,31362,31366,31391,31415,31439,31473,31496,31500,31504,31508,31526,31530,31534,31539,31579,31583,31595,31599,31609,31629,31633,31655,31677,31681,31693,31697,31701,31723,31752,31756,31760,31765,31797,31801,31813,31817,31827,31847,31851,31873,31895,31899,31904,31915,31935,31939,31971,32008,32012,32016,32020,32036,32040],{"__ignoreMap":3411},[3416,31145,31146,31148,31150,31152,31154],{"class":3418,"line":3419},[3416,31147,17433],{"class":11427},[3416,31149,17436],{"class":6397},[3416,31151,4043],{"class":3795},[3416,31153,17441],{"class":6397},[3416,31155,11594],{"class":3795},[3416,31157,31158,31160,31162,31164,31166,31168,31170],{"class":3418,"line":3425},[3416,31159,17433],{"class":11427},[3416,31161,17436],{"class":6397},[3416,31163,4043],{"class":3795},[3416,31165,17441],{"class":6397},[3416,31167,4043],{"class":3795},[3416,31169,17458],{"class":6397},[3416,31171,11594],{"class":3795},[3416,31173,31174],{"class":3418,"line":3431},[3416,31175,3441],{"emptyLinePlaceholder":3440},[3416,31177,31178,31181,31184],{"class":3418,"line":3437},[3416,31179,31180],{"class":4368},"public",[3416,31182,31183],{"class":4368}," class",[3416,31185,31186],{"class":6397}," LowLevelRepository\n",[3416,31188,31189],{"class":3418,"line":3444},[3416,31190,3796],{"class":3795},[3416,31192,31193,31196,31199,31202,31205],{"class":3418,"line":3450},[3416,31194,31195],{"class":4368},"    private",[3416,31197,31198],{"class":4368}," readonly",[3416,31200,31201],{"class":6397}," IAmazonDynamoDB",[3416,31203,31204],{"class":6387}," _client",[3416,31206,11594],{"class":3795},[3416,31208,31209,31211,31214,31217,31220,31222,31225],{"class":3418,"line":3456},[3416,31210,31195],{"class":4368},[3416,31212,31213],{"class":4368}," const",[3416,31215,31216],{"class":4368}," string",[3416,31218,31219],{"class":6387}," TableName",[3416,31221,6391],{"class":3795},[3416,31223,31224],{"class":3808},"\"Products\"",[3416,31226,11594],{"class":3795},[3416,31228,31229],{"class":3418,"line":3462},[3416,31230,3441],{"emptyLinePlaceholder":3440},[3416,31232,31233,31236,31239,31241,31243,31245,31248,31251,31253,31256],{"class":3418,"line":3468},[3416,31234,31235],{"class":4368},"    public",[3416,31237,31238],{"class":6330}," LowLevelRepository",[3416,31240,6423],{"class":3795},[3416,31242,30705],{"class":6397},[3416,31244,6388],{"class":6387},[3416,31246,31247],{"class":3795},") => ",[3416,31249,31250],{"class":6387},"_client",[3416,31252,6391],{"class":3795},[3416,31254,31255],{"class":6387},"client",[3416,31257,11594],{"class":3795},[3416,31259,31260],{"class":3418,"line":3474},[3416,31261,3441],{"emptyLinePlaceholder":3440},[3416,31263,31264],{"class":3418,"line":3480},[3416,31265,31266],{"class":3789},"    \u002F\u002F ── PutItem: Запис нового елемента ──────────────────────────────────────────\n",[3416,31268,31269,31271,31274,31276,31279,31281,31283,31286,31288,31290,31293,31295,31297,31300,31302,31305,31308],{"class":3418,"line":3486},[3416,31270,31235],{"class":4368},[3416,31272,31273],{"class":4368}," async",[3416,31275,11606],{"class":6397},[3416,31277,31278],{"class":6330}," CreateProductAsync",[3416,31280,6423],{"class":3795},[3416,31282,6461],{"class":4368},[3416,31284,31285],{"class":6387}," categoryId",[3416,31287,4384],{"class":3795},[3416,31289,6461],{"class":4368},[3416,31291,31292],{"class":6387}," sku",[3416,31294,4384],{"class":3795},[3416,31296,6461],{"class":4368},[3416,31298,31299],{"class":6387}," name",[3416,31301,4384],{"class":3795},[3416,31303,31304],{"class":4368},"decimal",[3416,31306,31307],{"class":6387}," price",[3416,31309,9656],{"class":3795},[3416,31311,31312],{"class":3418,"line":3492},[3416,31313,6474],{"class":3795},[3416,31315,31316,31318,31321,31323,31325],{"class":3418,"line":3498},[3416,31317,30853],{"class":4368},[3416,31319,31320],{"class":6387}," request",[3416,31322,6391],{"class":3795},[3416,31324,6394],{"class":4368},[3416,31326,6725],{"class":6397},[3416,31328,31329],{"class":3418,"line":3504},[3416,31330,8611],{"class":3795},[3416,31332,31333,31335,31337,31340],{"class":3418,"line":3510},[3416,31334,10247],{"class":6387},[3416,31336,6391],{"class":3795},[3416,31338,31339],{"class":6387},"TableName",[3416,31341,3812],{"class":3795},[3416,31343,31344,31346,31348,31350,31352,31354,31356,31358,31360],{"class":3418,"line":3515},[3416,31345,9521],{"class":6387},[3416,31347,6391],{"class":3795},[3416,31349,6394],{"class":4368},[3416,31351,6456],{"class":6397},[3416,31353,5861],{"class":3795},[3416,31355,6461],{"class":4368},[3416,31357,4384],{"class":3795},[3416,31359,6466],{"class":6397},[3416,31361,6469],{"class":3795},[3416,31363,31364],{"class":3418,"line":3521},[3416,31365,8628],{"class":3795},[3416,31367,31368,31371,31374,31376,31378,31380,31382,31384,31386,31389],{"class":3418,"line":3527},[3416,31369,31370],{"class":3795},"                { ",[3416,31372,31373],{"class":3808},"\"CategoryId\"",[3416,31375,4384],{"class":3795},[3416,31377,6394],{"class":4368},[3416,31379,6489],{"class":6397},[3416,31381,6492],{"class":3795},[3416,31383,6495],{"class":6387},[3416,31385,6391],{"class":3795},[3416,31387,31388],{"class":6387},"categoryId",[3416,31390,6503],{"class":3795},[3416,31392,31393,31395,31398,31400,31402,31404,31406,31408,31410,31413],{"class":3418,"line":3533},[3416,31394,31370],{"class":3795},[3416,31396,31397],{"class":3808},"\"Sku\"",[3416,31399,4384],{"class":3795},[3416,31401,6394],{"class":4368},[3416,31403,6489],{"class":6397},[3416,31405,6492],{"class":3795},[3416,31407,6495],{"class":6387},[3416,31409,6391],{"class":3795},[3416,31411,31412],{"class":6387},"sku",[3416,31414,6503],{"class":3795},[3416,31416,31417,31419,31422,31424,31426,31428,31430,31432,31434,31437],{"class":3418,"line":3539},[3416,31418,31370],{"class":3795},[3416,31420,31421],{"class":3808},"\"Name\"",[3416,31423,4384],{"class":3795},[3416,31425,6394],{"class":4368},[3416,31427,6489],{"class":6397},[3416,31429,6492],{"class":3795},[3416,31431,6495],{"class":6387},[3416,31433,6391],{"class":3795},[3416,31435,31436],{"class":6387},"name",[3416,31438,6503],{"class":3795},[3416,31440,31441,31443,31446,31448,31450,31452,31454,31456,31458,31461,31463,31465,31467,31470],{"class":3418,"line":3545},[3416,31442,31370],{"class":3795},[3416,31444,31445],{"class":3808},"\"Price\"",[3416,31447,4384],{"class":3795},[3416,31449,6394],{"class":4368},[3416,31451,6489],{"class":6397},[3416,31453,6492],{"class":3795},[3416,31455,10168],{"class":6387},[3416,31457,6391],{"class":3795},[3416,31459,31460],{"class":6387},"price",[3416,31462,4043],{"class":3795},[3416,31464,28214],{"class":6330},[3416,31466,6423],{"class":3795},[3416,31468,31469],{"class":3808},"\"F2\"",[3416,31471,31472],{"class":3795},") } },\n",[3416,31474,31475,31477,31480,31482,31484,31486,31488,31490,31492,31494],{"class":3418,"line":3551},[3416,31476,31370],{"class":3795},[3416,31478,31479],{"class":3808},"\"IsAvailable\"",[3416,31481,4384],{"class":3795},[3416,31483,6394],{"class":4368},[3416,31485,6489],{"class":6397},[3416,31487,6492],{"class":3795},[3416,31489,6850],{"class":6387},[3416,31491,6391],{"class":3795},[3416,31493,4038],{"class":4368},[3416,31495,6528],{"class":3795},[3416,31497,31498],{"class":3418,"line":3557},[3416,31499,8815],{"class":3795},[3416,31501,31502],{"class":3418,"line":3563},[3416,31503,30897],{"class":3795},[3416,31505,31506],{"class":3418,"line":3569},[3416,31507,3441],{"emptyLinePlaceholder":3440},[3416,31509,31510,31513,31515,31517,31519,31521,31524],{"class":3418,"line":3574},[3416,31511,31512],{"class":4368},"        await",[3416,31514,31204],{"class":6387},[3416,31516,4043],{"class":3795},[3416,31518,6718],{"class":6330},[3416,31520,6423],{"class":3795},[3416,31522,31523],{"class":6387},"request",[3416,31525,11465],{"class":3795},[3416,31527,31528],{"class":3418,"line":3579},[3416,31529,4167],{"class":3795},[3416,31531,31532],{"class":3418,"line":3584},[3416,31533,3441],{"emptyLinePlaceholder":3440},[3416,31535,31536],{"class":3418,"line":3590},[3416,31537,31538],{"class":3789},"    \u002F\u002F ── GetItem: Точкове зчитування елемента за HASH та RANGE ─────────────────────\n",[3416,31540,31541,31543,31545,31547,31549,31551,31553,31555,31557,31559,31562,31565,31567,31569,31571,31573,31575,31577],{"class":3418,"line":3596},[3416,31542,31235],{"class":4368},[3416,31544,31273],{"class":4368},[3416,31546,11606],{"class":6397},[3416,31548,5861],{"class":3795},[3416,31550,8645],{"class":6397},[3416,31552,5861],{"class":3795},[3416,31554,6461],{"class":4368},[3416,31556,4384],{"class":3795},[3416,31558,6466],{"class":6397},[3416,31560,31561],{"class":3795},">?> ",[3416,31563,31564],{"class":6330},"GetProductAsync",[3416,31566,6423],{"class":3795},[3416,31568,6461],{"class":4368},[3416,31570,31285],{"class":6387},[3416,31572,4384],{"class":3795},[3416,31574,6461],{"class":4368},[3416,31576,31292],{"class":6387},[3416,31578,9656],{"class":3795},[3416,31580,31581],{"class":3418,"line":3602},[3416,31582,6474],{"class":3795},[3416,31584,31585,31587,31589,31591,31593],{"class":3418,"line":3608},[3416,31586,30853],{"class":4368},[3416,31588,31320],{"class":6387},[3416,31590,6391],{"class":3795},[3416,31592,6394],{"class":4368},[3416,31594,6428],{"class":6397},[3416,31596,31597],{"class":3418,"line":3614},[3416,31598,8611],{"class":3795},[3416,31600,31601,31603,31605,31607],{"class":3418,"line":3620},[3416,31602,10247],{"class":6387},[3416,31604,6391],{"class":3795},[3416,31606,31339],{"class":6387},[3416,31608,3812],{"class":3795},[3416,31610,31611,31613,31615,31617,31619,31621,31623,31625,31627],{"class":3418,"line":3626},[3416,31612,9607],{"class":6387},[3416,31614,6391],{"class":3795},[3416,31616,6394],{"class":4368},[3416,31618,6456],{"class":6397},[3416,31620,5861],{"class":3795},[3416,31622,6461],{"class":4368},[3416,31624,4384],{"class":3795},[3416,31626,6466],{"class":6397},[3416,31628,6469],{"class":3795},[3416,31630,31631],{"class":3418,"line":3631},[3416,31632,8628],{"class":3795},[3416,31634,31635,31637,31639,31641,31643,31645,31647,31649,31651,31653],{"class":3418,"line":3636},[3416,31636,31370],{"class":3795},[3416,31638,31373],{"class":3808},[3416,31640,4384],{"class":3795},[3416,31642,6394],{"class":4368},[3416,31644,6489],{"class":6397},[3416,31646,6492],{"class":3795},[3416,31648,6495],{"class":6387},[3416,31650,6391],{"class":3795},[3416,31652,31388],{"class":6387},[3416,31654,6503],{"class":3795},[3416,31656,31657,31659,31661,31663,31665,31667,31669,31671,31673,31675],{"class":3418,"line":3641},[3416,31658,31370],{"class":3795},[3416,31660,31397],{"class":3808},[3416,31662,4384],{"class":3795},[3416,31664,6394],{"class":4368},[3416,31666,6489],{"class":6397},[3416,31668,6492],{"class":3795},[3416,31670,6495],{"class":6387},[3416,31672,6391],{"class":3795},[3416,31674,31412],{"class":6387},[3416,31676,6528],{"class":3795},[3416,31678,31679],{"class":3418,"line":3647},[3416,31680,9066],{"class":3795},[3416,31682,31683,31686,31688,31690],{"class":3418,"line":3653},[3416,31684,31685],{"class":6387},"            ConsistentRead",[3416,31687,6391],{"class":3795},[3416,31689,4038],{"class":4368},[3416,31691,31692],{"class":3789}," \u002F\u002F Strongly Consistent Read\n",[3416,31694,31695],{"class":3418,"line":3659},[3416,31696,30897],{"class":3795},[3416,31698,31699],{"class":3418,"line":3665},[3416,31700,3441],{"emptyLinePlaceholder":3440},[3416,31702,31703,31705,31707,31709,31711,31713,31715,31717,31719,31721],{"class":3418,"line":3671},[3416,31704,30853],{"class":4368},[3416,31706,6408],{"class":6387},[3416,31708,6391],{"class":3795},[3416,31710,6413],{"class":4368},[3416,31712,31204],{"class":6387},[3416,31714,4043],{"class":3795},[3416,31716,6420],{"class":6330},[3416,31718,6423],{"class":3795},[3416,31720,31523],{"class":6387},[3416,31722,11465],{"class":3795},[3416,31724,31725,31727,31729,31731,31734,31737,31740,31742,31745,31748,31750],{"class":3418,"line":3677},[3416,31726,30902],{"class":11427},[3416,31728,6408],{"class":6387},[3416,31730,4043],{"class":3795},[3416,31732,31733],{"class":6387},"IsItemSet",[3416,31735,31736],{"class":3795}," ? ",[3416,31738,31739],{"class":6387},"response",[3416,31741,4043],{"class":3795},[3416,31743,31744],{"class":6387},"Item",[3416,31746,31747],{"class":3795}," : ",[3416,31749,30944],{"class":4368},[3416,31751,11594],{"class":3795},[3416,31753,31754],{"class":3418,"line":3683},[3416,31755,4167],{"class":3795},[3416,31757,31758],{"class":3418,"line":3688},[3416,31759,3441],{"emptyLinePlaceholder":3440},[3416,31761,31762],{"class":3418,"line":3693},[3416,31763,31764],{"class":3789},"    \u002F\u002F ── UpdateItem: Оновлення окремого атрибута за виразом (Update Expression) ───\n",[3416,31766,31767,31769,31771,31773,31776,31778,31780,31782,31784,31786,31788,31790,31792,31795],{"class":3418,"line":3698},[3416,31768,31235],{"class":4368},[3416,31770,31273],{"class":4368},[3416,31772,11606],{"class":6397},[3416,31774,31775],{"class":6330}," UpdatePriceAsync",[3416,31777,6423],{"class":3795},[3416,31779,6461],{"class":4368},[3416,31781,31285],{"class":6387},[3416,31783,4384],{"class":3795},[3416,31785,6461],{"class":4368},[3416,31787,31292],{"class":6387},[3416,31789,4384],{"class":3795},[3416,31791,31304],{"class":4368},[3416,31793,31794],{"class":6387}," newPrice",[3416,31796,9656],{"class":3795},[3416,31798,31799],{"class":3418,"line":3704},[3416,31800,6474],{"class":3795},[3416,31802,31803,31805,31807,31809,31811],{"class":3418,"line":3710},[3416,31804,30853],{"class":4368},[3416,31806,31320],{"class":6387},[3416,31808,6391],{"class":3795},[3416,31810,6394],{"class":4368},[3416,31812,7076],{"class":6397},[3416,31814,31815],{"class":3418,"line":3715},[3416,31816,8611],{"class":3795},[3416,31818,31819,31821,31823,31825],{"class":3418,"line":12799},[3416,31820,10247],{"class":6387},[3416,31822,6391],{"class":3795},[3416,31824,31339],{"class":6387},[3416,31826,3812],{"class":3795},[3416,31828,31829,31831,31833,31835,31837,31839,31841,31843,31845],{"class":3418,"line":12822},[3416,31830,9607],{"class":6387},[3416,31832,6391],{"class":3795},[3416,31834,6394],{"class":4368},[3416,31836,6456],{"class":6397},[3416,31838,5861],{"class":3795},[3416,31840,6461],{"class":4368},[3416,31842,4384],{"class":3795},[3416,31844,6466],{"class":6397},[3416,31846,6469],{"class":3795},[3416,31848,31849],{"class":3418,"line":12827},[3416,31850,8628],{"class":3795},[3416,31852,31853,31855,31857,31859,31861,31863,31865,31867,31869,31871],{"class":3418,"line":12832},[3416,31854,31370],{"class":3795},[3416,31856,31373],{"class":3808},[3416,31858,4384],{"class":3795},[3416,31860,6394],{"class":4368},[3416,31862,6489],{"class":6397},[3416,31864,6492],{"class":3795},[3416,31866,6495],{"class":6387},[3416,31868,6391],{"class":3795},[3416,31870,31388],{"class":6387},[3416,31872,6503],{"class":3795},[3416,31874,31875,31877,31879,31881,31883,31885,31887,31889,31891,31893],{"class":3418,"line":12837},[3416,31876,31370],{"class":3795},[3416,31878,31397],{"class":3808},[3416,31880,4384],{"class":3795},[3416,31882,6394],{"class":4368},[3416,31884,6489],{"class":6397},[3416,31886,6492],{"class":3795},[3416,31888,6495],{"class":6387},[3416,31890,6391],{"class":3795},[3416,31892,31412],{"class":6387},[3416,31894,6528],{"class":3795},[3416,31896,31897],{"class":3418,"line":12843},[3416,31898,9066],{"class":3795},[3416,31900,31901],{"class":3418,"line":12860},[3416,31902,31903],{"class":3789},"            \u002F\u002F Вираз оновлення: встановлюємо нову ціну та дату\n",[3416,31905,31906,31908,31910,31913],{"class":3418,"line":12865},[3416,31907,10369],{"class":6387},[3416,31909,6391],{"class":3795},[3416,31911,31912],{"class":3808},"\"SET Price = :newPrice, UpdatedAt = :ts\"",[3416,31914,3812],{"class":3795},[3416,31916,31917,31919,31921,31923,31925,31927,31929,31931,31933],{"class":3418,"line":12876},[3416,31918,10379],{"class":6387},[3416,31920,6391],{"class":3795},[3416,31922,6394],{"class":4368},[3416,31924,6456],{"class":6397},[3416,31926,5861],{"class":3795},[3416,31928,6461],{"class":4368},[3416,31930,4384],{"class":3795},[3416,31932,6466],{"class":6397},[3416,31934,6469],{"class":3795},[3416,31936,31937],{"class":3418,"line":12897},[3416,31938,8628],{"class":3795},[3416,31940,31941,31943,31946,31948,31950,31952,31954,31956,31958,31961,31963,31965,31967,31969],{"class":3418,"line":12902},[3416,31942,31370],{"class":3795},[3416,31944,31945],{"class":3808},"\":newPrice\"",[3416,31947,4384],{"class":3795},[3416,31949,6394],{"class":4368},[3416,31951,6489],{"class":6397},[3416,31953,6492],{"class":3795},[3416,31955,10168],{"class":6387},[3416,31957,6391],{"class":3795},[3416,31959,31960],{"class":6387},"newPrice",[3416,31962,4043],{"class":3795},[3416,31964,28214],{"class":6330},[3416,31966,6423],{"class":3795},[3416,31968,31469],{"class":3808},[3416,31970,31472],{"class":3795},[3416,31972,31973,31975,31978,31980,31982,31984,31986,31988,31990,31992,31994,31996,31998,32000,32002,32005],{"class":3418,"line":12925},[3416,31974,31370],{"class":3795},[3416,31976,31977],{"class":3808},"\":ts\"",[3416,31979,4384],{"class":3795},[3416,31981,6394],{"class":4368},[3416,31983,6489],{"class":6397},[3416,31985,6492],{"class":3795},[3416,31987,6495],{"class":6387},[3416,31989,6391],{"class":3795},[3416,31991,11644],{"class":6387},[3416,31993,4043],{"class":3795},[3416,31995,28050],{"class":6387},[3416,31997,4043],{"class":3795},[3416,31999,28214],{"class":6330},[3416,32001,6423],{"class":3795},[3416,32003,32004],{"class":3808},"\"O\"",[3416,32006,32007],{"class":3795},") } }\n",[3416,32009,32010],{"class":3418,"line":12948},[3416,32011,8815],{"class":3795},[3416,32013,32014],{"class":3418,"line":12953},[3416,32015,30897],{"class":3795},[3416,32017,32018],{"class":3418,"line":20609},[3416,32019,3441],{"emptyLinePlaceholder":3440},[3416,32021,32022,32024,32026,32028,32030,32032,32034],{"class":3418,"line":20614},[3416,32023,31512],{"class":4368},[3416,32025,31204],{"class":6387},[3416,32027,4043],{"class":3795},[3416,32029,7069],{"class":6330},[3416,32031,6423],{"class":3795},[3416,32033,31523],{"class":6387},[3416,32035,11465],{"class":3795},[3416,32037,32038],{"class":3418,"line":20619},[3416,32039,4167],{"class":3795},[3416,32041,32042],{"class":3418,"line":20624},[3416,32043,3507],{"class":3795},[4584,32045,32047],{"id":32046},"використання-виразів-expressions-у-запитах","Використання виразів (Expressions) у запитах",[3353,32049,32050,32051,4039,32053,32055],{},"При читанні великих обсягів даних за допомогою ",[3413,32052,31040],{},[3413,32054,31046],{}," важливо використовувати вирази для мінімізації споживання RCU та фільтрації на боці сервера:",[4488,32057,32058,32064,32078,32088,32108],{},[3377,32059,32060,32063],{},[3363,32061,32062],{},"KeyConditionExpression:"," Визначає критерії відбору за первинним ключем (обов'язково вказувати HASH-ключ).",[3377,32065,32066,32069,32070,32073,32074,32077],{},[3363,32067,32068],{},"FilterExpression:"," Додатковий фільтр, який застосовується до знайдених даних ",[4091,32071,32072],{},"після"," зчитування з диска, але ",[4091,32075,32076],{},"перед"," поверненням клієнту (не економить RCU, але зменшує мережевий трафік).",[3377,32079,32080,32083,32084,32087],{},[3363,32081,32082],{},"ProjectionExpression:"," Перелік атрибутів, які необхідно повернути (аналог ",[3413,32085,32086],{},"SELECT column1, column2","). Економить пропускну здатність мережі.",[3377,32089,32090,32097,32098,4384,32100,4384,32102,4384,32105,13590],{},[3363,32091,32092,32093,32096],{},"ExpressionAttributeNames (словник з ",[3413,32094,32095],{},"#","):"," Використовується для екранування зарезервованих слів DynamoDB (таких як ",[3413,32099,5147],{},[3413,32101,4497],{},[3413,32103,32104],{},"User",[3413,32106,32107],{},"Timestamp",[3377,32109,32110,32115],{},[3363,32111,32112,32113,32096],{},"ExpressionAttributeValues (словник з ",[3413,32114,10458],{}," Передає значення параметрів у вирази.",[3353,32117,32118],{},"Приклад побудови запиту із зарезервованими іменами атрибутів:",[3406,32120,32122],{"className":6375,"code":32121,"language":6377,"meta":30432,"style":3411},"var queryRequest = new QueryRequest\n{\n    TableName = \"Products\",\n    KeyConditionExpression = \"CategoryId = :catId AND Sku >= :minSku\",\n    FilterExpression = \"#status = :statusVal AND Price \u003C :maxPrice\",\n    ProjectionExpression = \"Sku, #nameAttr, Price\",\n    ExpressionAttributeNames = new Dictionary\u003Cstring, string>\n    {\n        { \"#status\", \"Status\" }, \u002F\u002F Зарезервоване слово\n        { \"#nameAttr\", \"Name\" }   \u002F\u002F Зарезервоване слово\n    },\n    ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n    {\n        { \":catId\", new AttributeValue { S = \"Electronics\" } },\n        { \":minSku\", new AttributeValue { S = \"SKU-1000\" } },\n        { \":statusVal\", new AttributeValue { S = \"ACTIVE\" } },\n        { \":maxPrice\", new AttributeValue { N = \"500.00\" } }\n    }\n};\n\nvar response = await _client.QueryAsync(queryRequest);\n",[3413,32123,32124,32136,32140,32150,32161,32172,32184,32204,32208,32225,32241,32245,32265,32269,32292,32316,32339,32363,32367,32371,32375],{"__ignoreMap":3411},[3416,32125,32126,32128,32130,32132,32134],{"class":3418,"line":3419},[3416,32127,6384],{"class":4368},[3416,32129,18384],{"class":6387},[3416,32131,6391],{"class":3795},[3416,32133,6394],{"class":4368},[3416,32135,7755],{"class":6397},[3416,32137,32138],{"class":3418,"line":3425},[3416,32139,3796],{"class":3795},[3416,32141,32142,32144,32146,32148],{"class":3418,"line":3431},[3416,32143,6437],{"class":6387},[3416,32145,6391],{"class":3795},[3416,32147,31224],{"class":3808},[3416,32149,3812],{"class":3795},[3416,32151,32152,32154,32156,32159],{"class":3418,"line":3437},[3416,32153,7774],{"class":6387},[3416,32155,6391],{"class":3795},[3416,32157,32158],{"class":3808},"\"CategoryId = :catId AND Sku >= :minSku\"",[3416,32160,3812],{"class":3795},[3416,32162,32163,32165,32167,32170],{"class":3418,"line":3444},[3416,32164,8082],{"class":6387},[3416,32166,6391],{"class":3795},[3416,32168,32169],{"class":3808},"\"#status = :statusVal AND Price \u003C :maxPrice\"",[3416,32171,3812],{"class":3795},[3416,32173,32174,32177,32179,32182],{"class":3418,"line":3450},[3416,32175,32176],{"class":6387},"    ProjectionExpression",[3416,32178,6391],{"class":3795},[3416,32180,32181],{"class":3808},"\"Sku, #nameAttr, Price\"",[3416,32183,3812],{"class":3795},[3416,32185,32186,32188,32190,32192,32194,32196,32198,32200,32202],{"class":3418,"line":3456},[3416,32187,20755],{"class":6387},[3416,32189,6391],{"class":3795},[3416,32191,6394],{"class":4368},[3416,32193,6456],{"class":6397},[3416,32195,5861],{"class":3795},[3416,32197,6461],{"class":4368},[3416,32199,4384],{"class":3795},[3416,32201,6461],{"class":4368},[3416,32203,6469],{"class":3795},[3416,32205,32206],{"class":3418,"line":3462},[3416,32207,6474],{"class":3795},[3416,32209,32210,32212,32215,32217,32219,32222],{"class":3418,"line":3468},[3416,32211,6479],{"class":3795},[3416,32213,32214],{"class":3808},"\"#status\"",[3416,32216,4384],{"class":3795},[3416,32218,11860],{"class":3808},[3416,32220,32221],{"class":3795}," }, ",[3416,32223,32224],{"class":3789},"\u002F\u002F Зарезервоване слово\n",[3416,32226,32227,32229,32232,32234,32236,32239],{"class":3418,"line":3474},[3416,32228,6479],{"class":3795},[3416,32230,32231],{"class":3808},"\"#nameAttr\"",[3416,32233,4384],{"class":3795},[3416,32235,31421],{"class":3808},[3416,32237,32238],{"class":3795}," }   ",[3416,32240,32224],{"class":3789},[3416,32242,32243],{"class":3418,"line":3480},[3416,32244,4442],{"class":3795},[3416,32246,32247,32249,32251,32253,32255,32257,32259,32261,32263],{"class":3418,"line":3486},[3416,32248,7179],{"class":6387},[3416,32250,6391],{"class":3795},[3416,32252,6394],{"class":4368},[3416,32254,6456],{"class":6397},[3416,32256,5861],{"class":3795},[3416,32258,6461],{"class":4368},[3416,32260,4384],{"class":3795},[3416,32262,6466],{"class":6397},[3416,32264,6469],{"class":3795},[3416,32266,32267],{"class":3418,"line":3492},[3416,32268,6474],{"class":3795},[3416,32270,32271,32273,32276,32278,32280,32282,32284,32286,32288,32290],{"class":3418,"line":3498},[3416,32272,6479],{"class":3795},[3416,32274,32275],{"class":3808},"\":catId\"",[3416,32277,4384],{"class":3795},[3416,32279,6394],{"class":4368},[3416,32281,6489],{"class":6397},[3416,32283,6492],{"class":3795},[3416,32285,6495],{"class":6387},[3416,32287,6391],{"class":3795},[3416,32289,3920],{"class":3808},[3416,32291,6503],{"class":3795},[3416,32293,32294,32296,32299,32301,32303,32305,32307,32309,32311,32314],{"class":3418,"line":3504},[3416,32295,6479],{"class":3795},[3416,32297,32298],{"class":3808},"\":minSku\"",[3416,32300,4384],{"class":3795},[3416,32302,6394],{"class":4368},[3416,32304,6489],{"class":6397},[3416,32306,6492],{"class":3795},[3416,32308,6495],{"class":6387},[3416,32310,6391],{"class":3795},[3416,32312,32313],{"class":3808},"\"SKU-1000\"",[3416,32315,6503],{"class":3795},[3416,32317,32318,32320,32323,32325,32327,32329,32331,32333,32335,32337],{"class":3418,"line":3510},[3416,32319,6479],{"class":3795},[3416,32321,32322],{"class":3808},"\":statusVal\"",[3416,32324,4384],{"class":3795},[3416,32326,6394],{"class":4368},[3416,32328,6489],{"class":6397},[3416,32330,6492],{"class":3795},[3416,32332,6495],{"class":6387},[3416,32334,6391],{"class":3795},[3416,32336,11864],{"class":3808},[3416,32338,6503],{"class":3795},[3416,32340,32341,32343,32346,32348,32350,32352,32354,32356,32358,32361],{"class":3418,"line":3515},[3416,32342,6479],{"class":3795},[3416,32344,32345],{"class":3808},"\":maxPrice\"",[3416,32347,4384],{"class":3795},[3416,32349,6394],{"class":4368},[3416,32351,6489],{"class":6397},[3416,32353,6492],{"class":3795},[3416,32355,10168],{"class":6387},[3416,32357,6391],{"class":3795},[3416,32359,32360],{"class":3808},"\"500.00\"",[3416,32362,6528],{"class":3795},[3416,32364,32365],{"class":3418,"line":3521},[3416,32366,4167],{"class":3795},[3416,32368,32369],{"class":3418,"line":3527},[3416,32370,18505],{"class":3795},[3416,32372,32373],{"class":3418,"line":3533},[3416,32374,3441],{"emptyLinePlaceholder":3440},[3416,32376,32377,32379,32381,32383,32385,32387,32389,32391,32393,32395],{"class":3418,"line":3539},[3416,32378,6384],{"class":4368},[3416,32380,6408],{"class":6387},[3416,32382,6391],{"class":3795},[3416,32384,6413],{"class":4368},[3416,32386,31204],{"class":6387},[3416,32388,4043],{"class":3795},[3416,32390,7748],{"class":6330},[3416,32392,6423],{"class":3795},[3416,32394,18530],{"class":6387},[3416,32396,11465],{"class":3795},[3720,32398],{},[3727,32400,32402],{"id":32401},"_4-document-model-робота-з-неструктурованими-документами","4. Document Model: Робота з неструктурованими документами",[3353,32404,32405,32407,32408,5167,32410,32412,32413,4043],{},[3363,32406,30245],{}," — це проміжний рівень абстракції, який надає класи ",[3413,32409,11480],{},[3413,32411,30253],{}," для зручної роботи зі схемами без необхідності опису об'єктів ",[3413,32414,6466],{},[4584,32416,32418],{"id":32417},"ключові-класи-моделі-документів","Ключові класи моделі документів",[3353,32420,32421],{},"Для роботи з даними використовуються три основні класи:",[24357,32423,32424,32431,32434],{},[24360,32425,32427,32428,4043],{"name":11480,"type":32426},"Class","Представляє таблицю DynamoDB. Містить методи для CRUD-операцій на рівні документів. Створюється через статичний фабричний метод ",[3413,32429,32430],{},"Table.LoadTable(client, tableName)",[24360,32432,32433],{"name":30253,"type":32426},"Представляє окремий запис як колекцію пар \"ключ-значення\" (без жорсткої схеми). Самостійно мапить типи .NET (string, decimal, bool) на типи DynamoDB.",[24360,32435,32437],{"name":32436,"type":32426},"Search","Клас-ітератор для обробки результатів запитів Query та Scan з підтримкою пагінації.",[4584,32439,32441],{"id":32440},"основні-методи-класу-table","Основні методи класу Table",[24357,32443,32444,32450,32456,32459,32462,32467],{},[24360,32445,32446,32447,32449],{"name":6420,"type":31008},"Зчитує ",[3413,32448,30253],{}," за первинним ключем.",[24360,32451,32452,32453,32455],{"name":6718,"type":31008},"Зберігає або перезаписує ",[3413,32454,30253],{}," у таблиці.",[24360,32457,32458],{"name":7069,"type":31008},"Оновлює частину атрибутів документа.",[24360,32460,32461],{"name":7480,"type":31008},"Видаляє документ за ключем.",[24360,32463,32464,32465,4043],{"name":4887,"type":31008},"Виконує пошук за ключем партиції та сортувальним критеріями. Повертає об'єкт ",[3413,32466,32436],{},[24360,32468,32469,32470,4043],{"name":4891,"type":31008},"Виконує повне сканування таблиці. Повертає об'єкт ",[3413,32471,32436],{},[4584,32473,32475],{"id":32474},"допоміжні-методи-класу-document","Допоміжні методи класу Document",[24357,32477,32478,32486,32493],{},[24360,32479,32482,32483,32485],{"name":32480,"type":32481},"FromJson(string json)","Static Method","Створює об'єкт ",[3413,32484,30253],{}," з валідного JSON-рядка.",[24360,32487,32489,32490,32492],{"name":32488,"type":31008},"ToJson()","Серіалізує поточний ",[3413,32491,30253],{}," у JSON-рядок.",[24360,32494,32497,32498,4384,32501,4384,32504,4384,32507,4384,32510,4043],{"name":32495,"type":32496},"As[Type]()","Conversion Methods","Група методів приведення значень атрибутів: ",[3413,32499,32500],{},"AsString()",[3413,32502,32503],{},"AsInt()",[3413,32505,32506],{},"AsDecimal()",[3413,32508,32509],{},"AsBoolean()",[3413,32511,32512],{},"AsDouble()",[4584,32514,32516],{"id":32515},"методи-класу-search-пагінація","Методи класу Search (Пагінація)",[24357,32518,32519,32523,32527],{},[24360,32520,32522],{"name":32521,"type":31008},"GetNextSetAsync()","Зчитує наступну сторінку результатів з БД.",[24360,32524,32526],{"name":32525,"type":31008},"GetRemainingAsync()","Зчитує всі залишені записи, що відповідають запиту, автоматично роблячи послідовні запити до БД.",[24360,32528,32531,32532,32534],{"name":32529,"type":32530},"IsDone","Property (bool)","Повертає ",[3413,32533,4038],{},", якщо в БД більше немає сторінок для завантаження.",[4584,32536,32538],{"id":32537},"crud-операції-в-моделі-документів","CRUD-операції в моделі документів",[3406,32540,32542],{"className":6375,"code":32541,"language":6377,"meta":30432,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.DocumentModel;\n\npublic class DocumentModelRepository\n{\n    private readonly Table _table;\n\n    public DocumentModelRepository(IAmazonDynamoDB client)\n    {\n        \u002F\u002F Завантаження метаданих таблиці при ініціалізації\n        _table = Table.LoadTable(client, \"Products\");\n    }\n\n    public async Task PutDocumentAsync(string categoryId, string sku, string name, decimal price, List\u003Cstring> tags)\n    {\n        var productDoc = new Document();\n        productDoc[\"CategoryId\"] = categoryId; \u002F\u002F Автоматична конвертація в AttributeValue (S)\n        productDoc[\"Sku\"] = sku;\n        productDoc[\"Name\"] = name;\n        productDoc[\"Price\"] = price;          \u002F\u002F Автоматична конвертація в (N)\n        productDoc[\"Tags\"] = tags;            \u002F\u002F Автоматична конвертація в String Set (SS)\n        productDoc[\"CreatedAt\"] = DateTime.UtcNow;\n\n        await _table.PutItemAsync(productDoc);\n    }\n\n    public async Task\u003CDocument?> GetDocumentAsync(string categoryId, string sku)\n    {\n        \u002F\u002F Метод LoadItemAsync автоматично будує запит GetItem\n        return await _table.GetItemAsync(categoryId, sku);\n    }\n}\n",[3413,32543,32544,32556,32573,32577,32586,32590,32604,32608,32623,32627,32632,32656,32660,32664,32715,32719,32735,32754,32768,32782,32800,32819,32837,32841,32858,32862,32866,32898,32902,32907,32930,32934],{"__ignoreMap":3411},[3416,32545,32546,32548,32550,32552,32554],{"class":3418,"line":3419},[3416,32547,17433],{"class":11427},[3416,32549,17436],{"class":6397},[3416,32551,4043],{"class":3795},[3416,32553,17441],{"class":6397},[3416,32555,11594],{"class":3795},[3416,32557,32558,32560,32562,32564,32566,32568,32571],{"class":3418,"line":3425},[3416,32559,17433],{"class":11427},[3416,32561,17436],{"class":6397},[3416,32563,4043],{"class":3795},[3416,32565,17441],{"class":6397},[3416,32567,4043],{"class":3795},[3416,32569,32570],{"class":6397},"DocumentModel",[3416,32572,11594],{"class":3795},[3416,32574,32575],{"class":3418,"line":3431},[3416,32576,3441],{"emptyLinePlaceholder":3440},[3416,32578,32579,32581,32583],{"class":3418,"line":3437},[3416,32580,31180],{"class":4368},[3416,32582,31183],{"class":4368},[3416,32584,32585],{"class":6397}," DocumentModelRepository\n",[3416,32587,32588],{"class":3418,"line":3444},[3416,32589,3796],{"class":3795},[3416,32591,32592,32594,32596,32599,32602],{"class":3418,"line":3450},[3416,32593,31195],{"class":4368},[3416,32595,31198],{"class":4368},[3416,32597,32598],{"class":6397}," Table",[3416,32600,32601],{"class":6387}," _table",[3416,32603,11594],{"class":3795},[3416,32605,32606],{"class":3418,"line":3456},[3416,32607,3441],{"emptyLinePlaceholder":3440},[3416,32609,32610,32612,32615,32617,32619,32621],{"class":3418,"line":3462},[3416,32611,31235],{"class":4368},[3416,32613,32614],{"class":6330}," DocumentModelRepository",[3416,32616,6423],{"class":3795},[3416,32618,30705],{"class":6397},[3416,32620,6388],{"class":6387},[3416,32622,9656],{"class":3795},[3416,32624,32625],{"class":3418,"line":3468},[3416,32626,6474],{"class":3795},[3416,32628,32629],{"class":3418,"line":3474},[3416,32630,32631],{"class":3789},"        \u002F\u002F Завантаження метаданих таблиці при ініціалізації\n",[3416,32633,32634,32637,32639,32641,32643,32646,32648,32650,32652,32654],{"class":3418,"line":3480},[3416,32635,32636],{"class":6387},"        _table",[3416,32638,6391],{"class":3795},[3416,32640,11480],{"class":6387},[3416,32642,4043],{"class":3795},[3416,32644,32645],{"class":6330},"LoadTable",[3416,32647,6423],{"class":3795},[3416,32649,31255],{"class":6387},[3416,32651,4384],{"class":3795},[3416,32653,31224],{"class":3808},[3416,32655,11465],{"class":3795},[3416,32657,32658],{"class":3418,"line":3486},[3416,32659,4167],{"class":3795},[3416,32661,32662],{"class":3418,"line":3492},[3416,32663,3441],{"emptyLinePlaceholder":3440},[3416,32665,32666,32668,32670,32672,32675,32677,32679,32681,32683,32685,32687,32689,32691,32693,32695,32697,32699,32701,32703,32705,32707,32710,32713],{"class":3418,"line":3498},[3416,32667,31235],{"class":4368},[3416,32669,31273],{"class":4368},[3416,32671,11606],{"class":6397},[3416,32673,32674],{"class":6330}," PutDocumentAsync",[3416,32676,6423],{"class":3795},[3416,32678,6461],{"class":4368},[3416,32680,31285],{"class":6387},[3416,32682,4384],{"class":3795},[3416,32684,6461],{"class":4368},[3416,32686,31292],{"class":6387},[3416,32688,4384],{"class":3795},[3416,32690,6461],{"class":4368},[3416,32692,31299],{"class":6387},[3416,32694,4384],{"class":3795},[3416,32696,31304],{"class":4368},[3416,32698,31307],{"class":6387},[3416,32700,4384],{"class":3795},[3416,32702,9173],{"class":6397},[3416,32704,5861],{"class":3795},[3416,32706,6461],{"class":4368},[3416,32708,32709],{"class":3795},"> ",[3416,32711,32712],{"class":6387},"tags",[3416,32714,9656],{"class":3795},[3416,32716,32717],{"class":3418,"line":3504},[3416,32718,6474],{"class":3795},[3416,32720,32721,32723,32726,32728,32730,32733],{"class":3418,"line":3510},[3416,32722,30853],{"class":4368},[3416,32724,32725],{"class":6387}," productDoc",[3416,32727,6391],{"class":3795},[3416,32729,6394],{"class":4368},[3416,32731,32732],{"class":6397}," Document",[3416,32734,6401],{"class":3795},[3416,32736,32737,32740,32742,32744,32747,32749,32751],{"class":3418,"line":3515},[3416,32738,32739],{"class":6387},"        productDoc",[3416,32741,11789],{"class":3795},[3416,32743,31373],{"class":3808},[3416,32745,32746],{"class":3795},"] = ",[3416,32748,31388],{"class":6387},[3416,32750,8900],{"class":3795},[3416,32752,32753],{"class":3789},"\u002F\u002F Автоматична конвертація в AttributeValue (S)\n",[3416,32755,32756,32758,32760,32762,32764,32766],{"class":3418,"line":3521},[3416,32757,32739],{"class":6387},[3416,32759,11789],{"class":3795},[3416,32761,31397],{"class":3808},[3416,32763,32746],{"class":3795},[3416,32765,31412],{"class":6387},[3416,32767,11594],{"class":3795},[3416,32769,32770,32772,32774,32776,32778,32780],{"class":3418,"line":3527},[3416,32771,32739],{"class":6387},[3416,32773,11789],{"class":3795},[3416,32775,31421],{"class":3808},[3416,32777,32746],{"class":3795},[3416,32779,31436],{"class":6387},[3416,32781,11594],{"class":3795},[3416,32783,32784,32786,32788,32790,32792,32794,32797],{"class":3418,"line":3533},[3416,32785,32739],{"class":6387},[3416,32787,11789],{"class":3795},[3416,32789,31445],{"class":3808},[3416,32791,32746],{"class":3795},[3416,32793,31460],{"class":6387},[3416,32795,32796],{"class":3795},";          ",[3416,32798,32799],{"class":3789},"\u002F\u002F Автоматична конвертація в (N)\n",[3416,32801,32802,32804,32806,32809,32811,32813,32816],{"class":3418,"line":3539},[3416,32803,32739],{"class":6387},[3416,32805,11789],{"class":3795},[3416,32807,32808],{"class":3808},"\"Tags\"",[3416,32810,32746],{"class":3795},[3416,32812,32712],{"class":6387},[3416,32814,32815],{"class":3795},";            ",[3416,32817,32818],{"class":3789},"\u002F\u002F Автоматична конвертація в String Set (SS)\n",[3416,32820,32821,32823,32825,32827,32829,32831,32833,32835],{"class":3418,"line":3545},[3416,32822,32739],{"class":6387},[3416,32824,11789],{"class":3795},[3416,32826,6815],{"class":3808},[3416,32828,32746],{"class":3795},[3416,32830,11644],{"class":6387},[3416,32832,4043],{"class":3795},[3416,32834,28050],{"class":6387},[3416,32836,11594],{"class":3795},[3416,32838,32839],{"class":3418,"line":3551},[3416,32840,3441],{"emptyLinePlaceholder":3440},[3416,32842,32843,32845,32847,32849,32851,32853,32856],{"class":3418,"line":3557},[3416,32844,31512],{"class":4368},[3416,32846,32601],{"class":6387},[3416,32848,4043],{"class":3795},[3416,32850,6718],{"class":6330},[3416,32852,6423],{"class":3795},[3416,32854,32855],{"class":6387},"productDoc",[3416,32857,11465],{"class":3795},[3416,32859,32860],{"class":3418,"line":3563},[3416,32861,4167],{"class":3795},[3416,32863,32864],{"class":3418,"line":3569},[3416,32865,3441],{"emptyLinePlaceholder":3440},[3416,32867,32868,32870,32872,32874,32876,32878,32881,32884,32886,32888,32890,32892,32894,32896],{"class":3418,"line":3574},[3416,32869,31235],{"class":4368},[3416,32871,31273],{"class":4368},[3416,32873,11606],{"class":6397},[3416,32875,5861],{"class":3795},[3416,32877,30253],{"class":6397},[3416,32879,32880],{"class":3795},"?> ",[3416,32882,32883],{"class":6330},"GetDocumentAsync",[3416,32885,6423],{"class":3795},[3416,32887,6461],{"class":4368},[3416,32889,31285],{"class":6387},[3416,32891,4384],{"class":3795},[3416,32893,6461],{"class":4368},[3416,32895,31292],{"class":6387},[3416,32897,9656],{"class":3795},[3416,32899,32900],{"class":3418,"line":3579},[3416,32901,6474],{"class":3795},[3416,32903,32904],{"class":3418,"line":3584},[3416,32905,32906],{"class":3789},"        \u002F\u002F Метод LoadItemAsync автоматично будує запит GetItem\n",[3416,32908,32909,32911,32914,32916,32918,32920,32922,32924,32926,32928],{"class":3418,"line":3590},[3416,32910,30902],{"class":11427},[3416,32912,32913],{"class":4368}," await",[3416,32915,32601],{"class":6387},[3416,32917,4043],{"class":3795},[3416,32919,6420],{"class":6330},[3416,32921,6423],{"class":3795},[3416,32923,31388],{"class":6387},[3416,32925,4384],{"class":3795},[3416,32927,31412],{"class":6387},[3416,32929,11465],{"class":3795},[3416,32931,32932],{"class":3418,"line":3596},[3416,32933,4167],{"class":3795},[3416,32935,32936],{"class":3418,"line":3602},[3416,32937,3507],{"class":3795},[4584,32939,32941],{"id":32940},"інтеграція-з-json-даними","Інтеграція з JSON-даними",[3353,32943,32944,32945,5167,32948,10458],{},"Однією з найсильніших переваг моделі документів є підтримка прямого імпорту та експорту JSON-структур за допомогою методів ",[3413,32946,32947],{},"Document.FromJson",[3413,32949,32950],{},"Document.ToJson",[3406,32952,32954],{"className":6375,"code":32953,"language":6377,"meta":30432,"style":3411},"\u002F\u002F ── Імпорт: Перетворення JSON-рядка безпосередньо у запис таблиці ─────────────\nstring rawJson = \"\"\"\n{\n  \"CategoryId\": \"Books\",\n  \"Sku\": \"BOOK-9921\",\n  \"Name\": \"Clean Architecture\",\n  \"Details\": {\n    \"Author\": \"Robert C. Martin\",\n    \"Pages\": 432\n  }\n}\n\"\"\";\n\nDocument document = Document.FromJson(rawJson);\nawait _table.PutItemAsync(document);\n\n\u002F\u002F ── Експорт: Перетворення зчитаного документа у JSON-рядок ────────────────────\nDocument fetchedDoc = await _table.GetItemAsync(\"Books\", \"BOOK-9921\");\nstring jsonOutput = fetchedDoc.ToJson(); \n\u002F\u002F jsonOutput міститиме стандартний валідний JSON\n",[3413,32955,32956,32961,32973,32977,32982,32987,32992,32997,33002,33007,33011,33015,33022,33026,33049,33066,33070,33075,33104,33124],{"__ignoreMap":3411},[3416,32957,32958],{"class":3418,"line":3419},[3416,32959,32960],{"class":3789},"\u002F\u002F ── Імпорт: Перетворення JSON-рядка безпосередньо у запис таблиці ─────────────\n",[3416,32962,32963,32965,32968,32970],{"class":3418,"line":3425},[3416,32964,6461],{"class":4368},[3416,32966,32967],{"class":6387}," rawJson",[3416,32969,6391],{"class":3795},[3416,32971,32972],{"class":3808},"\"\"\"\n",[3416,32974,32975],{"class":3418,"line":3431},[3416,32976,3796],{"class":3808},[3416,32978,32979],{"class":3418,"line":3437},[3416,32980,32981],{"class":3808},"  \"CategoryId\": \"Books\",\n",[3416,32983,32984],{"class":3418,"line":3444},[3416,32985,32986],{"class":3808},"  \"Sku\": \"BOOK-9921\",\n",[3416,32988,32989],{"class":3418,"line":3450},[3416,32990,32991],{"class":3808},"  \"Name\": \"Clean Architecture\",\n",[3416,32993,32994],{"class":3418,"line":3456},[3416,32995,32996],{"class":3808},"  \"Details\": {\n",[3416,32998,32999],{"class":3418,"line":3462},[3416,33000,33001],{"class":3808},"    \"Author\": \"Robert C. Martin\",\n",[3416,33003,33004],{"class":3418,"line":3468},[3416,33005,33006],{"class":3808},"    \"Pages\": 432\n",[3416,33008,33009],{"class":3418,"line":3474},[3416,33010,30530],{"class":3808},[3416,33012,33013],{"class":3418,"line":3480},[3416,33014,3507],{"class":3808},[3416,33016,33017,33020],{"class":3418,"line":3486},[3416,33018,33019],{"class":3808},"\"\"\"",[3416,33021,11594],{"class":3795},[3416,33023,33024],{"class":3418,"line":3492},[3416,33025,3441],{"emptyLinePlaceholder":3440},[3416,33027,33028,33030,33033,33035,33037,33039,33042,33044,33047],{"class":3418,"line":3498},[3416,33029,30253],{"class":6397},[3416,33031,33032],{"class":6387}," document",[3416,33034,6391],{"class":3795},[3416,33036,30253],{"class":6387},[3416,33038,4043],{"class":3795},[3416,33040,33041],{"class":6330},"FromJson",[3416,33043,6423],{"class":3795},[3416,33045,33046],{"class":6387},"rawJson",[3416,33048,11465],{"class":3795},[3416,33050,33051,33053,33055,33057,33059,33061,33064],{"class":3418,"line":3504},[3416,33052,6413],{"class":4368},[3416,33054,32601],{"class":6387},[3416,33056,4043],{"class":3795},[3416,33058,6718],{"class":6330},[3416,33060,6423],{"class":3795},[3416,33062,33063],{"class":6387},"document",[3416,33065,11465],{"class":3795},[3416,33067,33068],{"class":3418,"line":3510},[3416,33069,3441],{"emptyLinePlaceholder":3440},[3416,33071,33072],{"class":3418,"line":3515},[3416,33073,33074],{"class":3789},"\u002F\u002F ── Експорт: Перетворення зчитаного документа у JSON-рядок ────────────────────\n",[3416,33076,33077,33079,33082,33084,33086,33088,33090,33092,33094,33097,33099,33102],{"class":3418,"line":3521},[3416,33078,30253],{"class":6397},[3416,33080,33081],{"class":6387}," fetchedDoc",[3416,33083,6391],{"class":3795},[3416,33085,6413],{"class":4368},[3416,33087,32601],{"class":6387},[3416,33089,4043],{"class":3795},[3416,33091,6420],{"class":6330},[3416,33093,6423],{"class":3795},[3416,33095,33096],{"class":3808},"\"Books\"",[3416,33098,4384],{"class":3795},[3416,33100,33101],{"class":3808},"\"BOOK-9921\"",[3416,33103,11465],{"class":3795},[3416,33105,33106,33108,33111,33113,33116,33118,33121],{"class":3418,"line":3527},[3416,33107,6461],{"class":4368},[3416,33109,33110],{"class":6387}," jsonOutput",[3416,33112,6391],{"class":3795},[3416,33114,33115],{"class":6387},"fetchedDoc",[3416,33117,4043],{"class":3795},[3416,33119,33120],{"class":6330},"ToJson",[3416,33122,33123],{"class":3795},"(); \n",[3416,33125,33126],{"class":3418,"line":3533},[3416,33127,33128],{"class":3789},"\u002F\u002F jsonOutput міститиме стандартний валідний JSON\n",[4584,33130,33132],{"id":33131},"виконання-запитів-через-search-helper","Виконання запитів через Search Helper",[3353,33134,33135,33136,33138],{},"Для ітерації по вибірці даних використовується клас ",[3413,33137,32436],{},", який підтримує ледачу підвантаження результатів сторінками:",[3406,33140,33142],{"className":6375,"code":33141,"language":6377,"meta":30432,"style":3411},"var filter = new QueryFilter(\"CategoryId\", QueryOperator.Equal, \"Books\");\nfilter.AddCondition(\"Price\", QueryOperator.LessThan, 50.00m);\n\nvar search = _table.Query(filter);\n\nwhile (!search.IsDone)\n{\n    \u002F\u002F Отримання наступної сторінки записів (Pagination)\n    List\u003CDocument> page = await search.GetNextSetAsync();\n    foreach (var doc in page)\n    {\n        Console.WriteLine($\"{doc[\"Name\"]} - {doc[\"Price\"].AsDecimal()}\");\n    }\n}\n",[3413,33143,33144,33178,33208,33212,33234,33238,33254,33258,33263,33290,33310,33314,33363,33367],{"__ignoreMap":3411},[3416,33145,33146,33148,33151,33153,33155,33158,33160,33162,33164,33167,33169,33172,33174,33176],{"class":3418,"line":3419},[3416,33147,6384],{"class":4368},[3416,33149,33150],{"class":6387}," filter",[3416,33152,6391],{"class":3795},[3416,33154,6394],{"class":4368},[3416,33156,33157],{"class":6397}," QueryFilter",[3416,33159,6423],{"class":3795},[3416,33161,31373],{"class":3808},[3416,33163,4384],{"class":3795},[3416,33165,33166],{"class":6387},"QueryOperator",[3416,33168,4043],{"class":3795},[3416,33170,33171],{"class":6387},"Equal",[3416,33173,4384],{"class":3795},[3416,33175,33096],{"class":3808},[3416,33177,11465],{"class":3795},[3416,33179,33180,33183,33185,33188,33190,33192,33194,33196,33198,33201,33203,33206],{"class":3418,"line":3425},[3416,33181,33182],{"class":6387},"filter",[3416,33184,4043],{"class":3795},[3416,33186,33187],{"class":6330},"AddCondition",[3416,33189,6423],{"class":3795},[3416,33191,31445],{"class":3808},[3416,33193,4384],{"class":3795},[3416,33195,33166],{"class":6387},[3416,33197,4043],{"class":3795},[3416,33199,33200],{"class":6387},"LessThan",[3416,33202,4384],{"class":3795},[3416,33204,33205],{"class":3870},"50.00m",[3416,33207,11465],{"class":3795},[3416,33209,33210],{"class":3418,"line":3431},[3416,33211,3441],{"emptyLinePlaceholder":3440},[3416,33213,33214,33216,33219,33221,33224,33226,33228,33230,33232],{"class":3418,"line":3437},[3416,33215,6384],{"class":4368},[3416,33217,33218],{"class":6387}," search",[3416,33220,6391],{"class":3795},[3416,33222,33223],{"class":6387},"_table",[3416,33225,4043],{"class":3795},[3416,33227,4887],{"class":6330},[3416,33229,6423],{"class":3795},[3416,33231,33182],{"class":6387},[3416,33233,11465],{"class":3795},[3416,33235,33236],{"class":3418,"line":3444},[3416,33237,3441],{"emptyLinePlaceholder":3440},[3416,33239,33240,33242,33245,33248,33250,33252],{"class":3418,"line":3450},[3416,33241,11428],{"class":11427},[3416,33243,33244],{"class":3795}," (!",[3416,33246,33247],{"class":6387},"search",[3416,33249,4043],{"class":3795},[3416,33251,32529],{"class":6387},[3416,33253,9656],{"class":3795},[3416,33255,33256],{"class":3418,"line":3456},[3416,33257,3796],{"class":3795},[3416,33259,33260],{"class":3418,"line":3462},[3416,33261,33262],{"class":3789},"    \u002F\u002F Отримання наступної сторінки записів (Pagination)\n",[3416,33264,33265,33268,33270,33272,33274,33277,33279,33281,33283,33285,33288],{"class":3418,"line":3468},[3416,33266,33267],{"class":6397},"    List",[3416,33269,5861],{"class":3795},[3416,33271,30253],{"class":6397},[3416,33273,32709],{"class":3795},[3416,33275,33276],{"class":6387},"page",[3416,33278,6391],{"class":3795},[3416,33280,6413],{"class":4368},[3416,33282,33218],{"class":6387},[3416,33284,4043],{"class":3795},[3416,33286,33287],{"class":6330},"GetNextSetAsync",[3416,33289,6401],{"class":3795},[3416,33291,33292,33295,33297,33299,33302,33305,33308],{"class":3418,"line":3474},[3416,33293,33294],{"class":11427},"    foreach",[3416,33296,11431],{"class":3795},[3416,33298,6384],{"class":4368},[3416,33300,33301],{"class":6387}," doc",[3416,33303,33304],{"class":11427}," in",[3416,33306,33307],{"class":6387}," page",[3416,33309,9656],{"class":3795},[3416,33311,33312],{"class":3418,"line":3480},[3416,33313,6474],{"class":3795},[3416,33315,33316,33318,33320,33322,33324,33327,33329,33332,33334,33336,33339,33342,33344,33346,33348,33350,33353,33356,33359,33361],{"class":3418,"line":3486},[3416,33317,11505],{"class":6387},[3416,33319,4043],{"class":3795},[3416,33321,11510],{"class":6330},[3416,33323,6423],{"class":3795},[3416,33325,33326],{"class":3808},"$\"",[3416,33328,11177],{"class":11533},[3416,33330,33331],{"class":6387},"doc",[3416,33333,11789],{"class":11533},[3416,33335,31421],{"class":3808},[3416,33337,33338],{"class":11533},"]}",[3416,33340,33341],{"class":3808}," - ",[3416,33343,11177],{"class":11533},[3416,33345,33331],{"class":6387},[3416,33347,11789],{"class":11533},[3416,33349,31445],{"class":3808},[3416,33351,33352],{"class":11533},"].",[3416,33354,33355],{"class":6330},"AsDecimal",[3416,33357,33358],{"class":11533},"()}",[3416,33360,24569],{"class":3808},[3416,33362,11465],{"class":3795},[3416,33364,33365],{"class":3418,"line":3492},[3416,33366,4167],{"class":3795},[3416,33368,33369],{"class":3418,"line":3498},[3416,33370,3507],{"class":3795},[3720,33372],{},[3727,33374,33376],{"id":33375},"_5-object-persistence-model-декларативний-orm","5. Object Persistence Model: Декларативний ORM",[3353,33378,33379,33381,33382,33384],{},[3363,33380,30273],{}," представляє найвищий рівень абстракції (ORM). Він використовує об'єкт ",[3413,33383,30279],{}," для мапінгу стандартних POCO-класів на таблиці за допомогою системи декларативних C#-атрибутів.",[4584,33386,33388],{"id":33387},"ключовий-клас-dynamodbcontext","Ключовий клас: DynamoDBContext",[3353,33390,33391,33392,33394],{},"Це основний робочий інструмент для ORM-мапінгу. Його інтерфейс ",[3413,33393,30735],{}," надає методи для збереження та завантаження POCO-об'єктів.",[24357,33396,33397,33405,33415,33419,33426,33432,33438,33445,33454],{},[24360,33398,33400,33401,33404],{"name":33399,"type":31008},"LoadAsync\u003CT>","Завантажує запис з БД та десеріалізує його в об'єкт типу ",[3413,33402,33403],{},"T"," за ключами.",[24360,33406,33408,33409,33411,33412,4043],{"name":33407,"type":31008},"SaveAsync\u003CT>","Зберігає об'єкт типу ",[3413,33410,33403],{}," у базі даних (виконує Upsert). Автоматично інкрементує версію сутності, якщо налаштовано ",[3413,33413,33414],{},"[DynamoDBVersion]",[24360,33416,33418],{"name":33417,"type":31008},"DeleteAsync\u003CT>","Видаляє об'єкт з бази даних за первинним ключем або за допомогою самого примірника сутності.",[24360,33420,33422,33423,4043],{"name":33421,"type":31008},"QueryAsync\u003CT>","Виконує типізований запис Query за Partition Key. Повертає ",[3413,33424,33425],{},"AsyncSearch\u003CT>",[24360,33427,33429,33430,4043],{"name":33428,"type":31008},"ScanAsync\u003CT>","Виконує типізоване сканування таблиці. Повертає ",[3413,33431,33425],{},[24360,33433,33435,33436,4043],{"name":33434,"type":31008},"CreateBatchWrite\u003CT>","Створює пакетний запис для групових операцій над сутностями типу ",[3413,33437,33403],{},[24360,33439,33441,33442,33444],{"name":33440,"type":31008},"CreateBatchGet\u003CT>","Створює пакетний запит для зчитування списку об'єктів типу ",[3413,33443,33403],{}," за списком первинних ключів.",[24360,33446,33448,33449,33451,33452,4043],{"name":33447,"type":31008},"FromDocument\u003CT>","Конвертує слабкотипізований ",[3413,33450,30253],{}," у строготипізований POCO-об'єкт ",[3413,33453,33403],{},[24360,33455,33457,33458,33460,33461,4043],{"name":33456,"type":31008},"ToDocument\u003CT>","Конвертує POCO-об'єкт ",[3413,33459,33403],{}," у слабкотипізований ",[3413,33462,30253],{},[4584,33464,33466],{"id":33465},"локальне-перевизначення-конфігурації-dynamodboperationconfig","Локальне перевизначення конфігурації (DynamoDBOperationConfig)",[3353,33468,33469,33470,33472,33473,4043],{},"При використанні ",[3413,33471,30279],{}," ви можете динамічно змінювати параметри виконання окремих CRUD-операцій за допомогою об'єкта ",[3413,33474,33475],{},"DynamoDBOperationConfig",[24357,33477,33478,33486,33490,33497,33509],{},[24360,33479,33481,33482,4039,33484,4043],{"name":33480,"type":6461,"default":30944},"IndexName","Вказує назву індексу (GSI або LSI), який необхідно використовувати для виконання операцій ",[3413,33483,4887],{},[3413,33485,4891],{},[24360,33487,33489],{"name":33488,"type":30958,"default":4042},"ConsistentRead","Визначає, чи використовувати Strongly Consistent читання. Зверніть увагу: GSI не підтримують Strongly Consistent читання.",[24360,33491,33493,33494,4043],{"name":33492,"type":6461,"default":30944},"OverrideTableName","Дозволяє динамічно спрямувати запит до іншої таблиці (наприклад, для шардингу або мультитенантності), ігноруючи ім'я, вказане в атрибуті ",[3413,33495,33496],{},"[DynamoDBTable]",[24360,33498,30959,33500,33502,33503,33505,33506,4043],{"name":33499,"type":30958,"default":4042},"IgnoreNullValues",[3413,33501,4038],{},", властивості POCO-класу зі значенням ",[3413,33504,30944],{}," не перезаписуватимуть існуючі значення в БД при використанні ",[3413,33507,33508],{},"SaveAsync",[24360,33510,33512,33513,4043],{"name":33511,"type":30958,"default":4042},"SkipVersionCheck","Дозволяє тимчасово вимкнути перевірку версії (Optimistic Locking), ігноруючи атрибут ",[3413,33514,33414],{},[4584,33516,33518],{"id":33517},"атрибути-мапування-даних-opm","Атрибути мапування даних OPM",[3353,33520,33521,33522,33525],{},"Для опису сутностей у просторі назв ",[3413,33523,33524],{},"Amazon.DynamoDBv2.DataModel"," використовуються такі атрибути:",[24357,33527,33528,33532,33537,33541,33548,33552,33559,33563,33567],{},[24360,33529,33531],{"name":33496,"type":33530,"required":4038},"Class Attribute","Вказує назву цільової таблиці DynamoDB.",[24360,33533,33536],{"name":33534,"type":33535,"required":4038},"[DynamoDBHashKey]","Property Attribute","Визначає Partition Key (HASH).",[24360,33538,33540],{"name":33539,"type":33535,"required":4042},"[DynamoDBRangeKey]","Визначає Sort Key (RANGE).",[24360,33542,33544,33545,13590],{"name":33543,"type":33535,"required":4042},"[DynamoDBProperty]","Вказує відповідність властивості та колонки. Дозволяє налаштовувати назву атрибута в БД та задавати кастомні конвертери (",[3413,33546,33547],{},"Converter",[24360,33549,33551],{"name":33550,"type":33535,"required":4042},"[DynamoDBIgnore]","Повністю виключає поле з процесів серіалізації.",[24360,33553,33554,33555,33558],{"name":33414,"type":33535,"required":4042},"Задіює ",[3363,33556,33557],{},"Оптимістичне блокування (Optimistic Locking)",". Поле автоматично інкрементується при записі та викликає виняток, якщо версія в БД була змінена іншим потоком.",[24360,33560,33562],{"name":33561,"type":33535,"required":4042},"[DynamoDBGlobalSecondaryIndexHashKey]","Визначає HASH-ключ для вказаного глобального індексу (GSI).",[24360,33564,33566],{"name":33565,"type":33535,"required":4042},"[DynamoDBGlobalSecondaryIndexRangeKey]","Визначає RANGE-ключ для глобального індексу (GSI).",[24360,33568,33570],{"name":33569,"type":33535,"required":4042},"[DynamoDBLocalSecondaryIndexRangeKey]","Визначає RANGE-ключ локального індексу (LSI).",[4584,33572,33574],{"id":33573},"проектування-poco-моделі-даних","Проектування POCO-моделі даних",[3353,33576,33577],{},"Нижче наведено приклад опису складної моделі даних з підтримкою GSI, оптимістичного блокування та вкладеного об'єкта, серіалізованого через кастомний конвертер:",[3406,33579,33581],{"className":6375,"code":33580,"language":6377,"meta":30432,"style":3411},"using Amazon.DynamoDBv2.DataModel;\n\n[DynamoDBTable(\"Catalog\")]\npublic class CatalogItem\n{\n    [DynamoDBHashKey(\"CategoryId\")] \u002F\u002F Первинний HASH\n    public string CategoryId { get; set; } = string.Empty;\n\n    [DynamoDBRangeKey(\"Sku\")] \u002F\u002F Первинний RANGE\n    public string Sku { get; set; } = string.Empty;\n\n    [DynamoDBProperty(\"Title\")]\n    public string Title { get; set; } = string.Empty;\n\n    [DynamoDBProperty(\"Price\")]\n    public decimal Price { get; set; }\n\n    \u002F\u002F Глобальний індекс: HASH-ключ для індексу \"Supplier-index\"\n    [DynamoDBGlobalSecondaryIndexHashKey(\"Supplier-index\", AttributeName = \"SupplierId\")]\n    public string SupplierId { get; set; } = string.Empty;\n\n    \u002F\u002F Автоматичне оптимістичне блокування версії запису\n    [DynamoDBVersion]\n    public int? Version { get; set; }\n\n    \u002F\u002F Вкладений складний об'єкт із кастомним конвертером в JSON String\n    [DynamoDBProperty(\"SpecSheet\", Converter = typeof(SpecsJsonConverter))]\n    public TechnicalSpecs Specs { get; set; } = new();\n\n    [DynamoDBIgnore]\n    public string MemoryCache { get; set; } = string.Empty;\n}\n\npublic class TechnicalSpecs\n{\n    public string Manufacturer { get; set; } = string.Empty;\n    public string WarrantyMonths { get; set; } = string.Empty;\n}\n",[3413,33582,33583,33599,33603,33618,33627,33631,33648,33679,33683,33699,33726,33730,33744,33771,33775,33787,33808,33812,33817,33840,33867,33871,33876,33885,33908,33912,33917,33945,33969,33973,33982,34009,34013,34017,34026,34030,34057,34084],{"__ignoreMap":3411},[3416,33584,33585,33587,33589,33591,33593,33595,33597],{"class":3418,"line":3419},[3416,33586,17433],{"class":11427},[3416,33588,17436],{"class":6397},[3416,33590,4043],{"class":3795},[3416,33592,17441],{"class":6397},[3416,33594,4043],{"class":3795},[3416,33596,30594],{"class":6397},[3416,33598,11594],{"class":3795},[3416,33600,33601],{"class":3418,"line":3425},[3416,33602,3441],{"emptyLinePlaceholder":3440},[3416,33604,33605,33607,33610,33612,33615],{"class":3418,"line":3431},[3416,33606,11789],{"class":3795},[3416,33608,33609],{"class":6397},"DynamoDBTable",[3416,33611,6423],{"class":3795},[3416,33613,33614],{"class":3808},"\"Catalog\"",[3416,33616,33617],{"class":3795},")]\n",[3416,33619,33620,33622,33624],{"class":3418,"line":3437},[3416,33621,31180],{"class":4368},[3416,33623,31183],{"class":4368},[3416,33625,33626],{"class":6397}," CatalogItem\n",[3416,33628,33629],{"class":3418,"line":3444},[3416,33630,3796],{"class":3795},[3416,33632,33633,33635,33638,33640,33642,33645],{"class":3418,"line":3450},[3416,33634,9496],{"class":3795},[3416,33636,33637],{"class":6397},"DynamoDBHashKey",[3416,33639,6423],{"class":3795},[3416,33641,31373],{"class":3808},[3416,33643,33644],{"class":3795},")] ",[3416,33646,33647],{"class":3789},"\u002F\u002F Первинний HASH\n",[3416,33649,33650,33652,33654,33657,33659,33662,33664,33667,33670,33672,33674,33677],{"class":3418,"line":3456},[3416,33651,31235],{"class":4368},[3416,33653,31216],{"class":4368},[3416,33655,33656],{"class":6387}," CategoryId",[3416,33658,6492],{"class":3795},[3416,33660,33661],{"class":4368},"get",[3416,33663,8900],{"class":3795},[3416,33665,33666],{"class":4368},"set",[3416,33668,33669],{"class":3795},"; } = ",[3416,33671,6461],{"class":4368},[3416,33673,4043],{"class":3795},[3416,33675,33676],{"class":6387},"Empty",[3416,33678,11594],{"class":3795},[3416,33680,33681],{"class":3418,"line":3462},[3416,33682,3441],{"emptyLinePlaceholder":3440},[3416,33684,33685,33687,33690,33692,33694,33696],{"class":3418,"line":3468},[3416,33686,9496],{"class":3795},[3416,33688,33689],{"class":6397},"DynamoDBRangeKey",[3416,33691,6423],{"class":3795},[3416,33693,31397],{"class":3808},[3416,33695,33644],{"class":3795},[3416,33697,33698],{"class":3789},"\u002F\u002F Первинний RANGE\n",[3416,33700,33701,33703,33705,33708,33710,33712,33714,33716,33718,33720,33722,33724],{"class":3418,"line":3474},[3416,33702,31235],{"class":4368},[3416,33704,31216],{"class":4368},[3416,33706,33707],{"class":6387}," Sku",[3416,33709,6492],{"class":3795},[3416,33711,33661],{"class":4368},[3416,33713,8900],{"class":3795},[3416,33715,33666],{"class":4368},[3416,33717,33669],{"class":3795},[3416,33719,6461],{"class":4368},[3416,33721,4043],{"class":3795},[3416,33723,33676],{"class":6387},[3416,33725,11594],{"class":3795},[3416,33727,33728],{"class":3418,"line":3480},[3416,33729,3441],{"emptyLinePlaceholder":3440},[3416,33731,33732,33734,33737,33739,33742],{"class":3418,"line":3486},[3416,33733,9496],{"class":3795},[3416,33735,33736],{"class":6397},"DynamoDBProperty",[3416,33738,6423],{"class":3795},[3416,33740,33741],{"class":3808},"\"Title\"",[3416,33743,33617],{"class":3795},[3416,33745,33746,33748,33750,33753,33755,33757,33759,33761,33763,33765,33767,33769],{"class":3418,"line":3492},[3416,33747,31235],{"class":4368},[3416,33749,31216],{"class":4368},[3416,33751,33752],{"class":6387}," Title",[3416,33754,6492],{"class":3795},[3416,33756,33661],{"class":4368},[3416,33758,8900],{"class":3795},[3416,33760,33666],{"class":4368},[3416,33762,33669],{"class":3795},[3416,33764,6461],{"class":4368},[3416,33766,4043],{"class":3795},[3416,33768,33676],{"class":6387},[3416,33770,11594],{"class":3795},[3416,33772,33773],{"class":3418,"line":3498},[3416,33774,3441],{"emptyLinePlaceholder":3440},[3416,33776,33777,33779,33781,33783,33785],{"class":3418,"line":3504},[3416,33778,9496],{"class":3795},[3416,33780,33736],{"class":6397},[3416,33782,6423],{"class":3795},[3416,33784,31445],{"class":3808},[3416,33786,33617],{"class":3795},[3416,33788,33789,33791,33794,33797,33799,33801,33803,33805],{"class":3418,"line":3510},[3416,33790,31235],{"class":4368},[3416,33792,33793],{"class":4368}," decimal",[3416,33795,33796],{"class":6387}," Price",[3416,33798,6492],{"class":3795},[3416,33800,33661],{"class":4368},[3416,33802,8900],{"class":3795},[3416,33804,33666],{"class":4368},[3416,33806,33807],{"class":3795},"; }\n",[3416,33809,33810],{"class":3418,"line":3515},[3416,33811,3441],{"emptyLinePlaceholder":3440},[3416,33813,33814],{"class":3418,"line":3521},[3416,33815,33816],{"class":3789},"    \u002F\u002F Глобальний індекс: HASH-ключ для індексу \"Supplier-index\"\n",[3416,33818,33819,33821,33824,33826,33829,33831,33833,33835,33838],{"class":3418,"line":3527},[3416,33820,9496],{"class":3795},[3416,33822,33823],{"class":6397},"DynamoDBGlobalSecondaryIndexHashKey",[3416,33825,6423],{"class":3795},[3416,33827,33828],{"class":3808},"\"Supplier-index\"",[3416,33830,4384],{"class":3795},[3416,33832,10857],{"class":6387},[3416,33834,6391],{"class":3795},[3416,33836,33837],{"class":3808},"\"SupplierId\"",[3416,33839,33617],{"class":3795},[3416,33841,33842,33844,33846,33849,33851,33853,33855,33857,33859,33861,33863,33865],{"class":3418,"line":3533},[3416,33843,31235],{"class":4368},[3416,33845,31216],{"class":4368},[3416,33847,33848],{"class":6387}," SupplierId",[3416,33850,6492],{"class":3795},[3416,33852,33661],{"class":4368},[3416,33854,8900],{"class":3795},[3416,33856,33666],{"class":4368},[3416,33858,33669],{"class":3795},[3416,33860,6461],{"class":4368},[3416,33862,4043],{"class":3795},[3416,33864,33676],{"class":6387},[3416,33866,11594],{"class":3795},[3416,33868,33869],{"class":3418,"line":3539},[3416,33870,3441],{"emptyLinePlaceholder":3440},[3416,33872,33873],{"class":3418,"line":3545},[3416,33874,33875],{"class":3789},"    \u002F\u002F Автоматичне оптимістичне блокування версії запису\n",[3416,33877,33878,33880,33883],{"class":3418,"line":3551},[3416,33879,9496],{"class":3795},[3416,33881,33882],{"class":6397},"DynamoDBVersion",[3416,33884,18183],{"class":3795},[3416,33886,33887,33889,33892,33895,33898,33900,33902,33904,33906],{"class":3418,"line":3557},[3416,33888,31235],{"class":4368},[3416,33890,33891],{"class":4368}," int",[3416,33893,33894],{"class":3795},"? ",[3416,33896,33897],{"class":6387},"Version",[3416,33899,6492],{"class":3795},[3416,33901,33661],{"class":4368},[3416,33903,8900],{"class":3795},[3416,33905,33666],{"class":4368},[3416,33907,33807],{"class":3795},[3416,33909,33910],{"class":3418,"line":3563},[3416,33911,3441],{"emptyLinePlaceholder":3440},[3416,33913,33914],{"class":3418,"line":3569},[3416,33915,33916],{"class":3789},"    \u002F\u002F Вкладений складний об'єкт із кастомним конвертером в JSON String\n",[3416,33918,33919,33921,33923,33925,33928,33930,33932,33934,33937,33939,33942],{"class":3418,"line":3574},[3416,33920,9496],{"class":3795},[3416,33922,33736],{"class":6397},[3416,33924,6423],{"class":3795},[3416,33926,33927],{"class":3808},"\"SpecSheet\"",[3416,33929,4384],{"class":3795},[3416,33931,33547],{"class":6387},[3416,33933,6391],{"class":3795},[3416,33935,33936],{"class":4368},"typeof",[3416,33938,6423],{"class":3795},[3416,33940,33941],{"class":6397},"SpecsJsonConverter",[3416,33943,33944],{"class":3795},"))]\n",[3416,33946,33947,33949,33952,33955,33957,33959,33961,33963,33965,33967],{"class":3418,"line":3579},[3416,33948,31235],{"class":4368},[3416,33950,33951],{"class":6397}," TechnicalSpecs",[3416,33953,33954],{"class":6387}," Specs",[3416,33956,6492],{"class":3795},[3416,33958,33661],{"class":4368},[3416,33960,8900],{"class":3795},[3416,33962,33666],{"class":4368},[3416,33964,33669],{"class":3795},[3416,33966,6394],{"class":4368},[3416,33968,6401],{"class":3795},[3416,33970,33971],{"class":3418,"line":3584},[3416,33972,3441],{"emptyLinePlaceholder":3440},[3416,33974,33975,33977,33980],{"class":3418,"line":3590},[3416,33976,9496],{"class":3795},[3416,33978,33979],{"class":6397},"DynamoDBIgnore",[3416,33981,18183],{"class":3795},[3416,33983,33984,33986,33988,33991,33993,33995,33997,33999,34001,34003,34005,34007],{"class":3418,"line":3596},[3416,33985,31235],{"class":4368},[3416,33987,31216],{"class":4368},[3416,33989,33990],{"class":6387}," MemoryCache",[3416,33992,6492],{"class":3795},[3416,33994,33661],{"class":4368},[3416,33996,8900],{"class":3795},[3416,33998,33666],{"class":4368},[3416,34000,33669],{"class":3795},[3416,34002,6461],{"class":4368},[3416,34004,4043],{"class":3795},[3416,34006,33676],{"class":6387},[3416,34008,11594],{"class":3795},[3416,34010,34011],{"class":3418,"line":3602},[3416,34012,3507],{"class":3795},[3416,34014,34015],{"class":3418,"line":3608},[3416,34016,3441],{"emptyLinePlaceholder":3440},[3416,34018,34019,34021,34023],{"class":3418,"line":3614},[3416,34020,31180],{"class":4368},[3416,34022,31183],{"class":4368},[3416,34024,34025],{"class":6397}," TechnicalSpecs\n",[3416,34027,34028],{"class":3418,"line":3620},[3416,34029,3796],{"class":3795},[3416,34031,34032,34034,34036,34039,34041,34043,34045,34047,34049,34051,34053,34055],{"class":3418,"line":3626},[3416,34033,31235],{"class":4368},[3416,34035,31216],{"class":4368},[3416,34037,34038],{"class":6387}," Manufacturer",[3416,34040,6492],{"class":3795},[3416,34042,33661],{"class":4368},[3416,34044,8900],{"class":3795},[3416,34046,33666],{"class":4368},[3416,34048,33669],{"class":3795},[3416,34050,6461],{"class":4368},[3416,34052,4043],{"class":3795},[3416,34054,33676],{"class":6387},[3416,34056,11594],{"class":3795},[3416,34058,34059,34061,34063,34066,34068,34070,34072,34074,34076,34078,34080,34082],{"class":3418,"line":3631},[3416,34060,31235],{"class":4368},[3416,34062,31216],{"class":4368},[3416,34064,34065],{"class":6387}," WarrantyMonths",[3416,34067,6492],{"class":3795},[3416,34069,33661],{"class":4368},[3416,34071,8900],{"class":3795},[3416,34073,33666],{"class":4368},[3416,34075,33669],{"class":3795},[3416,34077,6461],{"class":4368},[3416,34079,4043],{"class":3795},[3416,34081,33676],{"class":6387},[3416,34083,11594],{"class":3795},[3416,34085,34086],{"class":3418,"line":3636},[3416,34087,3507],{"class":3795},[4584,34089,34091],{"id":34090},"кастомний-конвертер-типів-ipropertyconverter","Кастомний конвертер типів (IPropertyConverter)",[3353,34093,34094,34095,10458],{},"Для збереження складних об'єктів або списків у вигляді одного атрибута (наприклад, JSON-рядка) необхідно імплементувати інтерфейс ",[3413,34096,34097],{},"IPropertyConverter",[3406,34099,34101],{"className":6375,"code":34100,"language":6377,"meta":30432,"style":3411},"using System.Text.Json;\nusing Amazon.DynamoDBv2.DataModel;\nusing Amazon.DynamoDBv2.DocumentModel;\n\npublic class SpecsJsonConverter : IPropertyConverter\n{\n    \u002F\u002F Серіалізація об'єкта C# у DynamoDBEntry\n    public DynamoDBEntry ToEntry(object value)\n    {\n        if (value is not TechnicalSpecs specs)\n            return new DynamoDBNull();\n\n        string json = JsonSerializer.Serialize(specs);\n        return new Primitive(json); \u002F\u002F Зберігаємо як звичайний рядок\n    }\n\n    \u002F\u002F Десеріалізація з DynamoDBEntry в об'єкт C#\n    public object FromEntry(DynamoDBEntry entry)\n    {\n        var primitive = entry as Primitive;\n        if (primitive == null || primitive.Value is not string json)\n            return new TechnicalSpecs();\n\n        return JsonSerializer.Deserialize\u003CTechnicalSpecs>(json) ?? new TechnicalSpecs();\n    }\n}\n",[3413,34102,34103,34122,34138,34154,34158,34172,34176,34181,34200,34204,34227,34239,34243,34268,34287,34291,34295,34300,34320,34324,34343,34375,34385,34389,34419,34423],{"__ignoreMap":3411},[3416,34104,34105,34107,34110,34112,34115,34117,34120],{"class":3418,"line":3419},[3416,34106,17433],{"class":11427},[3416,34108,34109],{"class":6397}," System",[3416,34111,4043],{"class":3795},[3416,34113,34114],{"class":6397},"Text",[3416,34116,4043],{"class":3795},[3416,34118,34119],{"class":6397},"Json",[3416,34121,11594],{"class":3795},[3416,34123,34124,34126,34128,34130,34132,34134,34136],{"class":3418,"line":3425},[3416,34125,17433],{"class":11427},[3416,34127,17436],{"class":6397},[3416,34129,4043],{"class":3795},[3416,34131,17441],{"class":6397},[3416,34133,4043],{"class":3795},[3416,34135,30594],{"class":6397},[3416,34137,11594],{"class":3795},[3416,34139,34140,34142,34144,34146,34148,34150,34152],{"class":3418,"line":3431},[3416,34141,17433],{"class":11427},[3416,34143,17436],{"class":6397},[3416,34145,4043],{"class":3795},[3416,34147,17441],{"class":6397},[3416,34149,4043],{"class":3795},[3416,34151,32570],{"class":6397},[3416,34153,11594],{"class":3795},[3416,34155,34156],{"class":3418,"line":3437},[3416,34157,3441],{"emptyLinePlaceholder":3440},[3416,34159,34160,34162,34164,34167,34169],{"class":3418,"line":3444},[3416,34161,31180],{"class":4368},[3416,34163,31183],{"class":4368},[3416,34165,34166],{"class":6397}," SpecsJsonConverter",[3416,34168,31747],{"class":3795},[3416,34170,34171],{"class":6397},"IPropertyConverter\n",[3416,34173,34174],{"class":3418,"line":3450},[3416,34175,3796],{"class":3795},[3416,34177,34178],{"class":3418,"line":3456},[3416,34179,34180],{"class":3789},"    \u002F\u002F Серіалізація об'єкта C# у DynamoDBEntry\n",[3416,34182,34183,34185,34188,34191,34193,34195,34198],{"class":3418,"line":3462},[3416,34184,31235],{"class":4368},[3416,34186,34187],{"class":6397}," DynamoDBEntry",[3416,34189,34190],{"class":6330}," ToEntry",[3416,34192,6423],{"class":3795},[3416,34194,24390],{"class":4368},[3416,34196,34197],{"class":6387}," value",[3416,34199,9656],{"class":3795},[3416,34201,34202],{"class":3418,"line":3468},[3416,34203,6474],{"class":3795},[3416,34205,34206,34209,34211,34214,34217,34220,34222,34225],{"class":3418,"line":3474},[3416,34207,34208],{"class":11427},"        if",[3416,34210,11431],{"class":3795},[3416,34212,34213],{"class":6387},"value",[3416,34215,34216],{"class":4368}," is",[3416,34218,34219],{"class":4368}," not",[3416,34221,33951],{"class":6397},[3416,34223,34224],{"class":6387}," specs",[3416,34226,9656],{"class":3795},[3416,34228,34229,34232,34234,34237],{"class":3418,"line":3480},[3416,34230,34231],{"class":11427},"            return",[3416,34233,30905],{"class":4368},[3416,34235,34236],{"class":6397}," DynamoDBNull",[3416,34238,6401],{"class":3795},[3416,34240,34241],{"class":3418,"line":3486},[3416,34242,3441],{"emptyLinePlaceholder":3440},[3416,34244,34245,34248,34251,34253,34256,34258,34261,34263,34266],{"class":3418,"line":3492},[3416,34246,34247],{"class":4368},"        string",[3416,34249,34250],{"class":6387}," json",[3416,34252,6391],{"class":3795},[3416,34254,34255],{"class":6387},"JsonSerializer",[3416,34257,4043],{"class":3795},[3416,34259,34260],{"class":6330},"Serialize",[3416,34262,6423],{"class":3795},[3416,34264,34265],{"class":6387},"specs",[3416,34267,11465],{"class":3795},[3416,34269,34270,34272,34274,34277,34279,34281,34284],{"class":3418,"line":3498},[3416,34271,30902],{"class":11427},[3416,34273,30905],{"class":4368},[3416,34275,34276],{"class":6397}," Primitive",[3416,34278,6423],{"class":3795},[3416,34280,3782],{"class":6387},[3416,34282,34283],{"class":3795},"); ",[3416,34285,34286],{"class":3789},"\u002F\u002F Зберігаємо як звичайний рядок\n",[3416,34288,34289],{"class":3418,"line":3504},[3416,34290,4167],{"class":3795},[3416,34292,34293],{"class":3418,"line":3510},[3416,34294,3441],{"emptyLinePlaceholder":3440},[3416,34296,34297],{"class":3418,"line":3515},[3416,34298,34299],{"class":3789},"    \u002F\u002F Десеріалізація з DynamoDBEntry в об'єкт C#\n",[3416,34301,34302,34304,34307,34310,34312,34315,34318],{"class":3418,"line":3521},[3416,34303,31235],{"class":4368},[3416,34305,34306],{"class":4368}," object",[3416,34308,34309],{"class":6330}," FromEntry",[3416,34311,6423],{"class":3795},[3416,34313,34314],{"class":6397},"DynamoDBEntry",[3416,34316,34317],{"class":6387}," entry",[3416,34319,9656],{"class":3795},[3416,34321,34322],{"class":3418,"line":3527},[3416,34323,6474],{"class":3795},[3416,34325,34326,34328,34331,34333,34336,34339,34341],{"class":3418,"line":3533},[3416,34327,30853],{"class":4368},[3416,34329,34330],{"class":6387}," primitive",[3416,34332,6391],{"class":3795},[3416,34334,34335],{"class":6387},"entry",[3416,34337,34338],{"class":4368}," as",[3416,34340,34276],{"class":6397},[3416,34342,11594],{"class":3795},[3416,34344,34345,34347,34349,34352,34354,34356,34358,34360,34362,34365,34367,34369,34371,34373],{"class":3418,"line":3539},[3416,34346,34208],{"class":11427},[3416,34348,11431],{"class":3795},[3416,34350,34351],{"class":6387},"primitive",[3416,34353,11488],{"class":3795},[3416,34355,30944],{"class":4368},[3416,34357,27682],{"class":3795},[3416,34359,34351],{"class":6387},[3416,34361,4043],{"class":3795},[3416,34363,34364],{"class":6387},"Value",[3416,34366,34216],{"class":4368},[3416,34368,34219],{"class":4368},[3416,34370,31216],{"class":4368},[3416,34372,34250],{"class":6387},[3416,34374,9656],{"class":3795},[3416,34376,34377,34379,34381,34383],{"class":3418,"line":3545},[3416,34378,34231],{"class":11427},[3416,34380,30905],{"class":4368},[3416,34382,33951],{"class":6397},[3416,34384,6401],{"class":3795},[3416,34386,34387],{"class":3418,"line":3551},[3416,34388,3441],{"emptyLinePlaceholder":3440},[3416,34390,34391,34393,34396,34398,34401,34403,34406,34408,34410,34413,34415,34417],{"class":3418,"line":3557},[3416,34392,30902],{"class":11427},[3416,34394,34395],{"class":6387}," JsonSerializer",[3416,34397,4043],{"class":3795},[3416,34399,34400],{"class":6330},"Deserialize",[3416,34402,5861],{"class":3795},[3416,34404,34405],{"class":6397},"TechnicalSpecs",[3416,34407,30838],{"class":3795},[3416,34409,3782],{"class":6387},[3416,34411,34412],{"class":3795},") ?? ",[3416,34414,6394],{"class":4368},[3416,34416,33951],{"class":6397},[3416,34418,6401],{"class":3795},[3416,34420,34421],{"class":3418,"line":3563},[3416,34422,4167],{"class":3795},[3416,34424,34425],{"class":3418,"line":3569},[3416,34426,3507],{"class":3795},[4584,34428,34430],{"id":34429},"методи-інтерфейсу-ipropertyconverter","Методи інтерфейсу IPropertyConverter",[24357,34432,34433,34450],{},[24360,34434,34436,34437,34439,34440,4384,34442,4384,34444,4039,34447,13590],{"name":34435,"type":31008},"ToEntry(object value)","Серіалізує властивість C# класу в об'єкт ",[3413,34438,34314],{}," (наприклад, ",[3413,34441,30362],{},[3413,34443,30253],{},[3413,34445,34446],{},"DynamoDBNull",[3413,34448,34449],{},"DynamoDBList",[24360,34451,34453,34454,34456],{"name":34452,"type":31008},"FromEntry(DynamoDBEntry entry)","Десеріалізує об'єкт ",[3413,34455,34314],{}," з бази даних у вихідний тип властивості C#.",[4584,34458,34460],{"id":34459},"реалізація-crud-репозиторію-через-opm","Реалізація CRUD Репозиторію через OPM",[3406,34462,34464],{"className":6375,"code":34463,"language":6377,"meta":30432,"style":3411},"using Amazon.DynamoDBv2.DataModel;\n\npublic class DynamoDBCatalogRepository\n{\n    private readonly IDynamoDBContext _context;\n\n    public DynamoDBCatalogRepository(IDynamoDBContext context) => _context = context;\n\n    \u002F\u002F ── Load: Точкове зчитування (GetItem) ──────────────────────────────────────\n    public async Task\u003CCatalogItem?> GetByIdAsync(string categoryId, string sku)\n    {\n        return await _context.LoadAsync\u003CCatalogItem>(categoryId, sku);\n    }\n\n    \u002F\u002F ── Save: Збереження або перезапис (Upsert) ─────────────────────────────────\n    public async Task SaveItemAsync(CatalogItem item)\n    {\n        \u002F\u002F Метод SaveAsync автоматично аналізує [DynamoDBVersion].\n        \u002F\u002F Якщо запис існує, версія звіриться і збільшиться на 1.\n        \u002F\u002F При конфлікті виникне AmazonDynamoDBException із кодом помилки ConditionalCheckFailedException.\n        try\n        {\n            await _context.SaveAsync(item);\n        }\n        catch (AmazonDynamoDBException ex) when (ex.ErrorCode == \"ConditionalCheckFailedException\")\n        {\n            throw new InvalidOperationException(\"Запис був змінений іншим користувачем. Оновіть дані.\", ex);\n        }\n    }\n\n    \u002F\u002F ── Delete: Видалення сутності ──────────────────────────────────────────────\n    public async Task DeleteItemAsync(string categoryId, string sku)\n    {\n        await _context.DeleteAsync\u003CCatalogItem>(categoryId, sku);\n    }\n\n    \u002F\u002F ── Query через GSI: Зчитування за альтернативним індексом ───────────────────\n    public async Task\u003CIEnumerable\u003CCatalogItem>> GetBySupplierAsync(string supplierId)\n    {\n        var config = new DynamoDBOperationConfig\n        {\n            IndexName = \"Supplier-index\",\n            ConsistentRead = false \u002F\u002F На GSI допускається лише Eventually Consistent Read\n        };\n\n        \u002F\u002F QueryAsync повертає об'єкт AsyncSearch\u003CT>, який виступає ітератором\n        AsyncSearch\u003CCatalogItem> search = _context.QueryAsync\u003CCatalogItem>(supplierId, config);\n        \n        \u002F\u002F Зчитуємо всі сторінки даних, які залишилися\n        return await search.GetRemainingAsync();\n    }\n}\n",[3413,34465,34466,34482,34486,34495,34499,34513,34517,34543,34547,34552,34584,34588,34615,34619,34623,34628,34648,34652,34657,34662,34667,34672,34676,34694,34698,34734,34738,34759,34763,34767,34771,34776,34801,34805,34830,34834,34838,34843,34875,34879,34892,34896,34906,34917,34921,34925,34930,34966,34971,34976,34991,34995],{"__ignoreMap":3411},[3416,34467,34468,34470,34472,34474,34476,34478,34480],{"class":3418,"line":3419},[3416,34469,17433],{"class":11427},[3416,34471,17436],{"class":6397},[3416,34473,4043],{"class":3795},[3416,34475,17441],{"class":6397},[3416,34477,4043],{"class":3795},[3416,34479,30594],{"class":6397},[3416,34481,11594],{"class":3795},[3416,34483,34484],{"class":3418,"line":3425},[3416,34485,3441],{"emptyLinePlaceholder":3440},[3416,34487,34488,34490,34492],{"class":3418,"line":3431},[3416,34489,31180],{"class":4368},[3416,34491,31183],{"class":4368},[3416,34493,34494],{"class":6397}," DynamoDBCatalogRepository\n",[3416,34496,34497],{"class":3418,"line":3437},[3416,34498,3796],{"class":3795},[3416,34500,34501,34503,34505,34508,34511],{"class":3418,"line":3444},[3416,34502,31195],{"class":4368},[3416,34504,31198],{"class":4368},[3416,34506,34507],{"class":6397}," IDynamoDBContext",[3416,34509,34510],{"class":6387}," _context",[3416,34512,11594],{"class":3795},[3416,34514,34515],{"class":3418,"line":3450},[3416,34516,3441],{"emptyLinePlaceholder":3440},[3416,34518,34519,34521,34524,34526,34528,34531,34533,34536,34538,34541],{"class":3418,"line":3456},[3416,34520,31235],{"class":4368},[3416,34522,34523],{"class":6330}," DynamoDBCatalogRepository",[3416,34525,6423],{"class":3795},[3416,34527,30735],{"class":6397},[3416,34529,34530],{"class":6387}," context",[3416,34532,31247],{"class":3795},[3416,34534,34535],{"class":6387},"_context",[3416,34537,6391],{"class":3795},[3416,34539,34540],{"class":6387},"context",[3416,34542,11594],{"class":3795},[3416,34544,34545],{"class":3418,"line":3462},[3416,34546,3441],{"emptyLinePlaceholder":3440},[3416,34548,34549],{"class":3418,"line":3468},[3416,34550,34551],{"class":3789},"    \u002F\u002F ── Load: Точкове зчитування (GetItem) ──────────────────────────────────────\n",[3416,34553,34554,34556,34558,34560,34562,34565,34567,34570,34572,34574,34576,34578,34580,34582],{"class":3418,"line":3474},[3416,34555,31235],{"class":4368},[3416,34557,31273],{"class":4368},[3416,34559,11606],{"class":6397},[3416,34561,5861],{"class":3795},[3416,34563,34564],{"class":6397},"CatalogItem",[3416,34566,32880],{"class":3795},[3416,34568,34569],{"class":6330},"GetByIdAsync",[3416,34571,6423],{"class":3795},[3416,34573,6461],{"class":4368},[3416,34575,31285],{"class":6387},[3416,34577,4384],{"class":3795},[3416,34579,6461],{"class":4368},[3416,34581,31292],{"class":6387},[3416,34583,9656],{"class":3795},[3416,34585,34586],{"class":3418,"line":3480},[3416,34587,6474],{"class":3795},[3416,34589,34590,34592,34594,34596,34598,34601,34603,34605,34607,34609,34611,34613],{"class":3418,"line":3486},[3416,34591,30902],{"class":11427},[3416,34593,32913],{"class":4368},[3416,34595,34510],{"class":6387},[3416,34597,4043],{"class":3795},[3416,34599,34600],{"class":6330},"LoadAsync",[3416,34602,5861],{"class":3795},[3416,34604,34564],{"class":6397},[3416,34606,30838],{"class":3795},[3416,34608,31388],{"class":6387},[3416,34610,4384],{"class":3795},[3416,34612,31412],{"class":6387},[3416,34614,11465],{"class":3795},[3416,34616,34617],{"class":3418,"line":3492},[3416,34618,4167],{"class":3795},[3416,34620,34621],{"class":3418,"line":3498},[3416,34622,3441],{"emptyLinePlaceholder":3440},[3416,34624,34625],{"class":3418,"line":3504},[3416,34626,34627],{"class":3789},"    \u002F\u002F ── Save: Збереження або перезапис (Upsert) ─────────────────────────────────\n",[3416,34629,34630,34632,34634,34636,34639,34641,34643,34646],{"class":3418,"line":3510},[3416,34631,31235],{"class":4368},[3416,34633,31273],{"class":4368},[3416,34635,11606],{"class":6397},[3416,34637,34638],{"class":6330}," SaveItemAsync",[3416,34640,6423],{"class":3795},[3416,34642,34564],{"class":6397},[3416,34644,34645],{"class":6387}," item",[3416,34647,9656],{"class":3795},[3416,34649,34650],{"class":3418,"line":3515},[3416,34651,6474],{"class":3795},[3416,34653,34654],{"class":3418,"line":3521},[3416,34655,34656],{"class":3789},"        \u002F\u002F Метод SaveAsync автоматично аналізує [DynamoDBVersion].\n",[3416,34658,34659],{"class":3418,"line":3527},[3416,34660,34661],{"class":3789},"        \u002F\u002F Якщо запис існує, версія звіриться і збільшиться на 1.\n",[3416,34663,34664],{"class":3418,"line":3533},[3416,34665,34666],{"class":3789},"        \u002F\u002F При конфлікті виникне AmazonDynamoDBException із кодом помилки ConditionalCheckFailedException.\n",[3416,34668,34669],{"class":3418,"line":3539},[3416,34670,34671],{"class":11427},"        try\n",[3416,34673,34674],{"class":3418,"line":3545},[3416,34675,8611],{"class":3795},[3416,34677,34678,34681,34683,34685,34687,34689,34692],{"class":3418,"line":3551},[3416,34679,34680],{"class":4368},"            await",[3416,34682,34510],{"class":6387},[3416,34684,4043],{"class":3795},[3416,34686,33508],{"class":6330},[3416,34688,6423],{"class":3795},[3416,34690,34691],{"class":6387},"item",[3416,34693,11465],{"class":3795},[3416,34695,34696],{"class":3418,"line":3557},[3416,34697,8533],{"class":3795},[3416,34699,34700,34703,34705,34708,34711,34714,34717,34719,34722,34724,34727,34729,34732],{"class":3418,"line":3563},[3416,34701,34702],{"class":11427},"        catch",[3416,34704,11431],{"class":3795},[3416,34706,34707],{"class":6397},"AmazonDynamoDBException",[3416,34709,34710],{"class":6387}," ex",[3416,34712,34713],{"class":3795},") ",[3416,34715,34716],{"class":11427},"when",[3416,34718,11431],{"class":3795},[3416,34720,34721],{"class":6387},"ex",[3416,34723,4043],{"class":3795},[3416,34725,34726],{"class":6387},"ErrorCode",[3416,34728,11488],{"class":3795},[3416,34730,34731],{"class":3808},"\"ConditionalCheckFailedException\"",[3416,34733,9656],{"class":3795},[3416,34735,34736],{"class":3418,"line":3569},[3416,34737,8611],{"class":3795},[3416,34739,34740,34743,34745,34748,34750,34753,34755,34757],{"class":3418,"line":3574},[3416,34741,34742],{"class":11427},"            throw",[3416,34744,30905],{"class":4368},[3416,34746,34747],{"class":6397}," InvalidOperationException",[3416,34749,6423],{"class":3795},[3416,34751,34752],{"class":3808},"\"Запис був змінений іншим користувачем. Оновіть дані.\"",[3416,34754,4384],{"class":3795},[3416,34756,34721],{"class":6387},[3416,34758,11465],{"class":3795},[3416,34760,34761],{"class":3418,"line":3579},[3416,34762,8533],{"class":3795},[3416,34764,34765],{"class":3418,"line":3584},[3416,34766,4167],{"class":3795},[3416,34768,34769],{"class":3418,"line":3590},[3416,34770,3441],{"emptyLinePlaceholder":3440},[3416,34772,34773],{"class":3418,"line":3596},[3416,34774,34775],{"class":3789},"    \u002F\u002F ── Delete: Видалення сутності ──────────────────────────────────────────────\n",[3416,34777,34778,34780,34782,34784,34787,34789,34791,34793,34795,34797,34799],{"class":3418,"line":3602},[3416,34779,31235],{"class":4368},[3416,34781,31273],{"class":4368},[3416,34783,11606],{"class":6397},[3416,34785,34786],{"class":6330}," DeleteItemAsync",[3416,34788,6423],{"class":3795},[3416,34790,6461],{"class":4368},[3416,34792,31285],{"class":6387},[3416,34794,4384],{"class":3795},[3416,34796,6461],{"class":4368},[3416,34798,31292],{"class":6387},[3416,34800,9656],{"class":3795},[3416,34802,34803],{"class":3418,"line":3608},[3416,34804,6474],{"class":3795},[3416,34806,34807,34809,34811,34813,34816,34818,34820,34822,34824,34826,34828],{"class":3418,"line":3614},[3416,34808,31512],{"class":4368},[3416,34810,34510],{"class":6387},[3416,34812,4043],{"class":3795},[3416,34814,34815],{"class":6330},"DeleteAsync",[3416,34817,5861],{"class":3795},[3416,34819,34564],{"class":6397},[3416,34821,30838],{"class":3795},[3416,34823,31388],{"class":6387},[3416,34825,4384],{"class":3795},[3416,34827,31412],{"class":6387},[3416,34829,11465],{"class":3795},[3416,34831,34832],{"class":3418,"line":3620},[3416,34833,4167],{"class":3795},[3416,34835,34836],{"class":3418,"line":3626},[3416,34837,3441],{"emptyLinePlaceholder":3440},[3416,34839,34840],{"class":3418,"line":3631},[3416,34841,34842],{"class":3789},"    \u002F\u002F ── Query через GSI: Зчитування за альтернативним індексом ───────────────────\n",[3416,34844,34845,34847,34849,34851,34853,34856,34858,34860,34863,34866,34868,34870,34873],{"class":3418,"line":3636},[3416,34846,31235],{"class":4368},[3416,34848,31273],{"class":4368},[3416,34850,11606],{"class":6397},[3416,34852,5861],{"class":3795},[3416,34854,34855],{"class":6397},"IEnumerable",[3416,34857,5861],{"class":3795},[3416,34859,34564],{"class":6397},[3416,34861,34862],{"class":3795},">> ",[3416,34864,34865],{"class":6330},"GetBySupplierAsync",[3416,34867,6423],{"class":3795},[3416,34869,6461],{"class":4368},[3416,34871,34872],{"class":6387}," supplierId",[3416,34874,9656],{"class":3795},[3416,34876,34877],{"class":3418,"line":3641},[3416,34878,6474],{"class":3795},[3416,34880,34881,34883,34885,34887,34889],{"class":3418,"line":3647},[3416,34882,30853],{"class":4368},[3416,34884,30856],{"class":6387},[3416,34886,6391],{"class":3795},[3416,34888,6394],{"class":4368},[3416,34890,34891],{"class":6397}," DynamoDBOperationConfig\n",[3416,34893,34894],{"class":3418,"line":3653},[3416,34895,8611],{"class":3795},[3416,34897,34898,34900,34902,34904],{"class":3418,"line":3659},[3416,34899,15683],{"class":6387},[3416,34901,6391],{"class":3795},[3416,34903,33828],{"class":3808},[3416,34905,3812],{"class":3795},[3416,34907,34908,34910,34912,34914],{"class":3418,"line":3665},[3416,34909,31685],{"class":6387},[3416,34911,6391],{"class":3795},[3416,34913,4042],{"class":4368},[3416,34915,34916],{"class":3789}," \u002F\u002F На GSI допускається лише Eventually Consistent Read\n",[3416,34918,34919],{"class":3418,"line":3671},[3416,34920,30897],{"class":3795},[3416,34922,34923],{"class":3418,"line":3677},[3416,34924,3441],{"emptyLinePlaceholder":3440},[3416,34926,34927],{"class":3418,"line":3683},[3416,34928,34929],{"class":3789},"        \u002F\u002F QueryAsync повертає об'єкт AsyncSearch\u003CT>, який виступає ітератором\n",[3416,34931,34932,34935,34937,34939,34941,34943,34945,34947,34949,34951,34953,34955,34957,34960,34962,34964],{"class":3418,"line":3688},[3416,34933,34934],{"class":6397},"        AsyncSearch",[3416,34936,5861],{"class":3795},[3416,34938,34564],{"class":6397},[3416,34940,32709],{"class":3795},[3416,34942,33247],{"class":6387},[3416,34944,6391],{"class":3795},[3416,34946,34535],{"class":6387},[3416,34948,4043],{"class":3795},[3416,34950,7748],{"class":6330},[3416,34952,5861],{"class":3795},[3416,34954,34564],{"class":6397},[3416,34956,30838],{"class":3795},[3416,34958,34959],{"class":6387},"supplierId",[3416,34961,4384],{"class":3795},[3416,34963,30912],{"class":6387},[3416,34965,11465],{"class":3795},[3416,34967,34968],{"class":3418,"line":3693},[3416,34969,34970],{"class":3795},"        \n",[3416,34972,34973],{"class":3418,"line":3698},[3416,34974,34975],{"class":3789},"        \u002F\u002F Зчитуємо всі сторінки даних, які залишилися\n",[3416,34977,34978,34980,34982,34984,34986,34989],{"class":3418,"line":3704},[3416,34979,30902],{"class":11427},[3416,34981,32913],{"class":4368},[3416,34983,33218],{"class":6387},[3416,34985,4043],{"class":3795},[3416,34987,34988],{"class":6330},"GetRemainingAsync",[3416,34990,6401],{"class":3795},[3416,34992,34993],{"class":3418,"line":3710},[3416,34994,4167],{"class":3795},[3416,34996,34997],{"class":3418,"line":3715},[3416,34998,3507],{"class":3795},[3720,35000],{},[3727,35002,35004],{"id":35003},"_6-атомарні-транзакції-та-пакетна-обробка","6. Атомарні транзакції та пакетна обробка",[3353,35006,35007],{},"Для забезпечення максимальної продуктивності та надійності даних SDK надає механізми пакетної роботи та транзакційності на рівні ACID.",[4584,35009,35011],{"id":35010},"пакетні-операції-batch-operations","Пакетні операції (Batch Operations)",[3353,35013,35014,35015,35018,35019,35022],{},"Пакетний запис (",[3413,35016,35017],{},"BatchWrite",") та зчитування (",[3413,35020,35021],{},"BatchGet",") дозволяють об'єднати до 25 операцій запису\u002Fвидалення та до 100 операцій читання в один HTTP-запит. Це значно знижує RTT (Round Trip Time).",[3406,35024,35026],{"className":6375,"code":35025,"language":6377,"meta":30432,"style":3411},"\u002F\u002F Пакетний запис сутностей через ORM Context\npublic async Task SaveBatchAsync(List\u003CCatalogItem> items)\n{\n    var batchWrite = _context.CreateBatchWrite\u003CCatalogItem>();\n    \n    \u002F\u002F Додаємо елементи до пакету\n    batchWrite.AddPutItems(items);\n    \n    \u002F\u002F Можна комбінувати з видаленням\n    batchWrite.AddDeleteKey(\"Books\", \"BOOK-DELETE-1\");\n\n    await batchWrite.ExecuteAsync();\n}\n",[3413,35027,35028,35033,35059,35063,35085,35090,35095,35111,35115,35120,35140,35144,35157],{"__ignoreMap":3411},[3416,35029,35030],{"class":3418,"line":3419},[3416,35031,35032],{"class":3789},"\u002F\u002F Пакетний запис сутностей через ORM Context\n",[3416,35034,35035,35037,35039,35041,35044,35046,35048,35050,35052,35054,35057],{"class":3418,"line":3425},[3416,35036,31180],{"class":4368},[3416,35038,31273],{"class":4368},[3416,35040,11606],{"class":6397},[3416,35042,35043],{"class":6330}," SaveBatchAsync",[3416,35045,6423],{"class":3795},[3416,35047,9173],{"class":6397},[3416,35049,5861],{"class":3795},[3416,35051,34564],{"class":6397},[3416,35053,32709],{"class":3795},[3416,35055,35056],{"class":6387},"items",[3416,35058,9656],{"class":3795},[3416,35060,35061],{"class":3418,"line":3431},[3416,35062,3796],{"class":3795},[3416,35064,35065,35067,35070,35072,35074,35076,35079,35081,35083],{"class":3418,"line":3437},[3416,35066,11444],{"class":4368},[3416,35068,35069],{"class":6387}," batchWrite",[3416,35071,6391],{"class":3795},[3416,35073,34535],{"class":6387},[3416,35075,4043],{"class":3795},[3416,35077,35078],{"class":6330},"CreateBatchWrite",[3416,35080,5861],{"class":3795},[3416,35082,34564],{"class":6397},[3416,35084,30708],{"class":3795},[3416,35086,35087],{"class":3418,"line":3444},[3416,35088,35089],{"class":3795},"    \n",[3416,35091,35092],{"class":3418,"line":3450},[3416,35093,35094],{"class":3789},"    \u002F\u002F Додаємо елементи до пакету\n",[3416,35096,35097,35100,35102,35105,35107,35109],{"class":3418,"line":3456},[3416,35098,35099],{"class":6387},"    batchWrite",[3416,35101,4043],{"class":3795},[3416,35103,35104],{"class":6330},"AddPutItems",[3416,35106,6423],{"class":3795},[3416,35108,35056],{"class":6387},[3416,35110,11465],{"class":3795},[3416,35112,35113],{"class":3418,"line":3462},[3416,35114,35089],{"class":3795},[3416,35116,35117],{"class":3418,"line":3468},[3416,35118,35119],{"class":3789},"    \u002F\u002F Можна комбінувати з видаленням\n",[3416,35121,35122,35124,35126,35129,35131,35133,35135,35138],{"class":3418,"line":3474},[3416,35123,35099],{"class":6387},[3416,35125,4043],{"class":3795},[3416,35127,35128],{"class":6330},"AddDeleteKey",[3416,35130,6423],{"class":3795},[3416,35132,33096],{"class":3808},[3416,35134,4384],{"class":3795},[3416,35136,35137],{"class":3808},"\"BOOK-DELETE-1\"",[3416,35139,11465],{"class":3795},[3416,35141,35142],{"class":3418,"line":3480},[3416,35143,3441],{"emptyLinePlaceholder":3440},[3416,35145,35146,35148,35150,35152,35155],{"class":3418,"line":3486},[3416,35147,11603],{"class":4368},[3416,35149,35069],{"class":6387},[3416,35151,4043],{"class":3795},[3416,35153,35154],{"class":6330},"ExecuteAsync",[3416,35156,6401],{"class":3795},[3416,35158,35159],{"class":3418,"line":3492},[3416,35160,3507],{"class":3795},[22319,35162,35163],{},[3353,35164,35165,35167,35168,35170,35171,35174,35175,35178],{},[3416,35166,22325],{},"\nПри використанні пакетних запитів DynamoDB може повернути частину елементів як необроблені (",[3413,35169,8988],{}," \u002F ",[3413,35172,35173],{},"UnprocessedKeys",") у випадку вичерпання виділеної WCU\u002FRCU ліміту. Низькорівневий API вимагає ручної обробки та повторних спроб у циклі. ",[3413,35176,35177],{},"IDynamoDBContext.ExecuteAsync()"," намагається обробити частину ретриів самостійно, але у критичних сценаріях розробник має відслідковувати статус відповіді.",[4584,35180,35182],{"id":35181},"атомарні-acid-транзакції","Атомарні ACID Транзакції",[3353,35184,35185,35186,35188,35189,4043],{},"Транзакції гарантують повне виконання (All-or-Nothing) до 100 операцій (або 4 МБ об'єму). Вони реалізуються виключно через ",[3363,35187,30219],{}," клієнта ",[3413,35190,30226],{},[3353,35192,35193],{},"Розглянемо класичний приклад переказу коштів або замовлення товару з валідацією залишків на складі:",[3406,35195,35197],{"className":6375,"code":35196,"language":6377,"meta":30432,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\npublic class TransactionService\n{\n    private readonly IAmazonDynamoDB _client;\n\n    public TransactionService(IAmazonDynamoDB client) => _client = client;\n\n    public async Task ProcessOrderAsync(string customerId, string productId, int qty, decimal price)\n    {\n        string orderId = $\"ORD-{Guid.NewGuid():N}\";\n\n        var request = new TransactWriteItemsRequest\n        {\n            TransactItems = new List\u003CTransactWriteItem>\n            {\n                \u002F\u002F 1. Валідація та оновлення залишків на складі (Умова: склад має достатньо товару)\n                new()\n                {\n                    Update = new Update\n                    {\n                        TableName = \"Warehouse\",\n                        Key = new Dictionary\u003Cstring, AttributeValue>\n                        {\n                            { \"ProductId\", new AttributeValue { S = productId } }\n                        },\n                        UpdateExpression = \"SET Stock = Stock - :qty\",\n                        ConditionExpression = \"Stock >= :qty\", \u002F\u002F Перевірка умови\n                        ExpressionAttributeValues = new Dictionary\u003Cstring, AttributeValue>\n                        {\n                            { \":qty\", new AttributeValue { N = qty.ToString() } }\n                        }\n                    }\n                },\n                \u002F\u002F 2. Створення нового запису замовлення (Умова: таке замовлення ще не існує)\n                new()\n                {\n                    Put = new Put\n                    {\n                        TableName = \"Orders\",\n                        ConditionExpression = \"attribute_not_exists(OrderId)\",\n                        Item = new Dictionary\u003Cstring, AttributeValue>\n                        {\n                            { \"CustomerId\", new AttributeValue { S = customerId } },\n                            { \"OrderId\", new AttributeValue { S = orderId } },\n                            { \"Quantity\", new AttributeValue { N = qty.ToString() } },\n                            { \"TotalAmount\", new AttributeValue { N = (qty * price).ToString(\"F2\") } },\n                            { \"Status\", new AttributeValue { S = \"PAID\" } }\n                        }\n                    }\n                }\n            }\n        };\n\n        try\n        {\n            await _client.TransactWriteItemsAsync(request);\n        }\n        catch (TransactionCanceledException ex)\n        {\n            \u002F\u002F Обробка причин скасування транзакції\n            var reasons = ex.CancellationReasons\n                .Select((r, idx) => $\"Елемент {idx}: {r.Code} (Опис: {r.Message})\");\n            \n            throw new InvalidOperationException($\"Транзакцію скасовано. Причини:\\\\n{string.Join(\"\\\\n\", reasons)}\", ex);\n        }\n    }\n}\n",[3413,35198,35199,35211,35227,35231,35240,35244,35256,35260,35283,35287,35327,35331,35366,35370,35382,35386,35403,35407,35412,35418,35422,35433,35437,35449,35469,35473,35496,35501,35513,35528,35549,35553,35580,35584,35588,35592,35597,35603,35607,35618,35622,35632,35643,35663,35667,35690,35713,35739,35775,35797,35801,35805,35809,35813,35817,35821,35825,35829,35845,35849,35862,35866,35871,35888,35950,35955,36008,36012,36016],{"__ignoreMap":3411},[3416,35200,35201,35203,35205,35207,35209],{"class":3418,"line":3419},[3416,35202,17433],{"class":11427},[3416,35204,17436],{"class":6397},[3416,35206,4043],{"class":3795},[3416,35208,17441],{"class":6397},[3416,35210,11594],{"class":3795},[3416,35212,35213,35215,35217,35219,35221,35223,35225],{"class":3418,"line":3425},[3416,35214,17433],{"class":11427},[3416,35216,17436],{"class":6397},[3416,35218,4043],{"class":3795},[3416,35220,17441],{"class":6397},[3416,35222,4043],{"class":3795},[3416,35224,17458],{"class":6397},[3416,35226,11594],{"class":3795},[3416,35228,35229],{"class":3418,"line":3431},[3416,35230,3441],{"emptyLinePlaceholder":3440},[3416,35232,35233,35235,35237],{"class":3418,"line":3437},[3416,35234,31180],{"class":4368},[3416,35236,31183],{"class":4368},[3416,35238,35239],{"class":6397}," TransactionService\n",[3416,35241,35242],{"class":3418,"line":3444},[3416,35243,3796],{"class":3795},[3416,35245,35246,35248,35250,35252,35254],{"class":3418,"line":3450},[3416,35247,31195],{"class":4368},[3416,35249,31198],{"class":4368},[3416,35251,31201],{"class":6397},[3416,35253,31204],{"class":6387},[3416,35255,11594],{"class":3795},[3416,35257,35258],{"class":3418,"line":3456},[3416,35259,3441],{"emptyLinePlaceholder":3440},[3416,35261,35262,35264,35267,35269,35271,35273,35275,35277,35279,35281],{"class":3418,"line":3462},[3416,35263,31235],{"class":4368},[3416,35265,35266],{"class":6330}," TransactionService",[3416,35268,6423],{"class":3795},[3416,35270,30705],{"class":6397},[3416,35272,6388],{"class":6387},[3416,35274,31247],{"class":3795},[3416,35276,31250],{"class":6387},[3416,35278,6391],{"class":3795},[3416,35280,31255],{"class":6387},[3416,35282,11594],{"class":3795},[3416,35284,35285],{"class":3418,"line":3468},[3416,35286,3441],{"emptyLinePlaceholder":3440},[3416,35288,35289,35291,35293,35295,35298,35300,35302,35305,35307,35309,35312,35314,35316,35319,35321,35323,35325],{"class":3418,"line":3474},[3416,35290,31235],{"class":4368},[3416,35292,31273],{"class":4368},[3416,35294,11606],{"class":6397},[3416,35296,35297],{"class":6330}," ProcessOrderAsync",[3416,35299,6423],{"class":3795},[3416,35301,6461],{"class":4368},[3416,35303,35304],{"class":6387}," customerId",[3416,35306,4384],{"class":3795},[3416,35308,6461],{"class":4368},[3416,35310,35311],{"class":6387}," productId",[3416,35313,4384],{"class":3795},[3416,35315,28530],{"class":4368},[3416,35317,35318],{"class":6387}," qty",[3416,35320,4384],{"class":3795},[3416,35322,31304],{"class":4368},[3416,35324,31307],{"class":6387},[3416,35326,9656],{"class":3795},[3416,35328,35329],{"class":3418,"line":3480},[3416,35330,6474],{"class":3795},[3416,35332,35333,35335,35338,35340,35343,35345,35348,35350,35353,35356,35358,35360,35362,35364],{"class":3418,"line":3486},[3416,35334,34247],{"class":4368},[3416,35336,35337],{"class":6387}," orderId",[3416,35339,6391],{"class":3795},[3416,35341,35342],{"class":3808},"$\"ORD-",[3416,35344,11177],{"class":11533},[3416,35346,35347],{"class":6387},"Guid",[3416,35349,4043],{"class":11533},[3416,35351,35352],{"class":6330},"NewGuid",[3416,35354,35355],{"class":11533},"()",[3416,35357,10458],{"class":3795},[3416,35359,10168],{"class":6387},[3416,35361,11302],{"class":11533},[3416,35363,24569],{"class":3808},[3416,35365,11594],{"class":3795},[3416,35367,35368],{"class":3418,"line":3492},[3416,35369,3441],{"emptyLinePlaceholder":3440},[3416,35371,35372,35374,35376,35378,35380],{"class":3418,"line":3498},[3416,35373,30853],{"class":4368},[3416,35375,31320],{"class":6387},[3416,35377,6391],{"class":3795},[3416,35379,6394],{"class":4368},[3416,35381,9855],{"class":6397},[3416,35383,35384],{"class":3418,"line":3504},[3416,35385,8611],{"class":3795},[3416,35387,35388,35391,35393,35395,35397,35399,35401],{"class":3418,"line":3510},[3416,35389,35390],{"class":6387},"            TransactItems",[3416,35392,6391],{"class":3795},[3416,35394,6394],{"class":4368},[3416,35396,8640],{"class":6397},[3416,35398,5861],{"class":3795},[3416,35400,9875],{"class":6397},[3416,35402,6469],{"class":3795},[3416,35404,35405],{"class":3418,"line":3515},[3416,35406,8628],{"class":3795},[3416,35408,35409],{"class":3418,"line":3521},[3416,35410,35411],{"class":3789},"                \u002F\u002F 1. Валідація та оновлення залишків на складі (Умова: склад має достатньо товару)\n",[3416,35413,35414,35416],{"class":3418,"line":3527},[3416,35415,9213],{"class":4368},[3416,35417,17625],{"class":3795},[3416,35419,35420],{"class":3418,"line":3533},[3416,35421,8661],{"class":3795},[3416,35423,35424,35427,35429,35431],{"class":3418,"line":3539},[3416,35425,35426],{"class":6387},"                    Update",[3416,35428,6391],{"class":3795},[3416,35430,6394],{"class":4368},[3416,35432,10047],{"class":6397},[3416,35434,35435],{"class":3418,"line":3545},[3416,35436,8683],{"class":3795},[3416,35438,35439,35442,35444,35447],{"class":3418,"line":3551},[3416,35440,35441],{"class":6387},"                        TableName",[3416,35443,6391],{"class":3795},[3416,35445,35446],{"class":3808},"\"Warehouse\"",[3416,35448,3812],{"class":3795},[3416,35450,35451,35453,35455,35457,35459,35461,35463,35465,35467],{"class":3418,"line":3557},[3416,35452,9375],{"class":6387},[3416,35454,6391],{"class":3795},[3416,35456,6394],{"class":4368},[3416,35458,6456],{"class":6397},[3416,35460,5861],{"class":3795},[3416,35462,6461],{"class":4368},[3416,35464,4384],{"class":3795},[3416,35466,6466],{"class":6397},[3416,35468,6469],{"class":3795},[3416,35470,35471],{"class":3418,"line":3563},[3416,35472,9262],{"class":3795},[3416,35474,35475,35477,35479,35481,35483,35485,35487,35489,35491,35494],{"class":3418,"line":3569},[3416,35476,9267],{"class":3795},[3416,35478,26075],{"class":3808},[3416,35480,4384],{"class":3795},[3416,35482,6394],{"class":4368},[3416,35484,6489],{"class":6397},[3416,35486,6492],{"class":3795},[3416,35488,6495],{"class":6387},[3416,35490,6391],{"class":3795},[3416,35492,35493],{"class":6387},"productId",[3416,35495,6528],{"class":3795},[3416,35497,35498],{"class":3418,"line":3574},[3416,35499,35500],{"class":3795},"                        },\n",[3416,35502,35503,35506,35508,35511],{"class":3418,"line":3579},[3416,35504,35505],{"class":6387},"                        UpdateExpression",[3416,35507,6391],{"class":3795},[3416,35509,35510],{"class":3808},"\"SET Stock = Stock - :qty\"",[3416,35512,3812],{"class":3795},[3416,35514,35515,35518,35520,35523,35525],{"class":3418,"line":3584},[3416,35516,35517],{"class":6387},"                        ConditionExpression",[3416,35519,6391],{"class":3795},[3416,35521,35522],{"class":3808},"\"Stock >= :qty\"",[3416,35524,4384],{"class":3795},[3416,35526,35527],{"class":3789},"\u002F\u002F Перевірка умови\n",[3416,35529,35530,35533,35535,35537,35539,35541,35543,35545,35547],{"class":3418,"line":3590},[3416,35531,35532],{"class":6387},"                        ExpressionAttributeValues",[3416,35534,6391],{"class":3795},[3416,35536,6394],{"class":4368},[3416,35538,6456],{"class":6397},[3416,35540,5861],{"class":3795},[3416,35542,6461],{"class":4368},[3416,35544,4384],{"class":3795},[3416,35546,6466],{"class":6397},[3416,35548,6469],{"class":3795},[3416,35550,35551],{"class":3418,"line":3596},[3416,35552,9262],{"class":3795},[3416,35554,35555,35557,35559,35561,35563,35565,35567,35569,35571,35574,35576,35578],{"class":3418,"line":3602},[3416,35556,9267],{"class":3795},[3416,35558,26128],{"class":3808},[3416,35560,4384],{"class":3795},[3416,35562,6394],{"class":4368},[3416,35564,6489],{"class":6397},[3416,35566,6492],{"class":3795},[3416,35568,10168],{"class":6387},[3416,35570,6391],{"class":3795},[3416,35572,35573],{"class":6387},"qty",[3416,35575,4043],{"class":3795},[3416,35577,28214],{"class":6330},[3416,35579,28428],{"class":3795},[3416,35581,35582],{"class":3418,"line":3608},[3416,35583,9335],{"class":3795},[3416,35585,35586],{"class":3418,"line":3614},[3416,35587,8805],{"class":3795},[3416,35589,35590],{"class":3418,"line":3620},[3416,35591,9344],{"class":3795},[3416,35593,35594],{"class":3418,"line":3626},[3416,35595,35596],{"class":3789},"                \u002F\u002F 2. Створення нового запису замовлення (Умова: таке замовлення ще не існує)\n",[3416,35598,35599,35601],{"class":3418,"line":3631},[3416,35600,9213],{"class":4368},[3416,35602,17625],{"class":3795},[3416,35604,35605],{"class":3418,"line":3636},[3416,35606,8661],{"class":3795},[3416,35608,35609,35612,35614,35616],{"class":3418,"line":3641},[3416,35610,35611],{"class":6387},"                    Put",[3416,35613,6391],{"class":3795},[3416,35615,6394],{"class":4368},[3416,35617,9905],{"class":6397},[3416,35619,35620],{"class":3418,"line":3647},[3416,35621,8683],{"class":3795},[3416,35623,35624,35626,35628,35630],{"class":3418,"line":3653},[3416,35625,35441],{"class":6387},[3416,35627,6391],{"class":3795},[3416,35629,19785],{"class":3808},[3416,35631,3812],{"class":3795},[3416,35633,35634,35636,35638,35641],{"class":3418,"line":3659},[3416,35635,35517],{"class":6387},[3416,35637,6391],{"class":3795},[3416,35639,35640],{"class":3808},"\"attribute_not_exists(OrderId)\"",[3416,35642,3812],{"class":3795},[3416,35644,35645,35647,35649,35651,35653,35655,35657,35659,35661],{"class":3418,"line":3665},[3416,35646,9241],{"class":6387},[3416,35648,6391],{"class":3795},[3416,35650,6394],{"class":4368},[3416,35652,6456],{"class":6397},[3416,35654,5861],{"class":3795},[3416,35656,6461],{"class":4368},[3416,35658,4384],{"class":3795},[3416,35660,6466],{"class":6397},[3416,35662,6469],{"class":3795},[3416,35664,35665],{"class":3418,"line":3671},[3416,35666,9262],{"class":3795},[3416,35668,35669,35671,35673,35675,35677,35679,35681,35683,35685,35688],{"class":3418,"line":3677},[3416,35670,9267],{"class":3795},[3416,35672,19820],{"class":3808},[3416,35674,4384],{"class":3795},[3416,35676,6394],{"class":4368},[3416,35678,6489],{"class":6397},[3416,35680,6492],{"class":3795},[3416,35682,6495],{"class":6387},[3416,35684,6391],{"class":3795},[3416,35686,35687],{"class":6387},"customerId",[3416,35689,6503],{"class":3795},[3416,35691,35692,35694,35696,35698,35700,35702,35704,35706,35708,35711],{"class":3418,"line":3683},[3416,35693,9267],{"class":3795},[3416,35695,20498],{"class":3808},[3416,35697,4384],{"class":3795},[3416,35699,6394],{"class":4368},[3416,35701,6489],{"class":6397},[3416,35703,6492],{"class":3795},[3416,35705,6495],{"class":6387},[3416,35707,6391],{"class":3795},[3416,35709,35710],{"class":6387},"orderId",[3416,35712,6503],{"class":3795},[3416,35714,35715,35717,35719,35721,35723,35725,35727,35729,35731,35733,35735,35737],{"class":3418,"line":3688},[3416,35716,9267],{"class":3795},[3416,35718,26414],{"class":3808},[3416,35720,4384],{"class":3795},[3416,35722,6394],{"class":4368},[3416,35724,6489],{"class":6397},[3416,35726,6492],{"class":3795},[3416,35728,10168],{"class":6387},[3416,35730,6391],{"class":3795},[3416,35732,35573],{"class":6387},[3416,35734,4043],{"class":3795},[3416,35736,28214],{"class":6330},[3416,35738,28217],{"class":3795},[3416,35740,35741,35743,35745,35747,35749,35751,35753,35755,35758,35760,35763,35765,35767,35769,35771,35773],{"class":3418,"line":3693},[3416,35742,9267],{"class":3795},[3416,35744,20165],{"class":3808},[3416,35746,4384],{"class":3795},[3416,35748,6394],{"class":4368},[3416,35750,6489],{"class":6397},[3416,35752,6492],{"class":3795},[3416,35754,10168],{"class":6387},[3416,35756,35757],{"class":3795}," = (",[3416,35759,35573],{"class":6387},[3416,35761,35762],{"class":3795}," * ",[3416,35764,31460],{"class":6387},[3416,35766,13590],{"class":3795},[3416,35768,28214],{"class":6330},[3416,35770,6423],{"class":3795},[3416,35772,31469],{"class":3808},[3416,35774,31472],{"class":3795},[3416,35776,35777,35779,35781,35783,35785,35787,35789,35791,35793,35795],{"class":3418,"line":3698},[3416,35778,9267],{"class":3795},[3416,35780,11860],{"class":3808},[3416,35782,4384],{"class":3795},[3416,35784,6394],{"class":4368},[3416,35786,6489],{"class":6397},[3416,35788,6492],{"class":3795},[3416,35790,6495],{"class":6387},[3416,35792,6391],{"class":3795},[3416,35794,20820],{"class":3808},[3416,35796,6528],{"class":3795},[3416,35798,35799],{"class":3418,"line":3704},[3416,35800,9335],{"class":3795},[3416,35802,35803],{"class":3418,"line":3710},[3416,35804,8805],{"class":3795},[3416,35806,35807],{"class":3418,"line":3715},[3416,35808,8810],{"class":3795},[3416,35810,35811],{"class":3418,"line":12799},[3416,35812,8815],{"class":3795},[3416,35814,35815],{"class":3418,"line":12822},[3416,35816,30897],{"class":3795},[3416,35818,35819],{"class":3418,"line":12827},[3416,35820,3441],{"emptyLinePlaceholder":3440},[3416,35822,35823],{"class":3418,"line":12832},[3416,35824,34671],{"class":11427},[3416,35826,35827],{"class":3418,"line":12837},[3416,35828,8611],{"class":3795},[3416,35830,35831,35833,35835,35837,35839,35841,35843],{"class":3418,"line":12843},[3416,35832,34680],{"class":4368},[3416,35834,31204],{"class":6387},[3416,35836,4043],{"class":3795},[3416,35838,9848],{"class":6330},[3416,35840,6423],{"class":3795},[3416,35842,31523],{"class":6387},[3416,35844,11465],{"class":3795},[3416,35846,35847],{"class":3418,"line":12860},[3416,35848,8533],{"class":3795},[3416,35850,35851,35853,35855,35858,35860],{"class":3418,"line":12865},[3416,35852,34702],{"class":11427},[3416,35854,11431],{"class":3795},[3416,35856,35857],{"class":6397},"TransactionCanceledException",[3416,35859,34710],{"class":6387},[3416,35861,9656],{"class":3795},[3416,35863,35864],{"class":3418,"line":12876},[3416,35865,8611],{"class":3795},[3416,35867,35868],{"class":3418,"line":12897},[3416,35869,35870],{"class":3789},"            \u002F\u002F Обробка причин скасування транзакції\n",[3416,35872,35873,35876,35879,35881,35883,35885],{"class":3418,"line":12902},[3416,35874,35875],{"class":4368},"            var",[3416,35877,35878],{"class":6387}," reasons",[3416,35880,6391],{"class":3795},[3416,35882,34721],{"class":6387},[3416,35884,4043],{"class":3795},[3416,35886,35887],{"class":6387},"CancellationReasons\n",[3416,35889,35890,35893,35896,35899,35902,35904,35907,35909,35912,35914,35916,35918,35920,35922,35924,35926,35929,35931,35934,35936,35938,35940,35943,35945,35948],{"class":3418,"line":12925},[3416,35891,35892],{"class":3795},"                .",[3416,35894,35895],{"class":6330},"Select",[3416,35897,35898],{"class":3795},"((",[3416,35900,35901],{"class":6387},"r",[3416,35903,4384],{"class":3795},[3416,35905,35906],{"class":6387},"idx",[3416,35908,31247],{"class":3795},[3416,35910,35911],{"class":3808},"$\"Елемент ",[3416,35913,11177],{"class":11533},[3416,35915,35906],{"class":6387},[3416,35917,11302],{"class":11533},[3416,35919,3805],{"class":3808},[3416,35921,11177],{"class":11533},[3416,35923,35901],{"class":6387},[3416,35925,4043],{"class":11533},[3416,35927,35928],{"class":6387},"Code",[3416,35930,11302],{"class":11533},[3416,35932,35933],{"class":3808}," (Опис: ",[3416,35935,11177],{"class":11533},[3416,35937,35901],{"class":6387},[3416,35939,4043],{"class":11533},[3416,35941,35942],{"class":6387},"Message",[3416,35944,11302],{"class":11533},[3416,35946,35947],{"class":3808},")\"",[3416,35949,11465],{"class":3795},[3416,35951,35952],{"class":3418,"line":12948},[3416,35953,35954],{"class":3795},"            \n",[3416,35956,35957,35959,35961,35963,35965,35968,35971,35974,35976,35978,35980,35983,35985,35987,35989,35992,35994,35997,36000,36002,36004,36006],{"class":3418,"line":12953},[3416,35958,34742],{"class":11427},[3416,35960,30905],{"class":4368},[3416,35962,34747],{"class":6397},[3416,35964,6423],{"class":3795},[3416,35966,35967],{"class":3808},"$\"Транзакцію скасовано. Причини:",[3416,35969,35970],{"class":6340},"\\\\",[3416,35972,35973],{"class":3808},"n",[3416,35975,11177],{"class":11533},[3416,35977,6461],{"class":4368},[3416,35979,4043],{"class":11533},[3416,35981,35982],{"class":6330},"Join",[3416,35984,6423],{"class":11533},[3416,35986,24569],{"class":3808},[3416,35988,35970],{"class":6340},[3416,35990,35991],{"class":3808},"n\"",[3416,35993,4384],{"class":11533},[3416,35995,35996],{"class":6387},"reasons",[3416,35998,35999],{"class":11533},")}",[3416,36001,24569],{"class":3808},[3416,36003,4384],{"class":3795},[3416,36005,34721],{"class":6387},[3416,36007,11465],{"class":3795},[3416,36009,36010],{"class":3418,"line":20609},[3416,36011,8533],{"class":3795},[3416,36013,36014],{"class":3418,"line":20614},[3416,36015,4167],{"class":3795},[3416,36017,36018],{"class":3418,"line":20619},[3416,36019,3507],{"class":3795},[3720,36021],{},[3727,36023,36025],{"id":36024},"_7-обробка-подій-dynamodb-streams-у-net-lambda","7. Обробка подій DynamoDB Streams у .NET Lambda",[3353,36027,36028,36029,36031],{},"При активації ",[3363,36030,24041],{}," будь-яка зміна в таблиці записується у потік подій, який може викликати безсерверні функції AWS Lambda для побудови Event-Driven архітектури.",[4584,36033,36035],{"id":36034},"nuget-пакети-для-lambda-інтеграції","NuGet-пакети для Lambda-інтеграції",[3353,36037,36038],{},"У проекті AWS Lambda серіалізація та обробка здійснюється за допомогою пакетів:",[3406,36040,36042],{"className":6316,"code":36041,"language":6318,"meta":30432,"style":3411},"dotnet add package Amazon.Lambda.Core\ndotnet add package Amazon.Lambda.Serialization.SystemTextJson\ndotnet add package Amazon.Lambda.DynamoDBEvents\n",[3413,36043,36044,36055,36066],{"__ignoreMap":3411},[3416,36045,36046,36048,36050,36052],{"class":3418,"line":3419},[3416,36047,30444],{"class":6330},[3416,36049,30447],{"class":3808},[3416,36051,30450],{"class":3808},[3416,36053,36054],{"class":3808}," Amazon.Lambda.Core\n",[3416,36056,36057,36059,36061,36063],{"class":3418,"line":3425},[3416,36058,30444],{"class":6330},[3416,36060,30447],{"class":3808},[3416,36062,30450],{"class":3808},[3416,36064,36065],{"class":3808}," Amazon.Lambda.Serialization.SystemTextJson\n",[3416,36067,36068,36070,36072,36074],{"class":3418,"line":3431},[3416,36069,30444],{"class":6330},[3416,36071,30447],{"class":3808},[3416,36073,30450],{"class":3808},[3416,36075,36076],{"class":3808}," Amazon.Lambda.DynamoDBEvents\n",[4584,36078,36080],{"id":36079},"приклад-реалізації-lambda-обробника-functioncs","Приклад реалізації Lambda-обробника (Function.cs)",[3406,36082,36084],{"className":6375,"code":36083,"language":6377,"meta":30432,"style":3411},"using Amazon.Lambda.Core;\nusing Amazon.Lambda.DynamoDBEvents;\nusing System.Text.Json;\n\n\u002F\u002F Налаштування глобального серіалізатора Lambda\n[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]\n\nnamespace LambdaHandler;\n\npublic class OrderStreamProcessor\n{\n    public async Task FunctionHandlerAsync(DynamoDBEvent dynamoEvent, ILambdaContext context)\n    {\n        context.Logger.LogInformation($\"Отримано пакет подій. Кількість записів: {dynamoEvent.Records.Count}\");\n\n        foreach (var record in dynamoEvent.Records)\n        {\n            context.Logger.LogInformation($\"EventID: {record.EventID} | Назва події: {record.EventName}\");\n\n            switch (record.EventName)\n            {\n                case \"INSERT\":\n                    \u002F\u002F Зчитування нових даних\n                    var newItemMap = record.Dynamodb.NewImage;\n                    string customerId = newItemMap[\"CustomerId\"].S;\n                    string orderId = newItemMap[\"OrderId\"].S;\n                    context.Logger.LogInformation($\"[Створення] Замовлення {orderId} додано для клієнта {customerId}\");\n                    break;\n\n                case \"MODIFY\":\n                    \u002F\u002F Порівняння змін (Old Image проти New Image)\n                    var oldImage = record.Dynamodb.OldImage;\n                    var newImage = record.Dynamodb.NewImage;\n                    \n                    if (oldImage.TryGetValue(\"Status\", out var oldStatus) && \n                        newImage.TryGetValue(\"Status\", out var newStatus))\n                    {\n                        context.Logger.LogInformation($\"[Оновлення] Статус замовлення змінено: {oldStatus.S} -> {newStatus.S}\");\n                    }\n                    break;\n\n                case \"REMOVE\":\n                    \u002F\u002F Перевірка джерела видалення (Користувач чи TTL-сервіс)\n                    bool isTtlDeletion = record.UserIdentity?.Type == \"Service\" && \n                                         record.UserIdentity?.PrincipalId == \"dynamodb.amazonaws.com\";\n\n                    if (isTtlDeletion)\n                    {\n                        context.Logger.LogInformation($\"[TTL] Запис автоматично видалено сервісом TTL: {record.Dynamodb.OldImage[\"OrderId\"].S}\");\n                    }\n                    else\n                    {\n                        context.Logger.LogInformation($\"[Видалення] Користувач видалив запис: {record.Dynamodb.OldImage[\"OrderId\"].S}\");\n                    }\n                    break;\n            }\n        }\n\n        await Task.CompletedTask;\n    }\n}\n",[3413,36085,36086,36103,36120,36136,36140,36145,36186,36190,36200,36204,36213,36217,36245,36249,36290,36294,36316,36320,36368,36372,36387,36391,36402,36407,36430,36452,36472,36509,36516,36520,36529,36534,36556,36577,36582,36615,36640,36644,36691,36695,36701,36705,36714,36719,36750,36771,36775,36786,36790,36833,36837,36842,36846,36889,36893,36899,36903,36907,36911,36924,36928],{"__ignoreMap":3411},[3416,36087,36088,36090,36092,36094,36096,36098,36101],{"class":3418,"line":3419},[3416,36089,17433],{"class":11427},[3416,36091,17436],{"class":6397},[3416,36093,4043],{"class":3795},[3416,36095,24670],{"class":6397},[3416,36097,4043],{"class":3795},[3416,36099,36100],{"class":6397},"Core",[3416,36102,11594],{"class":3795},[3416,36104,36105,36107,36109,36111,36113,36115,36118],{"class":3418,"line":3425},[3416,36106,17433],{"class":11427},[3416,36108,17436],{"class":6397},[3416,36110,4043],{"class":3795},[3416,36112,24670],{"class":6397},[3416,36114,4043],{"class":3795},[3416,36116,36117],{"class":6397},"DynamoDBEvents",[3416,36119,11594],{"class":3795},[3416,36121,36122,36124,36126,36128,36130,36132,36134],{"class":3418,"line":3431},[3416,36123,17433],{"class":11427},[3416,36125,34109],{"class":6397},[3416,36127,4043],{"class":3795},[3416,36129,34114],{"class":6397},[3416,36131,4043],{"class":3795},[3416,36133,34119],{"class":6397},[3416,36135,11594],{"class":3795},[3416,36137,36138],{"class":3418,"line":3437},[3416,36139,3441],{"emptyLinePlaceholder":3440},[3416,36141,36142],{"class":3418,"line":3444},[3416,36143,36144],{"class":3789},"\u002F\u002F Налаштування глобального серіалізатора Lambda\n",[3416,36146,36147,36149,36152,36154,36157,36159,36161,36163,36165,36167,36169,36171,36174,36176,36179,36181,36184],{"class":3418,"line":3450},[3416,36148,11789],{"class":3795},[3416,36150,36151],{"class":4368},"assembly",[3416,36153,3805],{"class":3795},[3416,36155,36156],{"class":6397},"LambdaSerializer",[3416,36158,6423],{"class":3795},[3416,36160,33936],{"class":4368},[3416,36162,6423],{"class":3795},[3416,36164,22807],{"class":6397},[3416,36166,4043],{"class":3795},[3416,36168,24670],{"class":6397},[3416,36170,4043],{"class":3795},[3416,36172,36173],{"class":6397},"Serialization",[3416,36175,4043],{"class":3795},[3416,36177,36178],{"class":6397},"SystemTextJson",[3416,36180,4043],{"class":3795},[3416,36182,36183],{"class":6397},"DefaultLambdaJsonSerializer",[3416,36185,33944],{"class":3795},[3416,36187,36188],{"class":3418,"line":3456},[3416,36189,3441],{"emptyLinePlaceholder":3440},[3416,36191,36192,36195,36198],{"class":3418,"line":3462},[3416,36193,36194],{"class":4368},"namespace",[3416,36196,36197],{"class":6397}," LambdaHandler",[3416,36199,11594],{"class":3795},[3416,36201,36202],{"class":3418,"line":3468},[3416,36203,3441],{"emptyLinePlaceholder":3440},[3416,36205,36206,36208,36210],{"class":3418,"line":3474},[3416,36207,31180],{"class":4368},[3416,36209,31183],{"class":4368},[3416,36211,36212],{"class":6397}," OrderStreamProcessor\n",[3416,36214,36215],{"class":3418,"line":3480},[3416,36216,3796],{"class":3795},[3416,36218,36219,36221,36223,36225,36228,36230,36233,36236,36238,36241,36243],{"class":3418,"line":3486},[3416,36220,31235],{"class":4368},[3416,36222,31273],{"class":4368},[3416,36224,11606],{"class":6397},[3416,36226,36227],{"class":6330}," FunctionHandlerAsync",[3416,36229,6423],{"class":3795},[3416,36231,36232],{"class":6397},"DynamoDBEvent",[3416,36234,36235],{"class":6387}," dynamoEvent",[3416,36237,4384],{"class":3795},[3416,36239,36240],{"class":6397},"ILambdaContext",[3416,36242,34530],{"class":6387},[3416,36244,9656],{"class":3795},[3416,36246,36247],{"class":3418,"line":3492},[3416,36248,6474],{"class":3795},[3416,36250,36251,36254,36256,36259,36261,36264,36266,36269,36271,36274,36276,36279,36281,36284,36286,36288],{"class":3418,"line":3498},[3416,36252,36253],{"class":6387},"        context",[3416,36255,4043],{"class":3795},[3416,36257,36258],{"class":6387},"Logger",[3416,36260,4043],{"class":3795},[3416,36262,36263],{"class":6330},"LogInformation",[3416,36265,6423],{"class":3795},[3416,36267,36268],{"class":3808},"$\"Отримано пакет подій. Кількість записів: ",[3416,36270,11177],{"class":11533},[3416,36272,36273],{"class":6387},"dynamoEvent",[3416,36275,4043],{"class":11533},[3416,36277,36278],{"class":6387},"Records",[3416,36280,4043],{"class":11533},[3416,36282,36283],{"class":6387},"Count",[3416,36285,11302],{"class":11533},[3416,36287,24569],{"class":3808},[3416,36289,11465],{"class":3795},[3416,36291,36292],{"class":3418,"line":3504},[3416,36293,3441],{"emptyLinePlaceholder":3440},[3416,36295,36296,36299,36301,36303,36306,36308,36310,36312,36314],{"class":3418,"line":3510},[3416,36297,36298],{"class":11427},"        foreach",[3416,36300,11431],{"class":3795},[3416,36302,6384],{"class":4368},[3416,36304,36305],{"class":6387}," record",[3416,36307,33304],{"class":11427},[3416,36309,36235],{"class":6387},[3416,36311,4043],{"class":3795},[3416,36313,36278],{"class":6387},[3416,36315,9656],{"class":3795},[3416,36317,36318],{"class":3418,"line":3515},[3416,36319,8611],{"class":3795},[3416,36321,36322,36325,36327,36329,36331,36333,36335,36338,36340,36343,36345,36348,36350,36353,36355,36357,36359,36362,36364,36366],{"class":3418,"line":3521},[3416,36323,36324],{"class":6387},"            context",[3416,36326,4043],{"class":3795},[3416,36328,36258],{"class":6387},[3416,36330,4043],{"class":3795},[3416,36332,36263],{"class":6330},[3416,36334,6423],{"class":3795},[3416,36336,36337],{"class":3808},"$\"EventID: ",[3416,36339,11177],{"class":11533},[3416,36341,36342],{"class":6387},"record",[3416,36344,4043],{"class":11533},[3416,36346,36347],{"class":6387},"EventID",[3416,36349,11302],{"class":11533},[3416,36351,36352],{"class":3808}," | Назва події: ",[3416,36354,11177],{"class":11533},[3416,36356,36342],{"class":6387},[3416,36358,4043],{"class":11533},[3416,36360,36361],{"class":6387},"EventName",[3416,36363,11302],{"class":11533},[3416,36365,24569],{"class":3808},[3416,36367,11465],{"class":3795},[3416,36369,36370],{"class":3418,"line":3527},[3416,36371,3441],{"emptyLinePlaceholder":3440},[3416,36373,36374,36377,36379,36381,36383,36385],{"class":3418,"line":3533},[3416,36375,36376],{"class":11427},"            switch",[3416,36378,11431],{"class":3795},[3416,36380,36342],{"class":6387},[3416,36382,4043],{"class":3795},[3416,36384,36361],{"class":6387},[3416,36386,9656],{"class":3795},[3416,36388,36389],{"class":3418,"line":3539},[3416,36390,8628],{"class":3795},[3416,36392,36393,36396,36399],{"class":3418,"line":3545},[3416,36394,36395],{"class":11427},"                case",[3416,36397,36398],{"class":3808}," \"INSERT\"",[3416,36400,36401],{"class":3795},":\n",[3416,36403,36404],{"class":3418,"line":3551},[3416,36405,36406],{"class":3789},"                    \u002F\u002F Зчитування нових даних\n",[3416,36408,36409,36412,36415,36417,36419,36421,36423,36425,36428],{"class":3418,"line":3557},[3416,36410,36411],{"class":4368},"                    var",[3416,36413,36414],{"class":6387}," newItemMap",[3416,36416,6391],{"class":3795},[3416,36418,36342],{"class":6387},[3416,36420,4043],{"class":3795},[3416,36422,23198],{"class":6387},[3416,36424,4043],{"class":3795},[3416,36426,36427],{"class":6387},"NewImage",[3416,36429,11594],{"class":3795},[3416,36431,36432,36435,36437,36439,36442,36444,36446,36448,36450],{"class":3418,"line":3563},[3416,36433,36434],{"class":4368},"                    string",[3416,36436,35304],{"class":6387},[3416,36438,6391],{"class":3795},[3416,36440,36441],{"class":6387},"newItemMap",[3416,36443,11789],{"class":3795},[3416,36445,19820],{"class":3808},[3416,36447,33352],{"class":3795},[3416,36449,6495],{"class":6387},[3416,36451,11594],{"class":3795},[3416,36453,36454,36456,36458,36460,36462,36464,36466,36468,36470],{"class":3418,"line":3569},[3416,36455,36434],{"class":4368},[3416,36457,35337],{"class":6387},[3416,36459,6391],{"class":3795},[3416,36461,36441],{"class":6387},[3416,36463,11789],{"class":3795},[3416,36465,20498],{"class":3808},[3416,36467,33352],{"class":3795},[3416,36469,6495],{"class":6387},[3416,36471,11594],{"class":3795},[3416,36473,36474,36477,36479,36481,36483,36485,36487,36490,36492,36494,36496,36499,36501,36503,36505,36507],{"class":3418,"line":3574},[3416,36475,36476],{"class":6387},"                    context",[3416,36478,4043],{"class":3795},[3416,36480,36258],{"class":6387},[3416,36482,4043],{"class":3795},[3416,36484,36263],{"class":6330},[3416,36486,6423],{"class":3795},[3416,36488,36489],{"class":3808},"$\"[Створення] Замовлення ",[3416,36491,11177],{"class":11533},[3416,36493,35710],{"class":6387},[3416,36495,11302],{"class":11533},[3416,36497,36498],{"class":3808}," додано для клієнта ",[3416,36500,11177],{"class":11533},[3416,36502,35687],{"class":6387},[3416,36504,11302],{"class":11533},[3416,36506,24569],{"class":3808},[3416,36508,11465],{"class":3795},[3416,36510,36511,36514],{"class":3418,"line":3579},[3416,36512,36513],{"class":11427},"                    break",[3416,36515,11594],{"class":3795},[3416,36517,36518],{"class":3418,"line":3584},[3416,36519,3441],{"emptyLinePlaceholder":3440},[3416,36521,36522,36524,36527],{"class":3418,"line":3590},[3416,36523,36395],{"class":11427},[3416,36525,36526],{"class":3808}," \"MODIFY\"",[3416,36528,36401],{"class":3795},[3416,36530,36531],{"class":3418,"line":3596},[3416,36532,36533],{"class":3789},"                    \u002F\u002F Порівняння змін (Old Image проти New Image)\n",[3416,36535,36536,36538,36541,36543,36545,36547,36549,36551,36554],{"class":3418,"line":3602},[3416,36537,36411],{"class":4368},[3416,36539,36540],{"class":6387}," oldImage",[3416,36542,6391],{"class":3795},[3416,36544,36342],{"class":6387},[3416,36546,4043],{"class":3795},[3416,36548,23198],{"class":6387},[3416,36550,4043],{"class":3795},[3416,36552,36553],{"class":6387},"OldImage",[3416,36555,11594],{"class":3795},[3416,36557,36558,36560,36563,36565,36567,36569,36571,36573,36575],{"class":3418,"line":3608},[3416,36559,36411],{"class":4368},[3416,36561,36562],{"class":6387}," newImage",[3416,36564,6391],{"class":3795},[3416,36566,36342],{"class":6387},[3416,36568,4043],{"class":3795},[3416,36570,23198],{"class":6387},[3416,36572,4043],{"class":3795},[3416,36574,36427],{"class":6387},[3416,36576,11594],{"class":3795},[3416,36578,36579],{"class":3418,"line":3614},[3416,36580,36581],{"class":3795},"                    \n",[3416,36583,36584,36587,36589,36592,36594,36597,36599,36601,36603,36606,36609,36612],{"class":3418,"line":3620},[3416,36585,36586],{"class":11427},"                    if",[3416,36588,11431],{"class":3795},[3416,36590,36591],{"class":6387},"oldImage",[3416,36593,4043],{"class":3795},[3416,36595,36596],{"class":6330},"TryGetValue",[3416,36598,6423],{"class":3795},[3416,36600,11860],{"class":3808},[3416,36602,4384],{"class":3795},[3416,36604,36605],{"class":4368},"out",[3416,36607,36608],{"class":4368}," var",[3416,36610,36611],{"class":6387}," oldStatus",[3416,36613,36614],{"class":3795},") && \n",[3416,36616,36617,36620,36622,36624,36626,36628,36630,36632,36634,36637],{"class":3418,"line":3626},[3416,36618,36619],{"class":6387},"                        newImage",[3416,36621,4043],{"class":3795},[3416,36623,36596],{"class":6330},[3416,36625,6423],{"class":3795},[3416,36627,11860],{"class":3808},[3416,36629,4384],{"class":3795},[3416,36631,36605],{"class":4368},[3416,36633,36608],{"class":4368},[3416,36635,36636],{"class":6387}," newStatus",[3416,36638,36639],{"class":3795},"))\n",[3416,36641,36642],{"class":3418,"line":3631},[3416,36643,8683],{"class":3795},[3416,36645,36646,36649,36651,36653,36655,36657,36659,36662,36664,36667,36669,36671,36673,36676,36678,36681,36683,36685,36687,36689],{"class":3418,"line":3636},[3416,36647,36648],{"class":6387},"                        context",[3416,36650,4043],{"class":3795},[3416,36652,36258],{"class":6387},[3416,36654,4043],{"class":3795},[3416,36656,36263],{"class":6330},[3416,36658,6423],{"class":3795},[3416,36660,36661],{"class":3808},"$\"[Оновлення] Статус замовлення змінено: ",[3416,36663,11177],{"class":11533},[3416,36665,36666],{"class":6387},"oldStatus",[3416,36668,4043],{"class":11533},[3416,36670,6495],{"class":6387},[3416,36672,11302],{"class":11533},[3416,36674,36675],{"class":3808}," -> ",[3416,36677,11177],{"class":11533},[3416,36679,36680],{"class":6387},"newStatus",[3416,36682,4043],{"class":11533},[3416,36684,6495],{"class":6387},[3416,36686,11302],{"class":11533},[3416,36688,24569],{"class":3808},[3416,36690,11465],{"class":3795},[3416,36692,36693],{"class":3418,"line":3641},[3416,36694,8805],{"class":3795},[3416,36696,36697,36699],{"class":3418,"line":3647},[3416,36698,36513],{"class":11427},[3416,36700,11594],{"class":3795},[3416,36702,36703],{"class":3418,"line":3653},[3416,36704,3441],{"emptyLinePlaceholder":3440},[3416,36706,36707,36709,36712],{"class":3418,"line":3659},[3416,36708,36395],{"class":11427},[3416,36710,36711],{"class":3808}," \"REMOVE\"",[3416,36713,36401],{"class":3795},[3416,36715,36716],{"class":3418,"line":3665},[3416,36717,36718],{"class":3789},"                    \u002F\u002F Перевірка джерела видалення (Користувач чи TTL-сервіс)\n",[3416,36720,36721,36724,36727,36729,36731,36733,36736,36739,36742,36744,36747],{"class":3418,"line":3671},[3416,36722,36723],{"class":4368},"                    bool",[3416,36725,36726],{"class":6387}," isTtlDeletion",[3416,36728,6391],{"class":3795},[3416,36730,36342],{"class":6387},[3416,36732,4043],{"class":3795},[3416,36734,36735],{"class":6387},"UserIdentity",[3416,36737,36738],{"class":3795},"?.",[3416,36740,36741],{"class":6387},"Type",[3416,36743,11488],{"class":3795},[3416,36745,36746],{"class":3808},"\"Service\"",[3416,36748,36749],{"class":3795}," && \n",[3416,36751,36752,36755,36757,36759,36761,36764,36766,36769],{"class":3418,"line":3677},[3416,36753,36754],{"class":6387},"                                         record",[3416,36756,4043],{"class":3795},[3416,36758,36735],{"class":6387},[3416,36760,36738],{"class":3795},[3416,36762,36763],{"class":6387},"PrincipalId",[3416,36765,11488],{"class":3795},[3416,36767,36768],{"class":3808},"\"dynamodb.amazonaws.com\"",[3416,36770,11594],{"class":3795},[3416,36772,36773],{"class":3418,"line":3683},[3416,36774,3441],{"emptyLinePlaceholder":3440},[3416,36776,36777,36779,36781,36784],{"class":3418,"line":3688},[3416,36778,36586],{"class":11427},[3416,36780,11431],{"class":3795},[3416,36782,36783],{"class":6387},"isTtlDeletion",[3416,36785,9656],{"class":3795},[3416,36787,36788],{"class":3418,"line":3693},[3416,36789,8683],{"class":3795},[3416,36791,36792,36794,36796,36798,36800,36802,36804,36807,36809,36811,36813,36815,36817,36819,36821,36823,36825,36827,36829,36831],{"class":3418,"line":3698},[3416,36793,36648],{"class":6387},[3416,36795,4043],{"class":3795},[3416,36797,36258],{"class":6387},[3416,36799,4043],{"class":3795},[3416,36801,36263],{"class":6330},[3416,36803,6423],{"class":3795},[3416,36805,36806],{"class":3808},"$\"[TTL] Запис автоматично видалено сервісом TTL: ",[3416,36808,11177],{"class":11533},[3416,36810,36342],{"class":6387},[3416,36812,4043],{"class":11533},[3416,36814,23198],{"class":6387},[3416,36816,4043],{"class":11533},[3416,36818,36553],{"class":6387},[3416,36820,11789],{"class":11533},[3416,36822,20498],{"class":3808},[3416,36824,33352],{"class":11533},[3416,36826,6495],{"class":6387},[3416,36828,11302],{"class":11533},[3416,36830,24569],{"class":3808},[3416,36832,11465],{"class":3795},[3416,36834,36835],{"class":3418,"line":3704},[3416,36836,8805],{"class":3795},[3416,36838,36839],{"class":3418,"line":3710},[3416,36840,36841],{"class":11427},"                    else\n",[3416,36843,36844],{"class":3418,"line":3715},[3416,36845,8683],{"class":3795},[3416,36847,36848,36850,36852,36854,36856,36858,36860,36863,36865,36867,36869,36871,36873,36875,36877,36879,36881,36883,36885,36887],{"class":3418,"line":12799},[3416,36849,36648],{"class":6387},[3416,36851,4043],{"class":3795},[3416,36853,36258],{"class":6387},[3416,36855,4043],{"class":3795},[3416,36857,36263],{"class":6330},[3416,36859,6423],{"class":3795},[3416,36861,36862],{"class":3808},"$\"[Видалення] Користувач видалив запис: ",[3416,36864,11177],{"class":11533},[3416,36866,36342],{"class":6387},[3416,36868,4043],{"class":11533},[3416,36870,23198],{"class":6387},[3416,36872,4043],{"class":11533},[3416,36874,36553],{"class":6387},[3416,36876,11789],{"class":11533},[3416,36878,20498],{"class":3808},[3416,36880,33352],{"class":11533},[3416,36882,6495],{"class":6387},[3416,36884,11302],{"class":11533},[3416,36886,24569],{"class":3808},[3416,36888,11465],{"class":3795},[3416,36890,36891],{"class":3418,"line":12822},[3416,36892,8805],{"class":3795},[3416,36894,36895,36897],{"class":3418,"line":12827},[3416,36896,36513],{"class":11427},[3416,36898,11594],{"class":3795},[3416,36900,36901],{"class":3418,"line":12832},[3416,36902,8815],{"class":3795},[3416,36904,36905],{"class":3418,"line":12837},[3416,36906,8533],{"class":3795},[3416,36908,36909],{"class":3418,"line":12843},[3416,36910,3441],{"emptyLinePlaceholder":3440},[3416,36912,36913,36915,36917,36919,36922],{"class":3418,"line":12860},[3416,36914,31512],{"class":4368},[3416,36916,11606],{"class":6387},[3416,36918,4043],{"class":3795},[3416,36920,36921],{"class":6387},"CompletedTask",[3416,36923,11594],{"class":3795},[3416,36925,36926],{"class":3418,"line":12865},[3416,36927,4167],{"class":3795},[3416,36929,36930],{"class":3418,"line":12876},[3416,36931,3507],{"class":3795},[22319,36933,36934],{},[3353,36935,36936,36938,36939,36941,36942,36945,36946,36949,36950,36953,36954,4384,36956,4384,36958,36960],{},[3416,36937,27452],{},"\nКлас ",[3413,36940,6466],{}," у бібліотеці ",[3413,36943,36944],{},"Amazon.Lambda.DynamoDBEvents"," — це ",[3363,36947,36948],{},"інший тип"," порівняно з ",[3413,36951,36952],{},"Amazon.DynamoDBv2.Model.AttributeValue"," у AWS SDK. Вони мають ідентичні за назвою властивості (",[3413,36955,6495],{},[3413,36957,10168],{},[3413,36959,6850],{},"), але розташовані в різних збірках. Якщо вам потрібно перетворити карту атрибутів Lambda-події в об'єкти домену, скористайтеся JSON-трансляцією або ручним перемальовуванням полів.",[3720,36962],{},[3727,36964,36966],{"id":36965},"_8-практичні-best-practices-для-розробників-net","8. Практичні Best Practices для розробників .NET",[3353,36968,36969],{},"Для забезпечення стабільної роботи .NET додатків під високим навантаженням дотримуйтеся наступних правил конфігурації клієнта:",[3374,36971,36972,37028,37074],{},[3377,36973,36974,36977,36978,36980,36981,36983,36984,36986,36987,36401,36989],{},[3363,36975,36976],{},"Керування TCP-підключеннями (Connection pooling):","\nРеєструйте ",[3413,36979,30705],{}," виключно як ",[3363,36982,30762],{},". Під капотом SDK використовує ",[3413,36985,30758],{},", який автоматично утилізує з'єднання. Налаштувати ліміти з'єднань можна через ",[3413,36988,30933],{},[3406,36990,36992],{"className":6375,"code":36991,"language":6377,"meta":30432,"style":3411},"var config = new AmazonDynamoDBConfig\n{\n    \u002F\u002F Збільшуємо ліміт підключень (за замовчуванням 50) для систем із великим паралелізмом\n    ConnectionLimit = 500\n};\n",[3413,36993,36994,37006,37010,37015,37024],{"__ignoreMap":3411},[3416,36995,36996,36998,37000,37002,37004],{"class":3418,"line":3419},[3416,36997,6384],{"class":4368},[3416,36999,30856],{"class":6387},[3416,37001,6391],{"class":3795},[3416,37003,6394],{"class":4368},[3416,37005,30863],{"class":6397},[3416,37007,37008],{"class":3418,"line":3425},[3416,37009,3796],{"class":3795},[3416,37011,37012],{"class":3418,"line":3431},[3416,37013,37014],{"class":3789},"    \u002F\u002F Збільшуємо ліміт підключень (за замовчуванням 50) для систем із великим паралелізмом\n",[3416,37016,37017,37020,37022],{"class":3418,"line":3437},[3416,37018,37019],{"class":6387},"    ConnectionLimit",[3416,37021,6391],{"class":3795},[3416,37023,23250],{"class":3870},[3416,37025,37026],{"class":3418,"line":3444},[3416,37027,18505],{"class":3795},[3377,37029,37030,37033,37034,37036,37037],{},[3363,37031,37032],{},"Обробка таймаутів та мережевих помилок:","\nSDK за замовчуванням робить повторні спроби (Exponential Backoff) для помилок типу ",[3413,37035,16738],{}," або тимчасових втрат з'єднання. Налаштувати кількість ретриїв можна вручну:\n",[3406,37038,37040],{"className":6375,"code":37039,"language":6377,"meta":30432,"style":3411},"var config = new AmazonDynamoDBConfig\n{\n    MaxErrorRetry = 5 \u002F\u002F Кількість автоматичних повторних спроб\n};\n",[3413,37041,37042,37054,37058,37070],{"__ignoreMap":3411},[3416,37043,37044,37046,37048,37050,37052],{"class":3418,"line":3419},[3416,37045,6384],{"class":4368},[3416,37047,30856],{"class":6387},[3416,37049,6391],{"class":3795},[3416,37051,6394],{"class":4368},[3416,37053,30863],{"class":6397},[3416,37055,37056],{"class":3418,"line":3425},[3416,37057,3796],{"class":3795},[3416,37059,37060,37063,37065,37067],{"class":3418,"line":3431},[3416,37061,37062],{"class":6387},"    MaxErrorRetry",[3416,37064,6391],{"class":3795},[3416,37066,11650],{"class":3870},[3416,37068,37069],{"class":3789}," \u002F\u002F Кількість автоматичних повторних спроб\n",[3416,37071,37072],{"class":3418,"line":3437},[3416,37073,18505],{"class":3795},[3377,37075,37076,37079,37080,37083,37084,37087,37088,37090,37091,37094,37095,37097],{},[3363,37077,37078],{},"Локалізація та парсинг чисел (CultureInfo):","\nПри ручному формуванні ",[3413,37081,37082],{},"AttributeValue.N"," завжди передавайте числа через інваріантну культуру ",[3413,37085,37086],{},"price.ToString(CultureInfo.InvariantCulture)"," or ",[3413,37089,31469],{},", щоб запобігти генерації коми замість крапки (",[3413,37092,37093],{},"89,99"," замість ",[3413,37096,5278],{},"), що призведе до помилки десеріалізації з боку AWS API.",[3720,37099],{},[3348,37101,37103],{"id":37102},"практичний-приклад-інтерактивна-робота-з-dynamodb-через-aws-cli","Практичний приклад: Інтерактивна робота з DynamoDB через AWS CLI",[3353,37105,37106,37107,37110,37111,37114,37115,4384,37117,4384,37119,37121],{},"Перш ніж переходити до розробки коду на C#, важливо зрозуміти низькорівневу механіку DynamoDB «на дотик». Найкращий спосіб зробити це — скористатися утилітою командного рядка ",[3363,37108,37109],{},"AWS CLI"," для взаємодії з вашим ",[3363,37112,37113],{},"хмарним акаунтом AWS",". Це дозволить наочно побачити структуру JSON-документів з явним зазначенням типів даних (",[3413,37116,6495],{},[3413,37118,10168],{},[3413,37120,6850],{},"), які надсилаються в HTTP-запитах до DynamoDB API.",[3727,37123,37125],{"id":37124},"налаштування-середовища-та-автентифікації","Налаштування середовища та автентифікації",[3353,37127,37128,37129,37131,37132,32096],{},"Для виконання запитів до хмари AWS переконайтеся, що на вашій машині встановлено ",[3363,37130,37109],{}," та налаштовано профіль автентифікації за замовчуванням (Default Profile) або інший профіль з відповідними правами доступу до DynamoDB (наприклад, політика ",[3413,37133,37134],{},"AmazonDynamoDBFullAccess",[3406,37136,37138],{"className":6316,"code":37137,"language":6318,"meta":3411,"style":3411},"# Конфігурація доступу до реального акаунту AWS\naws configure\n",[3413,37139,37140,37145],{"__ignoreMap":3411},[3416,37141,37142],{"class":3418,"line":3419},[3416,37143,37144],{"class":3789},"# Конфігурація доступу до реального акаунту AWS\n",[3416,37146,37147,37149],{"class":3418,"line":3425},[3416,37148,6331],{"class":6330},[3416,37150,37151],{"class":3808}," configure\n",[3353,37153,37154],{},"Утиліта попросить ввести:",[4488,37156,37157,37163,37169,37178],{},[3377,37158,37159,37162],{},[3363,37160,37161],{},"AWS Access Key ID",": ваш ідентифікатор ключа доступу IAM.",[3377,37164,37165,37168],{},[3363,37166,37167],{},"AWS Secret Access Key",": ваш секретний ключ доступу IAM.",[3377,37170,37171,37174,37175,13590],{},[3363,37172,37173],{},"Default region name",": регіон вашої бази (наприклад, ",[3413,37176,37177],{},"eu-central-1",[3377,37179,37180,37183,37184,4043],{},[3363,37181,37182],{},"Default output format",": формат виводу, наприклад ",[3413,37185,3782],{},[3353,37187,37188],{},"Після цього всі команди будуть за замовчуванням виконуватися у вашому хмарному середовищі AWS.",[22319,37190,37191],{},[3353,37192,37193,37196,37199,37200,37203,37204,4043],{},[3416,37194,37195],{},"!TIP",[3363,37197,37198],{},"Альтернатива (Локальний запуск):"," Якщо ви хочете запустити ці ж команди локально на Docker-контейнері DynamoDB Local (з Кроку 1 альтернативного шляху C#-прикладу), додавайте до кожної команди параметр ",[3413,37201,37202],{},"--endpoint-url http:\u002F\u002Flocalhost:8000"," та вказуйте будь-який фейковий профіль за допомогою ",[3413,37205,37206],{},"--profile local",[3720,37208],{},[3727,37210,37212],{"id":37211},"крок-1-створення-таблиці-create-table","Крок 1: Створення таблиці (Create Table)",[3353,37214,37215,37216,37219,37220,37222,37223,37226],{},"Створимо таблицю ",[3413,37217,37218],{},"SandboxTasks"," із композитним ключем (Partition Key ",[3413,37221,4494],{}," типу String та Sort Key ",[3413,37224,37225],{},"TaskId"," типу String), а також додамо локальний вторинний індекс (LSI) для фільтрації за пріоритетом.",[3406,37228,37230],{"className":6316,"code":37229,"language":6318,"meta":3411,"style":3411},"aws dynamodb create-table \\\n    --table-name SandboxTasks \\\n    --attribute-definitions \\\n        AttributeName=UserId,AttributeType=S \\\n        AttributeName=TaskId,AttributeType=S \\\n        AttributeName=Priority,AttributeType=S \\\n    --key-schema \\\n        AttributeName=UserId,KeyType=HASH \\\n        AttributeName=TaskId,KeyType=RANGE \\\n    --local-secondary-indexes \\\n        \"[\n            {\n                \\\"IndexName\\\": \\\"Priority-index\\\",\n                \\\"KeySchema\\\": [\n                    {\\\"AttributeName\\\": \\\"UserId\\\", \\\"KeyType\\\": \\\"HASH\\\"},\n                    {\\\"AttributeName\\\": \\\"Priority\\\", \\\"KeyType\\\": \\\"RANGE\\\"}\n                ],\n                \\\"Projection\\\": {\n                    \\\"ProjectionType\\\": \\\"ALL\\\"\n                }\n            }\n        ]\" \\\n    --billing-mode PAY_PER_REQUEST\n",[3413,37231,37232,37242,37251,37257,37263,37270,37277,37283,37289,37296,37302,37307,37311,37331,37342,37380,37417,37422,37432,37450,37454,37458,37465],{"__ignoreMap":3411},[3416,37233,37234,37236,37238,37240],{"class":3418,"line":3419},[3416,37235,6331],{"class":6330},[3416,37237,6334],{"class":3808},[3416,37239,10696],{"class":3808},[3416,37241,6341],{"class":6340},[3416,37243,37244,37246,37249],{"class":3418,"line":3425},[3416,37245,6346],{"class":4368},[3416,37247,37248],{"class":3808}," SandboxTasks",[3416,37250,6341],{"class":6340},[3416,37252,37253,37255],{"class":3418,"line":3431},[3416,37254,10711],{"class":4368},[3416,37256,6341],{"class":6340},[3416,37258,37259,37261],{"class":3418,"line":3437},[3416,37260,10718],{"class":3808},[3416,37262,6341],{"class":6340},[3416,37264,37265,37268],{"class":3418,"line":3444},[3416,37266,37267],{"class":3808},"        AttributeName=TaskId,AttributeType=S",[3416,37269,6341],{"class":6340},[3416,37271,37272,37275],{"class":3418,"line":3450},[3416,37273,37274],{"class":3808},"        AttributeName=Priority,AttributeType=S",[3416,37276,6341],{"class":6340},[3416,37278,37279,37281],{"class":3418,"line":3456},[3416,37280,10732],{"class":4368},[3416,37282,6341],{"class":6340},[3416,37284,37285,37287],{"class":3418,"line":3462},[3416,37286,10739],{"class":3808},[3416,37288,6341],{"class":6340},[3416,37290,37291,37294],{"class":3418,"line":3468},[3416,37292,37293],{"class":3808},"        AttributeName=TaskId,KeyType=RANGE",[3416,37295,6341],{"class":6340},[3416,37297,37298,37300],{"class":3418,"line":3474},[3416,37299,15326],{"class":4368},[3416,37301,6341],{"class":6340},[3416,37303,37304],{"class":3418,"line":3480},[3416,37305,37306],{"class":3808},"        \"[\n",[3416,37308,37309],{"class":3418,"line":3486},[3416,37310,8628],{"class":3808},[3416,37312,37313,37316,37318,37320,37322,37324,37327,37329],{"class":3418,"line":3492},[3416,37314,37315],{"class":6340},"                \\\"",[3416,37317,33480],{"class":3808},[3416,37319,25075],{"class":6340},[3416,37321,3805],{"class":3808},[3416,37323,25075],{"class":6340},[3416,37325,37326],{"class":3808},"Priority-index",[3416,37328,25075],{"class":6340},[3416,37330,3812],{"class":3808},[3416,37332,37333,37335,37338,37340],{"class":3418,"line":3498},[3416,37334,37315],{"class":6340},[3416,37336,37337],{"class":3808},"KeySchema",[3416,37339,25075],{"class":6340},[3416,37341,21353],{"class":3808},[3416,37343,37344,37347,37349,37351,37353,37355,37357,37359,37361,37363,37365,37367,37369,37371,37373,37375,37377],{"class":3418,"line":3504},[3416,37345,37346],{"class":3808},"                    {",[3416,37348,25075],{"class":6340},[3416,37350,10857],{"class":3808},[3416,37352,25075],{"class":6340},[3416,37354,3805],{"class":3808},[3416,37356,25075],{"class":6340},[3416,37358,4494],{"class":3808},[3416,37360,25075],{"class":6340},[3416,37362,4384],{"class":3808},[3416,37364,25075],{"class":6340},[3416,37366,10951],{"class":3808},[3416,37368,25075],{"class":6340},[3416,37370,3805],{"class":3808},[3416,37372,25075],{"class":6340},[3416,37374,10960],{"class":3808},[3416,37376,25075],{"class":6340},[3416,37378,37379],{"class":3808},"},\n",[3416,37381,37382,37384,37386,37388,37390,37392,37394,37397,37399,37401,37403,37405,37407,37409,37411,37413,37415],{"class":3418,"line":3510},[3416,37383,37346],{"class":3808},[3416,37385,25075],{"class":6340},[3416,37387,10857],{"class":3808},[3416,37389,25075],{"class":6340},[3416,37391,3805],{"class":3808},[3416,37393,25075],{"class":6340},[3416,37395,37396],{"class":3808},"Priority",[3416,37398,25075],{"class":6340},[3416,37400,4384],{"class":3808},[3416,37402,25075],{"class":6340},[3416,37404,10951],{"class":3808},[3416,37406,25075],{"class":6340},[3416,37408,3805],{"class":3808},[3416,37410,25075],{"class":6340},[3416,37412,10989],{"class":3808},[3416,37414,25075],{"class":6340},[3416,37416,3507],{"class":3808},[3416,37418,37419],{"class":3418,"line":3515},[3416,37420,37421],{"class":3808},"                ],\n",[3416,37423,37424,37426,37428,37430],{"class":3418,"line":3521},[3416,37425,37315],{"class":6340},[3416,37427,15062],{"class":3808},[3416,37429,25075],{"class":6340},[3416,37431,4403],{"class":3808},[3416,37433,37434,37437,37439,37441,37443,37445,37447],{"class":3418,"line":3527},[3416,37435,37436],{"class":6340},"                    \\\"",[3416,37438,15797],{"class":3808},[3416,37440,25075],{"class":6340},[3416,37442,3805],{"class":3808},[3416,37444,25075],{"class":6340},[3416,37446,15103],{"class":3808},[3416,37448,37449],{"class":6340},"\\\"\n",[3416,37451,37452],{"class":3418,"line":3533},[3416,37453,8810],{"class":3808},[3416,37455,37456],{"class":3418,"line":3539},[3416,37457,8815],{"class":3808},[3416,37459,37460,37463],{"class":3418,"line":3545},[3416,37461,37462],{"class":3808},"        ]\"",[3416,37464,6341],{"class":6340},[3416,37466,37467,37469],{"class":3418,"line":3551},[3416,37468,10753],{"class":4368},[3416,37470,37471],{"class":3808}," PAY_PER_REQUEST\n",[3353,37473,37474],{},[3363,37475,37476],{},"Що тут відбувається:",[4488,37478,37479,37491,37496],{},[3377,37480,37481,37484,37485,4384,37487,4384,37489,13590],{},[3413,37482,37483],{},"AttributeDefinitions",": описує схему типів даних лише для полів, які використовуються в ключах (",[3413,37486,4494],{},[3413,37488,37225],{},[3413,37490,37396],{},[3377,37492,37493,37495],{},[3413,37494,37337],{},": визначає роль полів у первинному ключі.",[3377,37497,37498,37501,37502,37504],{},[3413,37499,37500],{},"LocalSecondaryIndexes",": створює індекс ",[3413,37503,37326],{},", який дозволяє сортувати та шукати задачі конкретного користувача за пріоритетом.",[3720,37506],{},[3727,37508,37510],{"id":37509},"крок-2-додавання-запису-putitem","Крок 2: Додавання запису (PutItem)",[3353,37512,37513,37514,4384,37517,4384,37520,37523],{},"Запишемо перше завдання до бази. Оскільки DynamoDB є безсхемною (schemaless) базою даних, ми можемо передавати будь-яку кількість додаткових атрибутів (наприклад, ",[3413,37515,37516],{},"Title",[3413,37518,37519],{},"Done",[3413,37521,37522],{},"StepsCount","), не оголошуючи їх у схемі таблиці:",[3406,37525,37527],{"className":6316,"code":37526,"language":6318,"meta":3411,"style":3411},"aws dynamodb put-item \\\n    --table-name SandboxTasks \\\n    --item '{\n        \"UserId\": {\"S\": \"user-42\"},\n        \"TaskId\": {\"S\": \"task-001\"},\n        \"Title\": {\"S\": \"Написати документацію по DynamoDB\"},\n        \"Priority\": {\"S\": \"HIGH\"},\n        \"Done\": {\"BOOL\": false},\n        \"StepsCount\": {\"N\": \"5\"},\n        \"Tags\": {\"L\": [{\"S\": \"aws\"}, {\"S\": \"nosql\"}, {\"S\": \"cli\"}]}\n    }'\n",[3413,37528,37529,37539,37547,37553,37558,37563,37568,37573,37578,37583,37588],{"__ignoreMap":3411},[3416,37530,37531,37533,37535,37537],{"class":3418,"line":3419},[3416,37532,6331],{"class":6330},[3416,37534,6334],{"class":3808},[3416,37536,6643],{"class":3808},[3416,37538,6341],{"class":6340},[3416,37540,37541,37543,37545],{"class":3418,"line":3425},[3416,37542,6346],{"class":4368},[3416,37544,37248],{"class":3808},[3416,37546,6341],{"class":6340},[3416,37548,37549,37551],{"class":3418,"line":3431},[3416,37550,6658],{"class":4368},[3416,37552,6661],{"class":3808},[3416,37554,37555],{"class":3418,"line":3437},[3416,37556,37557],{"class":3808},"        \"UserId\": {\"S\": \"user-42\"},\n",[3416,37559,37560],{"class":3418,"line":3444},[3416,37561,37562],{"class":3808},"        \"TaskId\": {\"S\": \"task-001\"},\n",[3416,37564,37565],{"class":3418,"line":3450},[3416,37566,37567],{"class":3808},"        \"Title\": {\"S\": \"Написати документацію по DynamoDB\"},\n",[3416,37569,37570],{"class":3418,"line":3456},[3416,37571,37572],{"class":3808},"        \"Priority\": {\"S\": \"HIGH\"},\n",[3416,37574,37575],{"class":3418,"line":3462},[3416,37576,37577],{"class":3808},"        \"Done\": {\"BOOL\": false},\n",[3416,37579,37580],{"class":3418,"line":3468},[3416,37581,37582],{"class":3808},"        \"StepsCount\": {\"N\": \"5\"},\n",[3416,37584,37585],{"class":3418,"line":3474},[3416,37586,37587],{"class":3808},"        \"Tags\": {\"L\": [{\"S\": \"aws\"}, {\"S\": \"nosql\"}, {\"S\": \"cli\"}]}\n",[3416,37589,37590],{"class":3418,"line":3480},[3416,37591,37592],{"class":3808},"    }'\n",[3353,37594,37595],{},[3363,37596,37597],{},"Зверніть увагу:",[4488,37599,37600],{},[3377,37601,37602,37603,37606,37607,37610,37611,37614,37615,37618],{},"Кожне значення загорнуте в об'єкт із ключем типу даних: ",[3413,37604,37605],{},"{\"S\": \"...\"}"," для String, ",[3413,37608,37609],{},"{\"BOOL\": ...}"," для Boolean, ",[3413,37612,37613],{},"{\"N\": \"...\"}"," для Number (числа передаються як рядки для запобігання втрати точності), ",[3413,37616,37617],{},"{\"L\": [...]}"," для List.",[3720,37620],{},[3727,37622,37624],{"id":37623},"крок-3-читання-запису-за-ключем-getitem","Крок 3: Читання запису за ключем (GetItem)",[3353,37626,37627],{},"Для точкового зчитування запису (Point Read) ми повинні передати повний первинний ключ (як Partition Key, так і Sort Key):",[3406,37629,37631],{"className":6316,"code":37630,"language":6318,"meta":3411,"style":3411},"aws dynamodb get-item \\\n    --table-name SandboxTasks \\\n    --key '{\n        \"UserId\": {\"S\": \"user-42\"},\n        \"TaskId\": {\"S\": \"task-001\"}\n    }'\n",[3413,37632,37633,37643,37651,37657,37661,37666],{"__ignoreMap":3411},[3416,37634,37635,37637,37639,37641],{"class":3418,"line":3419},[3416,37636,6331],{"class":6330},[3416,37638,6334],{"class":3808},[3416,37640,6337],{"class":3808},[3416,37642,6341],{"class":6340},[3416,37644,37645,37647,37649],{"class":3418,"line":3425},[3416,37646,6346],{"class":4368},[3416,37648,37248],{"class":3808},[3416,37650,6341],{"class":6340},[3416,37652,37653,37655],{"class":3418,"line":3431},[3416,37654,6356],{"class":4368},[3416,37656,6661],{"class":3808},[3416,37658,37659],{"class":3418,"line":3437},[3416,37660,37557],{"class":3808},[3416,37662,37663],{"class":3418,"line":3444},[3416,37664,37665],{"class":3808},"        \"TaskId\": {\"S\": \"task-001\"}\n",[3416,37667,37668],{"class":3418,"line":3450},[3416,37669,37592],{"class":3808},[3353,37671,37672],{},[3363,37673,37674],{},"Очікувана відповідь від бази:",[3406,37676,37678],{"className":3780,"code":37677,"language":3782,"meta":3411,"style":3411},"{\n    \"Item\": {\n        \"StepsCount\": {\"N\": \"5\"},\n        \"UserId\": {\"S\": \"user-42\"},\n        \"TaskId\": {\"S\": \"task-001\"},\n        \"Done\": {\"BOOL\": false},\n        \"Title\": {\"S\": \"Написати документацію по DynamoDB\"},\n        \"Priority\": {\"S\": \"HIGH\"},\n        \"Tags\": {\"L\": [{\"S\": \"aws\"}, {\"S\": \"nosql\"}, {\"S\": \"cli\"}]}\n    }\n}\n",[3413,37679,37680,37684,37691,37708,37724,37740,37755,37771,37787,37829,37833],{"__ignoreMap":3411},[3416,37681,37682],{"class":3418,"line":3419},[3416,37683,3796],{"class":3795},[3416,37685,37686,37689],{"class":3418,"line":3425},[3416,37687,37688],{"class":3801},"    \"Item\"",[3416,37690,4403],{"class":3795},[3416,37692,37693,37696,37698,37701,37703,37706],{"class":3418,"line":3431},[3416,37694,37695],{"class":3801},"        \"StepsCount\"",[3416,37697,11187],{"class":3795},[3416,37699,37700],{"class":3801},"\"N\"",[3416,37702,3805],{"class":3795},[3416,37704,37705],{"class":3808},"\"5\"",[3416,37707,37379],{"class":3795},[3416,37709,37710,37713,37715,37717,37719,37722],{"class":3418,"line":3437},[3416,37711,37712],{"class":3801},"        \"UserId\"",[3416,37714,11187],{"class":3795},[3416,37716,13450],{"class":3801},[3416,37718,3805],{"class":3795},[3416,37720,37721],{"class":3808},"\"user-42\"",[3416,37723,37379],{"class":3795},[3416,37725,37726,37729,37731,37733,37735,37738],{"class":3418,"line":3444},[3416,37727,37728],{"class":3801},"        \"TaskId\"",[3416,37730,11187],{"class":3795},[3416,37732,13450],{"class":3801},[3416,37734,3805],{"class":3795},[3416,37736,37737],{"class":3808},"\"task-001\"",[3416,37739,37379],{"class":3795},[3416,37741,37742,37745,37747,37749,37751,37753],{"class":3418,"line":3450},[3416,37743,37744],{"class":3801},"        \"Done\"",[3416,37746,11187],{"class":3795},[3416,37748,13477],{"class":3801},[3416,37750,3805],{"class":3795},[3416,37752,4042],{"class":4368},[3416,37754,37379],{"class":3795},[3416,37756,37757,37760,37762,37764,37766,37769],{"class":3418,"line":3456},[3416,37758,37759],{"class":3801},"        \"Title\"",[3416,37761,11187],{"class":3795},[3416,37763,13450],{"class":3801},[3416,37765,3805],{"class":3795},[3416,37767,37768],{"class":3808},"\"Написати документацію по DynamoDB\"",[3416,37770,37379],{"class":3795},[3416,37772,37773,37776,37778,37780,37782,37785],{"class":3418,"line":3462},[3416,37774,37775],{"class":3801},"        \"Priority\"",[3416,37777,11187],{"class":3795},[3416,37779,13450],{"class":3801},[3416,37781,3805],{"class":3795},[3416,37783,37784],{"class":3808},"\"HIGH\"",[3416,37786,37379],{"class":3795},[3416,37788,37789,37792,37794,37797,37800,37802,37804,37807,37810,37812,37814,37817,37819,37821,37823,37826],{"class":3418,"line":3468},[3416,37790,37791],{"class":3801},"        \"Tags\"",[3416,37793,11187],{"class":3795},[3416,37795,37796],{"class":3801},"\"L\"",[3416,37798,37799],{"class":3795},": [{",[3416,37801,13450],{"class":3801},[3416,37803,3805],{"class":3795},[3416,37805,37806],{"class":3808},"\"aws\"",[3416,37808,37809],{"class":3795},"}, {",[3416,37811,13450],{"class":3801},[3416,37813,3805],{"class":3795},[3416,37815,37816],{"class":3808},"\"nosql\"",[3416,37818,37809],{"class":3795},[3416,37820,13450],{"class":3801},[3416,37822,3805],{"class":3795},[3416,37824,37825],{"class":3808},"\"cli\"",[3416,37827,37828],{"class":3795},"}]}\n",[3416,37830,37831],{"class":3418,"line":3474},[3416,37832,4167],{"class":3795},[3416,37834,37835],{"class":3418,"line":3480},[3416,37836,3507],{"class":3795},[3720,37838],{},[3727,37840,37842],{"id":37841},"крок-4-умовне-оновлення-з-перевіркою-версії-updateitem-conditionexpression","Крок 4: Умовне оновлення з перевіркою версії (UpdateItem & ConditionExpression)",[3353,37844,37845,37846,37849,37850,37853],{},"Виконаємо оновлення статусу виконання задачі (",[3413,37847,37848],{},"Done = true","), але додамо умову: оновлювати лише якщо задача має статус ",[3413,37851,37852],{},"Done = false"," (Condition Expression). Це демонструє базову механіку уникнення конфліктів:",[3406,37855,37857],{"className":6316,"code":37856,"language":6318,"meta":3411,"style":3411},"aws dynamodb update-item \\\n    --table-name SandboxTasks \\\n    --key '{\n        \"UserId\": {\"S\": \"user-42\"},\n        \"TaskId\": {\"S\": \"task-001\"}\n    }' \\\n    --update-expression \"SET Done = :new_status\" \\\n    --condition-expression \"Done = :expected_status\" \\\n    --expression-attribute-values '{\n        \":new_status\": {\"BOOL\": true},\n        \":expected_status\": {\"BOOL\": false}\n    }' \\\n    --return-values ALL_NEW\n",[3413,37858,37859,37869,37877,37883,37887,37891,37897,37906,37915,37921,37926,37931,37937],{"__ignoreMap":3411},[3416,37860,37861,37863,37865,37867],{"class":3418,"line":3419},[3416,37862,6331],{"class":6330},[3416,37864,6334],{"class":3808},[3416,37866,6988],{"class":3808},[3416,37868,6341],{"class":6340},[3416,37870,37871,37873,37875],{"class":3418,"line":3425},[3416,37872,6346],{"class":4368},[3416,37874,37248],{"class":3808},[3416,37876,6341],{"class":6340},[3416,37878,37879,37881],{"class":3418,"line":3431},[3416,37880,6356],{"class":4368},[3416,37882,6661],{"class":3808},[3416,37884,37885],{"class":3418,"line":3437},[3416,37886,37557],{"class":3808},[3416,37888,37889],{"class":3418,"line":3444},[3416,37890,37665],{"class":3808},[3416,37892,37893,37895],{"class":3418,"line":3450},[3416,37894,6686],{"class":3808},[3416,37896,6341],{"class":6340},[3416,37898,37899,37901,37904],{"class":3418,"line":3456},[3416,37900,7011],{"class":4368},[3416,37902,37903],{"class":3808}," \"SET Done = :new_status\"",[3416,37905,6341],{"class":6340},[3416,37907,37908,37910,37913],{"class":3418,"line":3462},[3416,37909,30092],{"class":4368},[3416,37911,37912],{"class":3808}," \"Done = :expected_status\"",[3416,37914,6341],{"class":6340},[3416,37916,37917,37919],{"class":3418,"line":3468},[3416,37918,7021],{"class":4368},[3416,37920,6661],{"class":3808},[3416,37922,37923],{"class":3418,"line":3474},[3416,37924,37925],{"class":3808},"        \":new_status\": {\"BOOL\": true},\n",[3416,37927,37928],{"class":3418,"line":3480},[3416,37929,37930],{"class":3808},"        \":expected_status\": {\"BOOL\": false}\n",[3416,37932,37933,37935],{"class":3418,"line":3486},[3416,37934,6686],{"class":3808},[3416,37936,6341],{"class":6340},[3416,37938,37939,37942],{"class":3418,"line":3492},[3416,37940,37941],{"class":4368},"    --return-values",[3416,37943,37944],{"class":3808}," ALL_NEW\n",[3353,37946,37947],{},[3363,37948,37476],{},[4488,37950,37951,37960,37974],{},[3377,37952,37953,37956,37957,4043],{},[3413,37954,37955],{},"UpdateExpression",": визначає зміну атрибута за допомогою плейсхолдера ",[3413,37958,37959],{},":new_status",[3377,37961,37962,37964,37965,37967,37968,37971,37972,13590],{},[3413,37963,13830],{},": вказує, що операція запису відбудеться лише якщо поточне значення ",[3413,37966,37519],{}," дорівнює плейсхолдеру ",[3413,37969,37970],{},":expected_status"," (тобто ",[3413,37973,4042],{},[3377,37975,37976,37979],{},[3413,37977,37978],{},"ReturnValues ALL_NEW",": каже базі повернути оновлений об'єкт.",[3353,37981,37982,37985,37986,37989,37990,37992,37993,37995],{},[3363,37983,37984],{},"Результат повторного виконання:","\nЯкщо ви виконаєте цю саму команду вдруге, операція завершиться помилкою:\n",[3413,37987,37988],{},"An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation:","\nОскільки статус у базі вже став ",[3413,37991,4038],{},", умова ",[3413,37994,37852],{}," більше не виконується.",[3720,37997],{},[3727,37999,38001],{"id":38000},"крок-5-пошук-за-допомогою-запитів-query","Крок 5: Пошук за допомогою запитів (Query)",[4584,38003,38005],{"id":38004},"а-запит-за-головним-ключем","А. Запит за головним ключем",[3353,38007,38008,38009,38012,38013,10458],{},"Отримаємо список усіх задач користувача ",[3413,38010,38011],{},"user-42",", які починаються на префікс ",[3413,38014,38015],{},"task-",[3406,38017,38019],{"className":6316,"code":38018,"language":6318,"meta":3411,"style":3411},"aws dynamodb query \\\n    --table-name SandboxTasks \\\n    --key-condition-expression \"UserId = :uid AND TaskId begins_with(:task_prefix)\" \\\n    --expression-attribute-values '{\n        \":uid\": {\"S\": \"user-42\"},\n        \":task_prefix\": {\"S\": \"task-\"}\n    }'\n",[3413,38020,38021,38031,38039,38048,38054,38059,38064],{"__ignoreMap":3411},[3416,38022,38023,38025,38027,38029],{"class":3418,"line":3419},[3416,38024,6331],{"class":6330},[3416,38026,6334],{"class":3808},[3416,38028,7676],{"class":3808},[3416,38030,6341],{"class":6340},[3416,38032,38033,38035,38037],{"class":3418,"line":3425},[3416,38034,6346],{"class":4368},[3416,38036,37248],{"class":3808},[3416,38038,6341],{"class":6340},[3416,38040,38041,38043,38046],{"class":3418,"line":3431},[3416,38042,7691],{"class":4368},[3416,38044,38045],{"class":3808}," \"UserId = :uid AND TaskId begins_with(:task_prefix)\"",[3416,38047,6341],{"class":6340},[3416,38049,38050,38052],{"class":3418,"line":3437},[3416,38051,7021],{"class":4368},[3416,38053,6661],{"class":3808},[3416,38055,38056],{"class":3418,"line":3444},[3416,38057,38058],{"class":3808},"        \":uid\": {\"S\": \"user-42\"},\n",[3416,38060,38061],{"class":3418,"line":3450},[3416,38062,38063],{"class":3808},"        \":task_prefix\": {\"S\": \"task-\"}\n",[3416,38065,38066],{"class":3418,"line":3456},[3416,38067,37592],{"class":3808},[4584,38069,38071],{"id":38070},"б-запит-за-допомогою-вторинного-індексу-lsi","Б. Запит за допомогою вторинного індексу LSI",[3353,38073,38074,38075,38077,38078,38081],{},"Тепер скористаємося індексом ",[3413,38076,37326],{},", щоб отримати лише задачі з високим пріоритетом (",[3413,38079,38080],{},"HIGH","), відсортовані за спаданням:",[3406,38083,38085],{"className":6316,"code":38084,"language":6318,"meta":3411,"style":3411},"aws dynamodb query \\\n    --table-name SandboxTasks \\\n    --index-name Priority-index \\\n    --key-condition-expression \"UserId = :uid AND Priority = :priority\" \\\n    --expression-attribute-values '{\n        \":uid\": {\"S\": \"user-42\"},\n        \":priority\": {\"S\": \"HIGH\"}\n    }'\n",[3413,38086,38087,38097,38105,38114,38123,38129,38133,38138],{"__ignoreMap":3411},[3416,38088,38089,38091,38093,38095],{"class":3418,"line":3419},[3416,38090,6331],{"class":6330},[3416,38092,6334],{"class":3808},[3416,38094,7676],{"class":3808},[3416,38096,6341],{"class":6340},[3416,38098,38099,38101,38103],{"class":3418,"line":3425},[3416,38100,6346],{"class":4368},[3416,38102,37248],{"class":3808},[3416,38104,6341],{"class":6340},[3416,38106,38107,38109,38112],{"class":3418,"line":3431},[3416,38108,16188],{"class":4368},[3416,38110,38111],{"class":3808}," Priority-index",[3416,38113,6341],{"class":6340},[3416,38115,38116,38118,38121],{"class":3418,"line":3437},[3416,38117,7691],{"class":4368},[3416,38119,38120],{"class":3808}," \"UserId = :uid AND Priority = :priority\"",[3416,38122,6341],{"class":6340},[3416,38124,38125,38127],{"class":3418,"line":3444},[3416,38126,7021],{"class":4368},[3416,38128,6661],{"class":3808},[3416,38130,38131],{"class":3418,"line":3450},[3416,38132,38058],{"class":3808},[3416,38134,38135],{"class":3418,"line":3456},[3416,38136,38137],{"class":3808},"        \":priority\": {\"S\": \"HIGH\"}\n",[3416,38139,38140],{"class":3418,"line":3462},[3416,38141,37592],{"class":3808},[3720,38143],{},[3727,38145,38147],{"id":38146},"крок-6-видалення-запису-та-очищення-deleteitem","Крок 6: Видалення запису та очищення (DeleteItem)",[3353,38149,38150],{},"Видалимо створену задачу:",[3406,38152,38154],{"className":6316,"code":38153,"language":6318,"meta":3411,"style":3411},"aws dynamodb delete-item \\\n    --table-name SandboxTasks \\\n    --key '{\n        \"UserId\": {\"S\": \"user-42\"},\n        \"TaskId\": {\"S\": \"task-001\"}\n    }'\n",[3413,38155,38156,38166,38174,38180,38184,38188],{"__ignoreMap":3411},[3416,38157,38158,38160,38162,38164],{"class":3418,"line":3419},[3416,38159,6331],{"class":6330},[3416,38161,6334],{"class":3808},[3416,38163,7432],{"class":3808},[3416,38165,6341],{"class":6340},[3416,38167,38168,38170,38172],{"class":3418,"line":3425},[3416,38169,6346],{"class":4368},[3416,38171,37248],{"class":3808},[3416,38173,6341],{"class":6340},[3416,38175,38176,38178],{"class":3418,"line":3431},[3416,38177,6356],{"class":4368},[3416,38179,6661],{"class":3808},[3416,38181,38182],{"class":3418,"line":3437},[3416,38183,37557],{"class":3808},[3416,38185,38186],{"class":3418,"line":3444},[3416,38187,37665],{"class":3808},[3416,38189,38190],{"class":3418,"line":3450},[3416,38191,37592],{"class":3808},[3353,38193,38194],{},"Для повного видалення таблиці після експериментів виконайте:",[3406,38196,38198],{"className":6316,"code":38197,"language":6318,"meta":3411,"style":3411},"aws dynamodb delete-table \\\n    --table-name SandboxTasks\n",[3413,38199,38200,38211],{"__ignoreMap":3411},[3416,38201,38202,38204,38206,38209],{"class":3418,"line":3419},[3416,38203,6331],{"class":6330},[3416,38205,6334],{"class":3808},[3416,38207,38208],{"class":3808}," delete-table",[3416,38210,6341],{"class":6340},[3416,38212,38213,38215],{"class":3418,"line":3425},[3416,38214,6346],{"class":4368},[3416,38216,38217],{"class":3808}," SandboxTasks\n",[3720,38219],{},[3348,38221,38223],{"id":38222},"практичний-приклад-c-web-api-dynamodb-від-а-до-я","Практичний приклад: C# Web API + DynamoDB від А до Я",[3353,38225,38226,38227,38229],{},"У цьому розділі ми розберемо реалізацію повноцінного production-готового веб-сервісу з управління завданнями (Task Management API) на ASP.NET Core від А до Я. Наш застосунок підтримуватиме повний CRUD-цикл за допомогою OPM ORM (",[3413,38228,30279],{},") та вибірку за глобальним вторинним індексом (GSI).",[3353,38231,38232,38233,38236,38237,38239],{},"Основним середовищем розгортання є ",[3363,38234,38235],{},"реальна хмара AWS"," (з керуванням ресурсами через веб-консоль та автентифікацією через AWS CLI), а використання локального контейнера з ",[3363,38238,30785],{}," охарактеризовано як альтернативний спрощений шлях.",[3720,38241],{},[3727,38243,38245],{"id":38244},"крок-1-підготовка-інфраструктури-aws-console-credentials-альтернатива","Крок 1: Підготовка інфраструктури (AWS Console, Credentials & Альтернатива)",[3353,38247,38248],{},"Для початку роботи нам необхідно створити таблицю в хмарі AWS та налаштувати права доступу на локальній машині розробника.",[38250,38251,38252,38256,38259,38410,38414,38419,38470,38482,38489,38493,38496],"steps",{},[3727,38253,38255],{"id":38254},"_1-створення-таблиці-через-aws-management-console","1. Створення таблиці через AWS Management Console",[3353,38257,38258],{},"Для створення таблиці вручну виконайте такі кроки:",[3374,38260,38261,38271,38277,38283,38319,38356,38401],{},[3377,38262,38263,38264,38270],{},"Відкрийте ",[4675,38265,38269],{"href":38266,"rel":38267},"https:\u002F\u002Faws.amazon.com\u002Fconsole\u002F",[38268],"nofollow","AWS Management Console"," та авторизуйтесь у вашому акаунті.",[3377,38272,38273,38274,38276],{},"У полі пошуку сервісів введіть ",[3363,38275,10442],{}," та перейдіть на головну сторінку сервісу.",[3377,38278,38279,38280,38282],{},"Натисніть кнопку ",[3363,38281,10449],{}," (Створити таблицю).",[3377,38284,38285,38286,38289,38290],{},"У секції ",[3363,38287,38288],{},"Table details"," вкажіть такі параметри:\n",[4488,38291,38292,38300,38310],{},[3377,38293,38294,3805,38297],{},[3363,38295,38296],{},"Table name",[3413,38298,38299],{},"UserTasks",[3377,38301,38302,3805,38305,38307,38308,6259],{},[3363,38303,38304],{},"Partition key",[3413,38306,4494],{}," (тип залишіть як ",[3363,38309,4605],{},[3377,38311,38312,3805,38315,38307,38317,6259],{},[3363,38313,38314],{},"Sort key",[3413,38316,37225],{},[3363,38318,4605],{},[3377,38320,38285,38321,38324,38325,38328,38329],{},[3363,38322,38323],{},"Table settings"," виберіть пункт ",[3363,38326,38327],{},"Customize settings"," (Налаштувати параметри):\n",[4488,38330,38331,38337,38347],{},[3377,38332,38333,38336],{},[3363,38334,38335],{},"Capacity calculator",": пропустіть цей пункт.",[3377,38338,38339,38342,38343,38346],{},[3363,38340,38341],{},"Table class",": виберіть ",[3363,38344,38345],{},"DynamoDB Standard"," (за замовчуванням).",[3377,38348,38349,38342,38352,38355],{},[3363,38350,38351],{},"Read\u002Fwrite capacity mode",[3363,38353,38354],{},"On-demand"," (за запитом). Це найкращий варіант для навчання та тестування, оскільки ви платите лише за фактично виконані запити, а не за зарезервовану ємність (WCU\u002FRCU).",[3377,38357,38358,38359,38362,38363,36401,38366],{},"Прокрутіть вниз до секції ",[3363,38360,38361],{},"Global secondary indexes"," (Глобальні вторинні індекси) та натисніть ",[3363,38364,38365],{},"Create index",[4488,38367,38368,38376,38386,38395],{},[3377,38369,38370,3805,38372,4602,38374,6259],{},[3363,38371,38304],{},[3413,38373,5147],{},[3363,38375,4605],{},[3377,38377,38378,38381,38382,38385],{},[3363,38379,38380],{},"Index name",": автоматично підставиться ",[3413,38383,38384],{},"Status-index"," (якщо ні, введіть вручну).",[3377,38387,38388,38342,38391,38394],{},[3363,38389,38390],{},"Attribute projections",[3363,38392,38393],{},"All"," (це дозволить копіювати всі поля запису у вторинний індекс).",[3377,38396,38397,38398,38400],{},"Натисніть ",[3363,38399,38365],{}," у спливаючому вікні.",[3377,38402,38403,38404,38406,38407,4043],{},"Прокрутіть сторінку до самого кінця та натисніть кнопку ",[3363,38405,10449],{},". Створення таблиці триває близько 10-30 секунд, статус зміниться на ",[3363,38408,38409],{},"Active",[3727,38411,38413],{"id":38412},"_2-налаштування-локальних-aws-credentials","2. Налаштування локальних AWS Credentials",[3353,38415,38416,38417,10458],{},"Веб-додаток на C# під час запуску локально на вашому комп'ютері використовує офіційний AWS SDK. Щоб він міг авторизуватися в хмарі AWS, потрібно налаштувати облікові дані на локальній машині за допомогою ",[3363,38418,37109],{},[3374,38420,38421,38435],{},[3377,38422,38423,38424],{},"Відкрийте термінал та запустіть команду налаштування:\n",[3406,38425,38427],{"className":6316,"code":38426,"language":6318,"meta":3411,"style":3411},"aws configure\n",[3413,38428,38429],{"__ignoreMap":3411},[3416,38430,38431,38433],{"class":3418,"line":3419},[3416,38432,6331],{"class":6330},[3416,38434,37151],{"class":3808},[3377,38436,38437,38438],{},"Утиліта запитає у вас конфігураційні дані:\n",[4488,38439,38440,38448,38456,38463],{},[3377,38441,38442,38444,38445,13590],{},[3363,38443,37161],{},": введіть ваш ключ доступу IAM-коривувача (наприклад, ",[3413,38446,38447],{},"AKIAIOSFODNN7EXAMPLE",[3377,38449,38450,38452,38453,13590],{},[3363,38451,37167],{},": введіть ваш секретний ключ (наприклад, ",[3413,38454,38455],{},"wJalrXUtnFEMI\u002FK7MDENG\u002FbPxRfiCYEXAMPLEKEY",[3377,38457,38458,38460,38461,13590],{},[3363,38459,37173],{},": введіть регіон, у якому ви створили таблицю (наприклад, ",[3413,38462,37177],{},[3377,38464,38465,38467,38468,4043],{},[3363,38466,37182],{},": залишіть порожнім або введіть ",[3413,38469,3782],{},[22319,38471,38472],{},[3353,38473,38474,38476,38477,38479,38480,13590],{},[3416,38475,27452],{},"\nПереконайтеся, що ваш IAM-користувач, ключі якого ви ввели, має права доступу на роботу з DynamoDB (наприклад, політику ",[3413,38478,37134],{}," або точкові права на читання\u002Fзапис до таблиці ",[3413,38481,38299],{},[3353,38483,38484,38485,38488],{},"Тепер під час запуску додатку AWS SDK автоматично підхопить конфігурацію з файлу ",[3413,38486,38487],{},"~\u002F.aws\u002Fcredentials"," та надішле запити до реальної бази у хмарі.",[3727,38490,38492],{"id":38491},"_3-альтернатива-локальний-запуск-через-docker-compose-dynamodb-local","3. Альтернатива: Локальний запуск через Docker Compose (DynamoDB Local)",[3353,38494,38495],{},"Якщо ви бажаєте протестувати код локально без використання реального хмарного акаунту AWS, ви можете запустити базу даних у локальному Docker-контейнері:",[3374,38497,38498,38669,38691],{},[3377,38499,38500,38501,36401,38504],{},"Створіть у корені проєкту файл ",[3413,38502,38503],{},"docker-compose.yml",[3406,38505,38509],{"className":38506,"code":38507,"filename":38503,"language":38508,"meta":3411,"style":3411},"language-yaml shiki shiki-themes light-plus dark-plus dark-plus","version: '3.8'\n\nservices:\n  dynamodb-local:\n    image: amazon\u002Fdynamodb-local:latest\n    container_name: dynamodb-local\n    ports:\n      - \"8000:8000\"\n    volumes:\n      - \".\u002Fdocker\u002Fdynamodb:\u002Fhome\u002Fdynamodblocal-data\"\n    command: \"-jar DynamoDBLocal.jar -sharedDb -dbPath \u002Fhome\u002Fdynamodblocal-data\"\n\n  dynamodb-admin:\n    image: aaronshaf\u002Fdynamodb-admin:latest\n    container_name: dynamodb-admin\n    ports:\n      - \"8001:8001\"\n    environment:\n      - DYNAMO_ENDPOINT=http:\u002F\u002Fdynamodb-local:8000\n    depends_on:\n      - dynamodb-local\n","yaml",[3413,38510,38511,38523,38527,38534,38541,38551,38561,38568,38576,38583,38590,38600,38604,38611,38620,38629,38635,38642,38649,38656,38663],{"__ignoreMap":3411},[3416,38512,38513,38517,38519],{"class":3418,"line":3419},[3416,38514,38516],{"class":38515},"sKtos","version",[3416,38518,3805],{"class":3795},[3416,38520,38522],{"class":38521},"su9tN","'3.8'\n",[3416,38524,38525],{"class":3418,"line":3425},[3416,38526,3441],{"emptyLinePlaceholder":3440},[3416,38528,38529,38532],{"class":3418,"line":3431},[3416,38530,38531],{"class":38515},"services",[3416,38533,36401],{"class":3795},[3416,38535,38536,38539],{"class":3418,"line":3437},[3416,38537,38538],{"class":38515},"  dynamodb-local",[3416,38540,36401],{"class":3795},[3416,38542,38543,38546,38548],{"class":3418,"line":3444},[3416,38544,38545],{"class":38515},"    image",[3416,38547,3805],{"class":3795},[3416,38549,38550],{"class":38521},"amazon\u002Fdynamodb-local:latest\n",[3416,38552,38553,38556,38558],{"class":3418,"line":3450},[3416,38554,38555],{"class":38515},"    container_name",[3416,38557,3805],{"class":3795},[3416,38559,38560],{"class":38521},"dynamodb-local\n",[3416,38562,38563,38566],{"class":3418,"line":3456},[3416,38564,38565],{"class":38515},"    ports",[3416,38567,36401],{"class":3795},[3416,38569,38570,38573],{"class":3418,"line":3462},[3416,38571,38572],{"class":3795},"      - ",[3416,38574,38575],{"class":3808},"\"8000:8000\"\n",[3416,38577,38578,38581],{"class":3418,"line":3468},[3416,38579,38580],{"class":38515},"    volumes",[3416,38582,36401],{"class":3795},[3416,38584,38585,38587],{"class":3418,"line":3474},[3416,38586,38572],{"class":3795},[3416,38588,38589],{"class":3808},"\".\u002Fdocker\u002Fdynamodb:\u002Fhome\u002Fdynamodblocal-data\"\n",[3416,38591,38592,38595,38597],{"class":3418,"line":3480},[3416,38593,38594],{"class":38515},"    command",[3416,38596,3805],{"class":3795},[3416,38598,38599],{"class":3808},"\"-jar DynamoDBLocal.jar -sharedDb -dbPath \u002Fhome\u002Fdynamodblocal-data\"\n",[3416,38601,38602],{"class":3418,"line":3486},[3416,38603,3441],{"emptyLinePlaceholder":3440},[3416,38605,38606,38609],{"class":3418,"line":3492},[3416,38607,38608],{"class":38515},"  dynamodb-admin",[3416,38610,36401],{"class":3795},[3416,38612,38613,38615,38617],{"class":3418,"line":3498},[3416,38614,38545],{"class":38515},[3416,38616,3805],{"class":3795},[3416,38618,38619],{"class":38521},"aaronshaf\u002Fdynamodb-admin:latest\n",[3416,38621,38622,38624,38626],{"class":3418,"line":3504},[3416,38623,38555],{"class":38515},[3416,38625,3805],{"class":3795},[3416,38627,38628],{"class":38521},"dynamodb-admin\n",[3416,38630,38631,38633],{"class":3418,"line":3510},[3416,38632,38565],{"class":38515},[3416,38634,36401],{"class":3795},[3416,38636,38637,38639],{"class":3418,"line":3515},[3416,38638,38572],{"class":3795},[3416,38640,38641],{"class":3808},"\"8001:8001\"\n",[3416,38643,38644,38647],{"class":3418,"line":3521},[3416,38645,38646],{"class":38515},"    environment",[3416,38648,36401],{"class":3795},[3416,38650,38651,38653],{"class":3418,"line":3527},[3416,38652,38572],{"class":3795},[3416,38654,38655],{"class":38521},"DYNAMO_ENDPOINT=http:\u002F\u002Fdynamodb-local:8000\n",[3416,38657,38658,38661],{"class":3418,"line":3533},[3416,38659,38660],{"class":38515},"    depends_on",[3416,38662,36401],{"class":3795},[3416,38664,38665,38667],{"class":3418,"line":3539},[3416,38666,38572],{"class":3795},[3416,38668,38560],{"class":38521},[3377,38670,38671,38672],{},"Запустіть Docker-контейнер командою:\n",[3406,38673,38675],{"className":6316,"code":38674,"language":6318,"meta":3411,"style":3411},"docker compose up -d\n",[3413,38676,38677],{"__ignoreMap":3411},[3416,38678,38679,38682,38685,38688],{"class":3418,"line":3419},[3416,38680,38681],{"class":6330},"docker",[3416,38683,38684],{"class":3808}," compose",[3416,38686,38687],{"class":3808}," up",[3416,38689,38690],{"class":4368}," -d\n",[3377,38692,38693,38694,38697,38698,38701,38702,38704],{},"Після старту перейдіть за адресою ",[3413,38695,38696],{},"http:\u002F\u002Flocalhost:8001",", щоб користуватися графічним інтерфейсом адміністрування бази. При виборі локального варіанту обов'язково встановіть ",[3413,38699,38700],{},"\"LocalMode\": true"," у файлі конфігурації ",[3413,38703,30480],{}," (описано у Кроці 3), і додаток автоматично створить потрібну таблицю та індекс при запуску.",[3720,38706],{},[3727,38708,38710],{"id":38709},"крок-2-створення-та-структура-c-проєкту-aspnet-core-web-api","Крок 2: Створення та структура C# проєкту (ASP.NET Core Web API)",[3353,38712,38713],{},"Створимо новий проєкт веб-інтерфейсу за допомогою .NET CLI та додамо модель даних для завдань. Кожне завдання матиме:",[4488,38715,38716,38722,38728,38742,38746],{},[3377,38717,38718,38719,38721],{},"Partition Key: ",[3413,38720,4494],{}," (ідентифікатор користувача)",[3377,38723,38724,38725,38727],{},"Sort Key: ",[3413,38726,37225],{}," (ідентифікатор завдання)",[3377,38729,38730,38731,34439,38733,4384,38736,4384,38739,6259],{},"Атрибут ",[3413,38732,5147],{},[3413,38734,38735],{},"TODO",[3413,38737,38738],{},"IN_PROGRESS",[3413,38740,38741],{},"DONE",[3377,38743,38730,38744],{},[3413,38745,37396],{},[3377,38747,38748,38749,38751],{},"Мапування GSI ",[3413,38750,38384],{}," для вибірки завдань за статусом.",[38250,38753,38754,38758,38761,38831,38835,38842],{},[3727,38755,38757],{"id":38756},"_1-ініціалізація-проєкту-та-встановлення-nuget-пакетів","1. Ініціалізація проєкту та встановлення NuGet-пакетів",[3353,38759,38760],{},"Виконайте наступні команди у терміналі:",[3406,38762,38764],{"className":6316,"code":38763,"language":6318,"meta":3411,"style":3411},"# Створюємо Minimal Web API проєкт\ndotnet new web -o TaskManager.Api\n\n# Переходимо до папки проєкту\ncd TaskManager.Api\n\n# Встановлюємо пакети AWS SDK\ndotnet add package AWSSDK.DynamoDBv2\ndotnet add package AWSSDK.Extensions.NETCore.Setup\n",[3413,38765,38766,38771,38786,38790,38795,38802,38806,38811,38821],{"__ignoreMap":3411},[3416,38767,38768],{"class":3418,"line":3419},[3416,38769,38770],{"class":3789},"# Створюємо Minimal Web API проєкт\n",[3416,38772,38773,38775,38777,38780,38783],{"class":3418,"line":3425},[3416,38774,30444],{"class":6330},[3416,38776,30905],{"class":3808},[3416,38778,38779],{"class":3808}," web",[3416,38781,38782],{"class":4368}," -o",[3416,38784,38785],{"class":3808}," TaskManager.Api\n",[3416,38787,38788],{"class":3418,"line":3431},[3416,38789,3441],{"emptyLinePlaceholder":3440},[3416,38791,38792],{"class":3418,"line":3437},[3416,38793,38794],{"class":3789},"# Переходимо до папки проєкту\n",[3416,38796,38797,38800],{"class":3418,"line":3444},[3416,38798,38799],{"class":6330},"cd",[3416,38801,38785],{"class":3808},[3416,38803,38804],{"class":3418,"line":3450},[3416,38805,3441],{"emptyLinePlaceholder":3440},[3416,38807,38808],{"class":3418,"line":3456},[3416,38809,38810],{"class":3789},"# Встановлюємо пакети AWS SDK\n",[3416,38812,38813,38815,38817,38819],{"class":3418,"line":3462},[3416,38814,30444],{"class":6330},[3416,38816,30447],{"class":3808},[3416,38818,30450],{"class":3808},[3416,38820,30453],{"class":3808},[3416,38822,38823,38825,38827,38829],{"class":3418,"line":3468},[3416,38824,30444],{"class":6330},[3416,38826,30447],{"class":3808},[3416,38828,30450],{"class":3808},[3416,38830,30473],{"class":3808},[3727,38832,38834],{"id":38833},"_2-створення-моделі-сутності-taskitem","2. Створення моделі сутності TaskItem",[3353,38836,38837,38838,38841],{},"Створимо клас ",[3413,38839,38840],{},"TaskItem",", розмітивши його атрибутами OPM ORM:",[38843,38844,38845],"code-tree",{},[3406,38846,38849],{"className":6375,"code":38847,"filename":38848,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2.DataModel;\n\nnamespace TaskManager.Api.Models;\n\n[DynamoDBTable(\"UserTasks\")]\npublic class TaskItem\n{\n    [DynamoDBHashKey(\"UserId\")] \u002F\u002F Partition Key\n    public string UserId { get; set; } = string.Empty;\n\n    [DynamoDBRangeKey(\"TaskId\")] \u002F\u002F Sort Key\n    public string TaskId { get; set; } = string.Empty;\n\n    [DynamoDBProperty(\"Title\")]\n    public string Title { get; set; } = string.Empty;\n\n    [DynamoDBProperty(\"Description\")]\n    public string Description { get; set; } = string.Empty;\n\n    \u002F\u002F HASH-ключ для GSI \"Status-index\"\n    [DynamoDBGlobalSecondaryIndexHashKey(\"Status-index\", AttributeName = \"Status\")]\n    public string Status { get; set; } = \"TODO\";\n\n    [DynamoDBProperty(\"Priority\")]\n    public string Priority { get; set; } = \"MEDIUM\";\n\n    [DynamoDBProperty(\"CreatedAt\")]\n    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;\n\n    \u002F\u002F Оптимістичне блокування версії\n    [DynamoDBVersion]\n    public int? Version { get; set; }\n}\n","Models\u002FTaskItem.cs",[3413,38850,38851,38867,38871,38890,38894,38907,38916,38920,38935,38962,38966,38982,39009,39013,39025,39051,39055,39068,39095,39099,39104,39125,39149,39153,39166,39190,39194,39206,39234,39238,39243,39251,39271],{"__ignoreMap":3411},[3416,38852,38853,38855,38857,38859,38861,38863,38865],{"class":3418,"line":3419},[3416,38854,17433],{"class":11427},[3416,38856,17436],{"class":6397},[3416,38858,4043],{"class":3795},[3416,38860,17441],{"class":6397},[3416,38862,4043],{"class":3795},[3416,38864,30594],{"class":6397},[3416,38866,11594],{"class":3795},[3416,38868,38869],{"class":3418,"line":3425},[3416,38870,3441],{"emptyLinePlaceholder":3440},[3416,38872,38873,38875,38878,38880,38883,38885,38888],{"class":3418,"line":3431},[3416,38874,36194],{"class":4368},[3416,38876,38877],{"class":6397}," TaskManager",[3416,38879,4043],{"class":3795},[3416,38881,38882],{"class":6397},"Api",[3416,38884,4043],{"class":3795},[3416,38886,38887],{"class":6397},"Models",[3416,38889,11594],{"class":3795},[3416,38891,38892],{"class":3418,"line":3437},[3416,38893,3441],{"emptyLinePlaceholder":3440},[3416,38895,38896,38898,38900,38902,38905],{"class":3418,"line":3444},[3416,38897,11789],{"class":3795},[3416,38899,33609],{"class":6397},[3416,38901,6423],{"class":3795},[3416,38903,38904],{"class":3808},"\"UserTasks\"",[3416,38906,33617],{"class":3795},[3416,38908,38909,38911,38913],{"class":3418,"line":3450},[3416,38910,31180],{"class":4368},[3416,38912,31183],{"class":4368},[3416,38914,38915],{"class":6397}," TaskItem\n",[3416,38917,38918],{"class":3418,"line":3456},[3416,38919,3796],{"class":3795},[3416,38921,38922,38924,38926,38928,38930,38932],{"class":3418,"line":3462},[3416,38923,9496],{"class":3795},[3416,38925,33637],{"class":6397},[3416,38927,6423],{"class":3795},[3416,38929,6482],{"class":3808},[3416,38931,33644],{"class":3795},[3416,38933,38934],{"class":3789},"\u002F\u002F Partition Key\n",[3416,38936,38937,38939,38941,38944,38946,38948,38950,38952,38954,38956,38958,38960],{"class":3418,"line":3468},[3416,38938,31235],{"class":4368},[3416,38940,31216],{"class":4368},[3416,38942,38943],{"class":6387}," UserId",[3416,38945,6492],{"class":3795},[3416,38947,33661],{"class":4368},[3416,38949,8900],{"class":3795},[3416,38951,33666],{"class":4368},[3416,38953,33669],{"class":3795},[3416,38955,6461],{"class":4368},[3416,38957,4043],{"class":3795},[3416,38959,33676],{"class":6387},[3416,38961,11594],{"class":3795},[3416,38963,38964],{"class":3418,"line":3474},[3416,38965,3441],{"emptyLinePlaceholder":3440},[3416,38967,38968,38970,38972,38974,38977,38979],{"class":3418,"line":3480},[3416,38969,9496],{"class":3795},[3416,38971,33689],{"class":6397},[3416,38973,6423],{"class":3795},[3416,38975,38976],{"class":3808},"\"TaskId\"",[3416,38978,33644],{"class":3795},[3416,38980,38981],{"class":3789},"\u002F\u002F Sort Key\n",[3416,38983,38984,38986,38988,38991,38993,38995,38997,38999,39001,39003,39005,39007],{"class":3418,"line":3486},[3416,38985,31235],{"class":4368},[3416,38987,31216],{"class":4368},[3416,38989,38990],{"class":6387}," TaskId",[3416,38992,6492],{"class":3795},[3416,38994,33661],{"class":4368},[3416,38996,8900],{"class":3795},[3416,38998,33666],{"class":4368},[3416,39000,33669],{"class":3795},[3416,39002,6461],{"class":4368},[3416,39004,4043],{"class":3795},[3416,39006,33676],{"class":6387},[3416,39008,11594],{"class":3795},[3416,39010,39011],{"class":3418,"line":3492},[3416,39012,3441],{"emptyLinePlaceholder":3440},[3416,39014,39015,39017,39019,39021,39023],{"class":3418,"line":3498},[3416,39016,9496],{"class":3795},[3416,39018,33736],{"class":6397},[3416,39020,6423],{"class":3795},[3416,39022,33741],{"class":3808},[3416,39024,33617],{"class":3795},[3416,39026,39027,39029,39031,39033,39035,39037,39039,39041,39043,39045,39047,39049],{"class":3418,"line":3504},[3416,39028,31235],{"class":4368},[3416,39030,31216],{"class":4368},[3416,39032,33752],{"class":6387},[3416,39034,6492],{"class":3795},[3416,39036,33661],{"class":4368},[3416,39038,8900],{"class":3795},[3416,39040,33666],{"class":4368},[3416,39042,33669],{"class":3795},[3416,39044,6461],{"class":4368},[3416,39046,4043],{"class":3795},[3416,39048,33676],{"class":6387},[3416,39050,11594],{"class":3795},[3416,39052,39053],{"class":3418,"line":3510},[3416,39054,3441],{"emptyLinePlaceholder":3440},[3416,39056,39057,39059,39061,39063,39066],{"class":3418,"line":3515},[3416,39058,9496],{"class":3795},[3416,39060,33736],{"class":6397},[3416,39062,6423],{"class":3795},[3416,39064,39065],{"class":3808},"\"Description\"",[3416,39067,33617],{"class":3795},[3416,39069,39070,39072,39074,39077,39079,39081,39083,39085,39087,39089,39091,39093],{"class":3418,"line":3521},[3416,39071,31235],{"class":4368},[3416,39073,31216],{"class":4368},[3416,39075,39076],{"class":6387}," Description",[3416,39078,6492],{"class":3795},[3416,39080,33661],{"class":4368},[3416,39082,8900],{"class":3795},[3416,39084,33666],{"class":4368},[3416,39086,33669],{"class":3795},[3416,39088,6461],{"class":4368},[3416,39090,4043],{"class":3795},[3416,39092,33676],{"class":6387},[3416,39094,11594],{"class":3795},[3416,39096,39097],{"class":3418,"line":3527},[3416,39098,3441],{"emptyLinePlaceholder":3440},[3416,39100,39101],{"class":3418,"line":3533},[3416,39102,39103],{"class":3789},"    \u002F\u002F HASH-ключ для GSI \"Status-index\"\n",[3416,39105,39106,39108,39110,39112,39115,39117,39119,39121,39123],{"class":3418,"line":3539},[3416,39107,9496],{"class":3795},[3416,39109,33823],{"class":6397},[3416,39111,6423],{"class":3795},[3416,39113,39114],{"class":3808},"\"Status-index\"",[3416,39116,4384],{"class":3795},[3416,39118,10857],{"class":6387},[3416,39120,6391],{"class":3795},[3416,39122,11860],{"class":3808},[3416,39124,33617],{"class":3795},[3416,39126,39127,39129,39131,39134,39136,39138,39140,39142,39144,39147],{"class":3418,"line":3545},[3416,39128,31235],{"class":4368},[3416,39130,31216],{"class":4368},[3416,39132,39133],{"class":6387}," Status",[3416,39135,6492],{"class":3795},[3416,39137,33661],{"class":4368},[3416,39139,8900],{"class":3795},[3416,39141,33666],{"class":4368},[3416,39143,33669],{"class":3795},[3416,39145,39146],{"class":3808},"\"TODO\"",[3416,39148,11594],{"class":3795},[3416,39150,39151],{"class":3418,"line":3551},[3416,39152,3441],{"emptyLinePlaceholder":3440},[3416,39154,39155,39157,39159,39161,39164],{"class":3418,"line":3557},[3416,39156,9496],{"class":3795},[3416,39158,33736],{"class":6397},[3416,39160,6423],{"class":3795},[3416,39162,39163],{"class":3808},"\"Priority\"",[3416,39165,33617],{"class":3795},[3416,39167,39168,39170,39172,39175,39177,39179,39181,39183,39185,39188],{"class":3418,"line":3563},[3416,39169,31235],{"class":4368},[3416,39171,31216],{"class":4368},[3416,39173,39174],{"class":6387}," Priority",[3416,39176,6492],{"class":3795},[3416,39178,33661],{"class":4368},[3416,39180,8900],{"class":3795},[3416,39182,33666],{"class":4368},[3416,39184,33669],{"class":3795},[3416,39186,39187],{"class":3808},"\"MEDIUM\"",[3416,39189,11594],{"class":3795},[3416,39191,39192],{"class":3418,"line":3569},[3416,39193,3441],{"emptyLinePlaceholder":3440},[3416,39195,39196,39198,39200,39202,39204],{"class":3418,"line":3574},[3416,39197,9496],{"class":3795},[3416,39199,33736],{"class":6397},[3416,39201,6423],{"class":3795},[3416,39203,6815],{"class":3808},[3416,39205,33617],{"class":3795},[3416,39207,39208,39210,39213,39216,39218,39220,39222,39224,39226,39228,39230,39232],{"class":3418,"line":3579},[3416,39209,31235],{"class":4368},[3416,39211,39212],{"class":6397}," DateTime",[3416,39214,39215],{"class":6387}," CreatedAt",[3416,39217,6492],{"class":3795},[3416,39219,33661],{"class":4368},[3416,39221,8900],{"class":3795},[3416,39223,33666],{"class":4368},[3416,39225,33669],{"class":3795},[3416,39227,11644],{"class":6387},[3416,39229,4043],{"class":3795},[3416,39231,28050],{"class":6387},[3416,39233,11594],{"class":3795},[3416,39235,39236],{"class":3418,"line":3584},[3416,39237,3441],{"emptyLinePlaceholder":3440},[3416,39239,39240],{"class":3418,"line":3590},[3416,39241,39242],{"class":3789},"    \u002F\u002F Оптимістичне блокування версії\n",[3416,39244,39245,39247,39249],{"class":3418,"line":3596},[3416,39246,9496],{"class":3795},[3416,39248,33882],{"class":6397},[3416,39250,18183],{"class":3795},[3416,39252,39253,39255,39257,39259,39261,39263,39265,39267,39269],{"class":3418,"line":3602},[3416,39254,31235],{"class":4368},[3416,39256,33891],{"class":4368},[3416,39258,33894],{"class":3795},[3416,39260,33897],{"class":6387},[3416,39262,6492],{"class":3795},[3416,39264,33661],{"class":4368},[3416,39266,8900],{"class":3795},[3416,39268,33666],{"class":4368},[3416,39270,33807],{"class":3795},[3416,39272,39273],{"class":3418,"line":3608},[3416,39274,3507],{"class":3795},[3720,39276],{},[3727,39278,39280],{"id":39279},"крок-3-налаштування-клієнта-dependency-injection-та-автоматична-ініціалізація-бази","Крок 3: Налаштування клієнта, Dependency Injection та автоматична ініціалізація бази",[3353,39282,39283,39284,39286,39287,39289,39290,39293],{},"Оскільки в локальному режимі таблиця ",[3413,39285,38299],{}," та глобальний індекс ",[3413,39288,38384],{}," не існують за замовчуванням, ми налаштуємо спеціальний ",[3413,39291,39292],{},"Database Initializer",", який перевірить наявність таблиці під час старту веб-сервісу і створить її у разі відсутності.",[38250,39295,39296,39300,39310,39433,39437,39443,40074,40078,40084],{},[3727,39297,39299],{"id":39298},"_1-налаштування-файлу-конфігурації","1. Налаштування файлу конфігурації",[3353,39301,39302,39303,39305,39306,39309],{},"Створіть або оновіть файл ",[3413,39304,30480],{},", додавши секцію ",[3413,39307,39308],{},"\"DynamoDb\""," з конфігурацією локального підключення:",[38843,39311,39312],{},[3406,39313,39315],{"className":3780,"code":39314,"filename":30480,"language":3782,"meta":3411,"style":3411},"{\n  \"Logging\": {\n    \"LogLevel\": {\n      \"Default\": \"Information\",\n      \"Microsoft.AspNetCore\": \"Warning\"\n    }\n  },\n  \"AllowedHosts\": \"*\",\n  \"AWS\": {\n    \"Region\": \"eu-central-1\"\n  },\n  \"DynamoDb\": {\n    \"LocalMode\": true,\n    \"LocalServiceUrl\": \"http:\u002F\u002Flocalhost:8000\"\n  }\n}\n",[3413,39316,39317,39321,39328,39335,39347,39357,39361,39366,39378,39384,39393,39397,39404,39415,39425,39429],{"__ignoreMap":3411},[3416,39318,39319],{"class":3418,"line":3419},[3416,39320,3796],{"class":3795},[3416,39322,39323,39326],{"class":3418,"line":3425},[3416,39324,39325],{"class":3801},"  \"Logging\"",[3416,39327,4403],{"class":3795},[3416,39329,39330,39333],{"class":3418,"line":3431},[3416,39331,39332],{"class":3801},"    \"LogLevel\"",[3416,39334,4403],{"class":3795},[3416,39336,39337,39340,39342,39345],{"class":3418,"line":3437},[3416,39338,39339],{"class":3801},"      \"Default\"",[3416,39341,3805],{"class":3795},[3416,39343,39344],{"class":3808},"\"Information\"",[3416,39346,3812],{"class":3795},[3416,39348,39349,39352,39354],{"class":3418,"line":3444},[3416,39350,39351],{"class":3801},"      \"Microsoft.AspNetCore\"",[3416,39353,3805],{"class":3795},[3416,39355,39356],{"class":3808},"\"Warning\"\n",[3416,39358,39359],{"class":3418,"line":3450},[3416,39360,4167],{"class":3795},[3416,39362,39363],{"class":3418,"line":3456},[3416,39364,39365],{"class":3795},"  },\n",[3416,39367,39368,39371,39373,39376],{"class":3418,"line":3462},[3416,39369,39370],{"class":3801},"  \"AllowedHosts\"",[3416,39372,3805],{"class":3795},[3416,39374,39375],{"class":3808},"\"*\"",[3416,39377,3812],{"class":3795},[3416,39379,39380,39382],{"class":3418,"line":3468},[3416,39381,30501],{"class":3801},[3416,39383,4403],{"class":3795},[3416,39385,39386,39388,39390],{"class":3418,"line":3474},[3416,39387,30508],{"class":3801},[3416,39389,3805],{"class":3795},[3416,39391,39392],{"class":3808},"\"eu-central-1\"\n",[3416,39394,39395],{"class":3418,"line":3480},[3416,39396,39365],{"class":3795},[3416,39398,39399,39402],{"class":3418,"line":3486},[3416,39400,39401],{"class":3801},"  \"DynamoDb\"",[3416,39403,4403],{"class":3795},[3416,39405,39406,39409,39411,39413],{"class":3418,"line":3492},[3416,39407,39408],{"class":3801},"    \"LocalMode\"",[3416,39410,3805],{"class":3795},[3416,39412,4038],{"class":4368},[3416,39414,3812],{"class":3795},[3416,39416,39417,39420,39422],{"class":3418,"line":3498},[3416,39418,39419],{"class":3801},"    \"LocalServiceUrl\"",[3416,39421,3805],{"class":3795},[3416,39423,39424],{"class":3808},"\"http:\u002F\u002Flocalhost:8000\"\n",[3416,39426,39427],{"class":3418,"line":3504},[3416,39428,30530],{"class":3795},[3416,39430,39431],{"class":3418,"line":3510},[3416,39432,3507],{"class":3795},[3727,39434,39436],{"id":39435},"_2-реалізація-dynamodbinitializer","2. Реалізація DynamoDbInitializer",[3353,39438,39439,39440,39442],{},"Створимо інфраструктурний клас, який за допомогою низькорівневого API (",[3413,39441,30705],{},") автоматично конструює схему таблиці:",[38843,39444,39445],{},[3406,39446,39449],{"className":6375,"code":39447,"filename":39448,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.Model;\n\nnamespace TaskManager.Api.Infrastructure;\n\npublic class DynamoDbInitializer\n{\n    private readonly IAmazonDynamoDB _client;\n    private const string TableName = \"UserTasks\";\n\n    public DynamoDbInitializer(IAmazonDynamoDB client) => _client = client;\n\n    public async Task InitializeAsync()\n    {\n        \u002F\u002F Перевіряємо список існуючих таблиць\n        var tables = await _client.ListTablesAsync();\n        if (tables.TableNames.Contains(TableName))\n        {\n            return; \u002F\u002F Таблиця вже існує\n        }\n\n        var request = new CreateTableRequest\n        {\n            TableName = TableName,\n            BillingMode = BillingMode.PAY_PER_REQUEST,\n            \u002F\u002F Специфікація типів атрибутів, які використовуються як ключі (HASH\u002FRANGE)\n            AttributeDefinitions = new List\u003CAttributeDefinition>\n            {\n                new() { AttributeName = \"UserId\", AttributeType = ScalarAttributeType.S },\n                new() { AttributeName = \"TaskId\", AttributeType = ScalarAttributeType.S },\n                new() { AttributeName = \"Status\", AttributeType = ScalarAttributeType.S }\n            },\n            \u002F\u002F Головні ключі таблиці\n            KeySchema = new List\u003CKeySchemaElement>\n            {\n                new() { AttributeName = \"UserId\", KeyType = KeyType.HASH },  \u002F\u002F Partition Key\n                new() { AttributeName = \"TaskId\", KeyType = KeyType.RANGE }  \u002F\u002F Sort Key\n            },\n            \u002F\u002F Опис Global Secondary Index (GSI)\n            GlobalSecondaryIndexes = new List\u003CGlobalSecondaryIndex>\n            {\n                new()\n                {\n                    IndexName = \"Status-index\",\n                    KeySchema = new List\u003CKeySchemaElement>\n                    {\n                        new() { AttributeName = \"Status\", KeyType = KeyType.HASH }\n                    },\n                    Projection = new Projection\n                    {\n                        ProjectionType = ProjectionType.ALL \u002F\u002F Проектуємо всі атрибути у індекс\n                    }\n                }\n            }\n        };\n\n        await _client.CreateTableAsync(request);\n    }\n}\n","Infrastructure\u002FDynamoDbInitializer.cs",[3413,39450,39451,39463,39479,39483,39500,39504,39513,39517,39529,39545,39549,39572,39576,39589,39593,39598,39618,39643,39647,39656,39660,39664,39676,39680,39690,39705,39710,39727,39731,39757,39783,39809,39813,39818,39834,39838,39867,39896,39900,39905,39922,39926,39932,39936,39947,39964,39968,39995,39999,40010,40014,40030,40034,40038,40042,40046,40050,40066,40070],{"__ignoreMap":3411},[3416,39452,39453,39455,39457,39459,39461],{"class":3418,"line":3419},[3416,39454,17433],{"class":11427},[3416,39456,17436],{"class":6397},[3416,39458,4043],{"class":3795},[3416,39460,17441],{"class":6397},[3416,39462,11594],{"class":3795},[3416,39464,39465,39467,39469,39471,39473,39475,39477],{"class":3418,"line":3425},[3416,39466,17433],{"class":11427},[3416,39468,17436],{"class":6397},[3416,39470,4043],{"class":3795},[3416,39472,17441],{"class":6397},[3416,39474,4043],{"class":3795},[3416,39476,17458],{"class":6397},[3416,39478,11594],{"class":3795},[3416,39480,39481],{"class":3418,"line":3431},[3416,39482,3441],{"emptyLinePlaceholder":3440},[3416,39484,39485,39487,39489,39491,39493,39495,39498],{"class":3418,"line":3437},[3416,39486,36194],{"class":4368},[3416,39488,38877],{"class":6397},[3416,39490,4043],{"class":3795},[3416,39492,38882],{"class":6397},[3416,39494,4043],{"class":3795},[3416,39496,39497],{"class":6397},"Infrastructure",[3416,39499,11594],{"class":3795},[3416,39501,39502],{"class":3418,"line":3444},[3416,39503,3441],{"emptyLinePlaceholder":3440},[3416,39505,39506,39508,39510],{"class":3418,"line":3450},[3416,39507,31180],{"class":4368},[3416,39509,31183],{"class":4368},[3416,39511,39512],{"class":6397}," DynamoDbInitializer\n",[3416,39514,39515],{"class":3418,"line":3456},[3416,39516,3796],{"class":3795},[3416,39518,39519,39521,39523,39525,39527],{"class":3418,"line":3462},[3416,39520,31195],{"class":4368},[3416,39522,31198],{"class":4368},[3416,39524,31201],{"class":6397},[3416,39526,31204],{"class":6387},[3416,39528,11594],{"class":3795},[3416,39530,39531,39533,39535,39537,39539,39541,39543],{"class":3418,"line":3468},[3416,39532,31195],{"class":4368},[3416,39534,31213],{"class":4368},[3416,39536,31216],{"class":4368},[3416,39538,31219],{"class":6387},[3416,39540,6391],{"class":3795},[3416,39542,38904],{"class":3808},[3416,39544,11594],{"class":3795},[3416,39546,39547],{"class":3418,"line":3474},[3416,39548,3441],{"emptyLinePlaceholder":3440},[3416,39550,39551,39553,39556,39558,39560,39562,39564,39566,39568,39570],{"class":3418,"line":3480},[3416,39552,31235],{"class":4368},[3416,39554,39555],{"class":6330}," DynamoDbInitializer",[3416,39557,6423],{"class":3795},[3416,39559,30705],{"class":6397},[3416,39561,6388],{"class":6387},[3416,39563,31247],{"class":3795},[3416,39565,31250],{"class":6387},[3416,39567,6391],{"class":3795},[3416,39569,31255],{"class":6387},[3416,39571,11594],{"class":3795},[3416,39573,39574],{"class":3418,"line":3486},[3416,39575,3441],{"emptyLinePlaceholder":3440},[3416,39577,39578,39580,39582,39584,39587],{"class":3418,"line":3492},[3416,39579,31235],{"class":4368},[3416,39581,31273],{"class":4368},[3416,39583,11606],{"class":6397},[3416,39585,39586],{"class":6330}," InitializeAsync",[3416,39588,17625],{"class":3795},[3416,39590,39591],{"class":3418,"line":3498},[3416,39592,6474],{"class":3795},[3416,39594,39595],{"class":3418,"line":3504},[3416,39596,39597],{"class":3789},"        \u002F\u002F Перевіряємо список існуючих таблиць\n",[3416,39599,39600,39602,39605,39607,39609,39611,39613,39616],{"class":3418,"line":3510},[3416,39601,30853],{"class":4368},[3416,39603,39604],{"class":6387}," tables",[3416,39606,6391],{"class":3795},[3416,39608,6413],{"class":4368},[3416,39610,31204],{"class":6387},[3416,39612,4043],{"class":3795},[3416,39614,39615],{"class":6330},"ListTablesAsync",[3416,39617,6401],{"class":3795},[3416,39619,39620,39622,39624,39627,39629,39632,39634,39637,39639,39641],{"class":3418,"line":3515},[3416,39621,34208],{"class":11427},[3416,39623,11431],{"class":3795},[3416,39625,39626],{"class":6387},"tables",[3416,39628,4043],{"class":3795},[3416,39630,39631],{"class":6387},"TableNames",[3416,39633,4043],{"class":3795},[3416,39635,39636],{"class":6330},"Contains",[3416,39638,6423],{"class":3795},[3416,39640,31339],{"class":6387},[3416,39642,36639],{"class":3795},[3416,39644,39645],{"class":3418,"line":3521},[3416,39646,8611],{"class":3795},[3416,39648,39649,39651,39653],{"class":3418,"line":3527},[3416,39650,34231],{"class":11427},[3416,39652,8900],{"class":3795},[3416,39654,39655],{"class":3789},"\u002F\u002F Таблиця вже існує\n",[3416,39657,39658],{"class":3418,"line":3533},[3416,39659,8533],{"class":3795},[3416,39661,39662],{"class":3418,"line":3539},[3416,39663,3441],{"emptyLinePlaceholder":3440},[3416,39665,39666,39668,39670,39672,39674],{"class":3418,"line":3545},[3416,39667,30853],{"class":4368},[3416,39669,31320],{"class":6387},[3416,39671,6391],{"class":3795},[3416,39673,6394],{"class":4368},[3416,39675,10809],{"class":6397},[3416,39677,39678],{"class":3418,"line":3551},[3416,39679,8611],{"class":3795},[3416,39681,39682,39684,39686,39688],{"class":3418,"line":3557},[3416,39683,10247],{"class":6387},[3416,39685,6391],{"class":3795},[3416,39687,31339],{"class":6387},[3416,39689,3812],{"class":3795},[3416,39691,39692,39695,39697,39699,39701,39703],{"class":3418,"line":3563},[3416,39693,39694],{"class":6387},"            BillingMode",[3416,39696,6391],{"class":3795},[3416,39698,11005],{"class":6387},[3416,39700,4043],{"class":3795},[3416,39702,29452],{"class":6387},[3416,39704,3812],{"class":3795},[3416,39706,39707],{"class":3418,"line":3569},[3416,39708,39709],{"class":3789},"            \u002F\u002F Специфікація типів атрибутів, які використовуються як ключі (HASH\u002FRANGE)\n",[3416,39711,39712,39715,39717,39719,39721,39723,39725],{"class":3418,"line":3574},[3416,39713,39714],{"class":6387},"            AttributeDefinitions",[3416,39716,6391],{"class":3795},[3416,39718,6394],{"class":4368},[3416,39720,8640],{"class":6397},[3416,39722,5861],{"class":3795},[3416,39724,10839],{"class":6397},[3416,39726,6469],{"class":3795},[3416,39728,39729],{"class":3418,"line":3579},[3416,39730,8628],{"class":3795},[3416,39732,39733,39735,39737,39739,39741,39743,39745,39747,39749,39751,39753,39755],{"class":3418,"line":3584},[3416,39734,9213],{"class":4368},[3416,39736,17546],{"class":3795},[3416,39738,10857],{"class":6387},[3416,39740,6391],{"class":3795},[3416,39742,6482],{"class":3808},[3416,39744,4384],{"class":3795},[3416,39746,10866],{"class":6387},[3416,39748,6391],{"class":3795},[3416,39750,10871],{"class":6387},[3416,39752,4043],{"class":3795},[3416,39754,6495],{"class":6387},[3416,39756,8915],{"class":3795},[3416,39758,39759,39761,39763,39765,39767,39769,39771,39773,39775,39777,39779,39781],{"class":3418,"line":3590},[3416,39760,9213],{"class":4368},[3416,39762,17546],{"class":3795},[3416,39764,10857],{"class":6387},[3416,39766,6391],{"class":3795},[3416,39768,38976],{"class":3808},[3416,39770,4384],{"class":3795},[3416,39772,10866],{"class":6387},[3416,39774,6391],{"class":3795},[3416,39776,10871],{"class":6387},[3416,39778,4043],{"class":3795},[3416,39780,6495],{"class":6387},[3416,39782,8915],{"class":3795},[3416,39784,39785,39787,39789,39791,39793,39795,39797,39799,39801,39803,39805,39807],{"class":3418,"line":3596},[3416,39786,9213],{"class":4368},[3416,39788,17546],{"class":3795},[3416,39790,10857],{"class":6387},[3416,39792,6391],{"class":3795},[3416,39794,11860],{"class":3808},[3416,39796,4384],{"class":3795},[3416,39798,10866],{"class":6387},[3416,39800,6391],{"class":3795},[3416,39802,10871],{"class":6387},[3416,39804,4043],{"class":3795},[3416,39806,6495],{"class":6387},[3416,39808,8948],{"class":3795},[3416,39810,39811],{"class":3418,"line":3602},[3416,39812,9066],{"class":3795},[3416,39814,39815],{"class":3418,"line":3608},[3416,39816,39817],{"class":3789},"            \u002F\u002F Головні ключі таблиці\n",[3416,39819,39820,39822,39824,39826,39828,39830,39832],{"class":3418,"line":3614},[3416,39821,15695],{"class":6387},[3416,39823,6391],{"class":3795},[3416,39825,6394],{"class":4368},[3416,39827,8640],{"class":6397},[3416,39829,5861],{"class":3795},[3416,39831,10925],{"class":6397},[3416,39833,6469],{"class":3795},[3416,39835,39836],{"class":3418,"line":3620},[3416,39837,8628],{"class":3795},[3416,39839,39840,39842,39844,39846,39848,39850,39852,39854,39856,39858,39860,39862,39865],{"class":3418,"line":3626},[3416,39841,9213],{"class":4368},[3416,39843,17546],{"class":3795},[3416,39845,10857],{"class":6387},[3416,39847,6391],{"class":3795},[3416,39849,6482],{"class":3808},[3416,39851,4384],{"class":3795},[3416,39853,10951],{"class":6387},[3416,39855,6391],{"class":3795},[3416,39857,10951],{"class":6387},[3416,39859,4043],{"class":3795},[3416,39861,10960],{"class":6387},[3416,39863,39864],{"class":3795}," },  ",[3416,39866,38934],{"class":3789},[3416,39868,39869,39871,39873,39875,39877,39879,39881,39883,39885,39887,39889,39891,39894],{"class":3418,"line":3631},[3416,39870,9213],{"class":4368},[3416,39872,17546],{"class":3795},[3416,39874,10857],{"class":6387},[3416,39876,6391],{"class":3795},[3416,39878,38976],{"class":3808},[3416,39880,4384],{"class":3795},[3416,39882,10951],{"class":6387},[3416,39884,6391],{"class":3795},[3416,39886,10951],{"class":6387},[3416,39888,4043],{"class":3795},[3416,39890,10989],{"class":6387},[3416,39892,39893],{"class":3795}," }  ",[3416,39895,38981],{"class":3789},[3416,39897,39898],{"class":3418,"line":3636},[3416,39899,9066],{"class":3795},[3416,39901,39902],{"class":3418,"line":3641},[3416,39903,39904],{"class":3789},"            \u002F\u002F Опис Global Secondary Index (GSI)\n",[3416,39906,39907,39910,39912,39914,39916,39918,39920],{"class":3418,"line":3647},[3416,39908,39909],{"class":6387},"            GlobalSecondaryIndexes",[3416,39911,6391],{"class":3795},[3416,39913,6394],{"class":4368},[3416,39915,8640],{"class":6397},[3416,39917,5861],{"class":3795},[3416,39919,20011],{"class":6397},[3416,39921,6469],{"class":3795},[3416,39923,39924],{"class":3418,"line":3653},[3416,39925,8628],{"class":3795},[3416,39927,39928,39930],{"class":3418,"line":3659},[3416,39929,9213],{"class":4368},[3416,39931,17625],{"class":3795},[3416,39933,39934],{"class":3418,"line":3665},[3416,39935,8661],{"class":3795},[3416,39937,39938,39941,39943,39945],{"class":3418,"line":3671},[3416,39939,39940],{"class":6387},"                    IndexName",[3416,39942,6391],{"class":3795},[3416,39944,39114],{"class":3808},[3416,39946,3812],{"class":3795},[3416,39948,39949,39952,39954,39956,39958,39960,39962],{"class":3418,"line":3677},[3416,39950,39951],{"class":6387},"                    KeySchema",[3416,39953,6391],{"class":3795},[3416,39955,6394],{"class":4368},[3416,39957,8640],{"class":6397},[3416,39959,5861],{"class":3795},[3416,39961,10925],{"class":6397},[3416,39963,6469],{"class":3795},[3416,39965,39966],{"class":3418,"line":3683},[3416,39967,8683],{"class":3795},[3416,39969,39970,39973,39975,39977,39979,39981,39983,39985,39987,39989,39991,39993],{"class":3418,"line":3688},[3416,39971,39972],{"class":4368},"                        new",[3416,39974,17546],{"class":3795},[3416,39976,10857],{"class":6387},[3416,39978,6391],{"class":3795},[3416,39980,11860],{"class":3808},[3416,39982,4384],{"class":3795},[3416,39984,10951],{"class":6387},[3416,39986,6391],{"class":3795},[3416,39988,10951],{"class":6387},[3416,39990,4043],{"class":3795},[3416,39992,10960],{"class":6387},[3416,39994,8948],{"class":3795},[3416,39996,39997],{"class":3418,"line":3693},[3416,39998,8734],{"class":3795},[3416,40000,40001,40004,40006,40008],{"class":3418,"line":3698},[3416,40002,40003],{"class":6387},"                    Projection",[3416,40005,6391],{"class":3795},[3416,40007,6394],{"class":4368},[3416,40009,15783],{"class":6397},[3416,40011,40012],{"class":3418,"line":3704},[3416,40013,8683],{"class":3795},[3416,40015,40016,40019,40021,40023,40025,40027],{"class":3418,"line":3710},[3416,40017,40018],{"class":6387},"                        ProjectionType",[3416,40020,6391],{"class":3795},[3416,40022,15797],{"class":6387},[3416,40024,4043],{"class":3795},[3416,40026,15103],{"class":6387},[3416,40028,40029],{"class":3789}," \u002F\u002F Проектуємо всі атрибути у індекс\n",[3416,40031,40032],{"class":3418,"line":3715},[3416,40033,8805],{"class":3795},[3416,40035,40036],{"class":3418,"line":12799},[3416,40037,8810],{"class":3795},[3416,40039,40040],{"class":3418,"line":12822},[3416,40041,8815],{"class":3795},[3416,40043,40044],{"class":3418,"line":12827},[3416,40045,30897],{"class":3795},[3416,40047,40048],{"class":3418,"line":12832},[3416,40049,3441],{"emptyLinePlaceholder":3440},[3416,40051,40052,40054,40056,40058,40060,40062,40064],{"class":3418,"line":12837},[3416,40053,31512],{"class":4368},[3416,40055,31204],{"class":6387},[3416,40057,4043],{"class":3795},[3416,40059,10802],{"class":6330},[3416,40061,6423],{"class":3795},[3416,40063,31523],{"class":6387},[3416,40065,11465],{"class":3795},[3416,40067,40068],{"class":3418,"line":12843},[3416,40069,4167],{"class":3795},[3416,40071,40072],{"class":3418,"line":12860},[3416,40073,3507],{"class":3795},[3727,40075,40077],{"id":40076},"_3-реєстрація-di-та-запуск-ініціалізатора-при-старті","3. Реєстрація DI та запуск ініціалізатора при старті",[3353,40079,40080,40081,40083],{},"Оновимо файл ",[3413,40082,30562],{},", зареєструвавши клієнт SDK (з урахуванням режиму Local\u002FAWS), ORM контекст та репозиторії:",[38843,40085,40086],{},[3406,40087,40089],{"className":6375,"code":40088,"filename":30562,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2;\nusing Amazon.DynamoDBv2.DataModel;\nusing TaskManager.Api.Infrastructure;\nusing TaskManager.Api.Repositories;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n\u002F\u002F Зчитування конфігурації підключення\nvar dynamoConfig = builder.Configuration.GetSection(\"DynamoDb\");\nvar localMode = dynamoConfig.GetValue\u003Cbool>(\"LocalMode\");\n\nif (localMode)\n{\n    \u002F\u002F Налаштування для локального тестування (LocalStack \u002F DynamoDB Local)\n    builder.Services.AddSingleton\u003CIAmazonDynamoDB>(sp =>\n    {\n        var serviceUrl = dynamoConfig.GetValue\u003Cstring>(\"LocalServiceUrl\");\n        var clientConfig = new AmazonDynamoDBConfig\n        {\n            ServiceURL = serviceUrl,\n            UseHttp = true\n        };\n        return new AmazonDynamoDBClient(clientConfig);\n    });\n}\nelse\n{\n    \u002F\u002F Налаштування підключення до реальної хмари AWS\n    builder.Services.AddDefaultAWSOptions(builder.Configuration.GetAWSOptions());\n    builder.Services.AddAWSService\u003CIAmazonDynamoDB>();\n}\n\n\u002F\u002F Реєстрація ORM-контексту та сервісів\nbuilder.Services.AddScoped\u003CIDynamoDBContext, DynamoDBContext>();\nbuilder.Services.AddTransient\u003CDynamoDbInitializer>();\nbuilder.Services.AddScoped\u003CITaskRepository, DynamoDBTaskRepository>();\n\nvar app = builder.Build();\n\n\u002F\u002F Автоматична ініціалізація бази під час запуску (лише для локальної розробки)\nif (localMode)\n{\n    using var scope = app.Services.CreateScope();\n    var initializer = scope.ServiceProvider.GetRequiredService\u003CDynamoDbInitializer>();\n    await initializer.InitializeAsync();\n}\n\napp.MapGet(\"\u002F\", () => \"Task Manager API is running!\");\n\n\u002F\u002F Наші ендпоінти будуть додані у Кроці 5...\n\napp.Run();\n",[3413,40090,40091,40103,40119,40135,40152,40156,40176,40180,40185,40211,40239,40243,40254,40258,40263,40285,40289,40315,40328,40332,40343,40351,40355,40370,40374,40378,40383,40387,40392,40419,40437,40441,40445,40450,40472,40492,40516,40520,40538,40542,40547,40557,40561,40587,40615,40628,40632,40636,40658,40662,40667,40671],{"__ignoreMap":3411},[3416,40092,40093,40095,40097,40099,40101],{"class":3418,"line":3419},[3416,40094,17433],{"class":11427},[3416,40096,17436],{"class":6397},[3416,40098,4043],{"class":3795},[3416,40100,17441],{"class":6397},[3416,40102,11594],{"class":3795},[3416,40104,40105,40107,40109,40111,40113,40115,40117],{"class":3418,"line":3425},[3416,40106,17433],{"class":11427},[3416,40108,17436],{"class":6397},[3416,40110,4043],{"class":3795},[3416,40112,17441],{"class":6397},[3416,40114,4043],{"class":3795},[3416,40116,30594],{"class":6397},[3416,40118,11594],{"class":3795},[3416,40120,40121,40123,40125,40127,40129,40131,40133],{"class":3418,"line":3431},[3416,40122,17433],{"class":11427},[3416,40124,38877],{"class":6397},[3416,40126,4043],{"class":3795},[3416,40128,38882],{"class":6397},[3416,40130,4043],{"class":3795},[3416,40132,39497],{"class":6397},[3416,40134,11594],{"class":3795},[3416,40136,40137,40139,40141,40143,40145,40147,40150],{"class":3418,"line":3437},[3416,40138,17433],{"class":11427},[3416,40140,38877],{"class":6397},[3416,40142,4043],{"class":3795},[3416,40144,38882],{"class":6397},[3416,40146,4043],{"class":3795},[3416,40148,40149],{"class":6397},"Repositories",[3416,40151,11594],{"class":3795},[3416,40153,40154],{"class":3418,"line":3444},[3416,40155,3441],{"emptyLinePlaceholder":3440},[3416,40157,40158,40160,40162,40164,40166,40168,40170,40172,40174],{"class":3418,"line":3450},[3416,40159,6384],{"class":4368},[3416,40161,30607],{"class":6387},[3416,40163,6391],{"class":3795},[3416,40165,30612],{"class":6387},[3416,40167,4043],{"class":3795},[3416,40169,30617],{"class":6330},[3416,40171,6423],{"class":3795},[3416,40173,30622],{"class":6387},[3416,40175,11465],{"class":3795},[3416,40177,40178],{"class":3418,"line":3456},[3416,40179,3441],{"emptyLinePlaceholder":3440},[3416,40181,40182],{"class":3418,"line":3462},[3416,40183,40184],{"class":3789},"\u002F\u002F Зчитування конфігурації підключення\n",[3416,40186,40187,40189,40192,40194,40196,40198,40200,40202,40205,40207,40209],{"class":3418,"line":3468},[3416,40188,6384],{"class":4368},[3416,40190,40191],{"class":6387}," dynamoConfig",[3416,40193,6391],{"class":3795},[3416,40195,30645],{"class":6387},[3416,40197,4043],{"class":3795},[3416,40199,30650],{"class":6387},[3416,40201,4043],{"class":3795},[3416,40203,40204],{"class":6330},"GetSection",[3416,40206,6423],{"class":3795},[3416,40208,39308],{"class":3808},[3416,40210,11465],{"class":3795},[3416,40212,40213,40215,40218,40220,40223,40225,40228,40230,40232,40234,40237],{"class":3418,"line":3474},[3416,40214,6384],{"class":4368},[3416,40216,40217],{"class":6387}," localMode",[3416,40219,6391],{"class":3795},[3416,40221,40222],{"class":6387},"dynamoConfig",[3416,40224,4043],{"class":3795},[3416,40226,40227],{"class":6330},"GetValue",[3416,40229,5861],{"class":3795},[3416,40231,30958],{"class":4368},[3416,40233,30838],{"class":3795},[3416,40235,40236],{"class":3808},"\"LocalMode\"",[3416,40238,11465],{"class":3795},[3416,40240,40241],{"class":3418,"line":3480},[3416,40242,3441],{"emptyLinePlaceholder":3440},[3416,40244,40245,40247,40249,40252],{"class":3418,"line":3486},[3416,40246,30796],{"class":11427},[3416,40248,11431],{"class":3795},[3416,40250,40251],{"class":6387},"localMode",[3416,40253,9656],{"class":3795},[3416,40255,40256],{"class":3418,"line":3492},[3416,40257,3796],{"class":3795},[3416,40259,40260],{"class":3418,"line":3498},[3416,40261,40262],{"class":3789},"    \u002F\u002F Налаштування для локального тестування (LocalStack \u002F DynamoDB Local)\n",[3416,40264,40265,40267,40269,40271,40273,40275,40277,40279,40281,40283],{"class":3418,"line":3504},[3416,40266,30822],{"class":6387},[3416,40268,4043],{"class":3795},[3416,40270,30666],{"class":6387},[3416,40272,4043],{"class":3795},[3416,40274,30831],{"class":6330},[3416,40276,5861],{"class":3795},[3416,40278,30705],{"class":6397},[3416,40280,30838],{"class":3795},[3416,40282,30841],{"class":6387},[3416,40284,30844],{"class":3795},[3416,40286,40287],{"class":3418,"line":3510},[3416,40288,6474],{"class":3795},[3416,40290,40291,40293,40296,40298,40300,40302,40304,40306,40308,40310,40313],{"class":3418,"line":3515},[3416,40292,30853],{"class":4368},[3416,40294,40295],{"class":6387}," serviceUrl",[3416,40297,6391],{"class":3795},[3416,40299,40222],{"class":6387},[3416,40301,4043],{"class":3795},[3416,40303,40227],{"class":6330},[3416,40305,5861],{"class":3795},[3416,40307,6461],{"class":4368},[3416,40309,30838],{"class":3795},[3416,40311,40312],{"class":3808},"\"LocalServiceUrl\"",[3416,40314,11465],{"class":3795},[3416,40316,40317,40319,40322,40324,40326],{"class":3418,"line":3521},[3416,40318,30853],{"class":4368},[3416,40320,40321],{"class":6387}," clientConfig",[3416,40323,6391],{"class":3795},[3416,40325,6394],{"class":4368},[3416,40327,30863],{"class":6397},[3416,40329,40330],{"class":3418,"line":3527},[3416,40331,8611],{"class":3795},[3416,40333,40334,40336,40338,40341],{"class":3418,"line":3533},[3416,40335,30872],{"class":6387},[3416,40337,6391],{"class":3795},[3416,40339,40340],{"class":6387},"serviceUrl",[3416,40342,3812],{"class":3795},[3416,40344,40345,40347,40349],{"class":3418,"line":3539},[3416,40346,30887],{"class":6387},[3416,40348,6391],{"class":3795},[3416,40350,30892],{"class":4368},[3416,40352,40353],{"class":3418,"line":3545},[3416,40354,30897],{"class":3795},[3416,40356,40357,40359,40361,40363,40365,40368],{"class":3418,"line":3551},[3416,40358,30902],{"class":11427},[3416,40360,30905],{"class":4368},[3416,40362,6398],{"class":6397},[3416,40364,6423],{"class":3795},[3416,40366,40367],{"class":6387},"clientConfig",[3416,40369,11465],{"class":3795},[3416,40371,40372],{"class":3418,"line":3557},[3416,40373,30919],{"class":3795},[3416,40375,40376],{"class":3418,"line":3563},[3416,40377,3507],{"class":3795},[3416,40379,40380],{"class":3418,"line":3569},[3416,40381,40382],{"class":11427},"else\n",[3416,40384,40385],{"class":3418,"line":3574},[3416,40386,3796],{"class":3795},[3416,40388,40389],{"class":3418,"line":3579},[3416,40390,40391],{"class":3789},"    \u002F\u002F Налаштування підключення до реальної хмари AWS\n",[3416,40393,40394,40396,40398,40400,40402,40404,40406,40408,40410,40412,40414,40416],{"class":3418,"line":3584},[3416,40395,30822],{"class":6387},[3416,40397,4043],{"class":3795},[3416,40399,30666],{"class":6387},[3416,40401,4043],{"class":3795},[3416,40403,30671],{"class":6330},[3416,40405,6423],{"class":3795},[3416,40407,30645],{"class":6387},[3416,40409,4043],{"class":3795},[3416,40411,30650],{"class":6387},[3416,40413,4043],{"class":3795},[3416,40415,30655],{"class":6330},[3416,40417,40418],{"class":3795},"());\n",[3416,40420,40421,40423,40425,40427,40429,40431,40433,40435],{"class":3418,"line":3590},[3416,40422,30822],{"class":6387},[3416,40424,4043],{"class":3795},[3416,40426,30666],{"class":6387},[3416,40428,4043],{"class":3795},[3416,40430,30700],{"class":6330},[3416,40432,5861],{"class":3795},[3416,40434,30705],{"class":6397},[3416,40436,30708],{"class":3795},[3416,40438,40439],{"class":3418,"line":3596},[3416,40440,3507],{"class":3795},[3416,40442,40443],{"class":3418,"line":3602},[3416,40444,3441],{"emptyLinePlaceholder":3440},[3416,40446,40447],{"class":3418,"line":3608},[3416,40448,40449],{"class":3789},"\u002F\u002F Реєстрація ORM-контексту та сервісів\n",[3416,40451,40452,40454,40456,40458,40460,40462,40464,40466,40468,40470],{"class":3418,"line":3614},[3416,40453,30645],{"class":6387},[3416,40455,4043],{"class":3795},[3416,40457,30666],{"class":6387},[3416,40459,4043],{"class":3795},[3416,40461,30730],{"class":6330},[3416,40463,5861],{"class":3795},[3416,40465,30735],{"class":6397},[3416,40467,4384],{"class":3795},[3416,40469,30279],{"class":6397},[3416,40471,30708],{"class":3795},[3416,40473,40474,40476,40478,40480,40482,40485,40487,40490],{"class":3418,"line":3620},[3416,40475,30645],{"class":6387},[3416,40477,4043],{"class":3795},[3416,40479,30666],{"class":6387},[3416,40481,4043],{"class":3795},[3416,40483,40484],{"class":6330},"AddTransient",[3416,40486,5861],{"class":3795},[3416,40488,40489],{"class":6397},"DynamoDbInitializer",[3416,40491,30708],{"class":3795},[3416,40493,40494,40496,40498,40500,40502,40504,40506,40509,40511,40514],{"class":3418,"line":3626},[3416,40495,30645],{"class":6387},[3416,40497,4043],{"class":3795},[3416,40499,30666],{"class":6387},[3416,40501,4043],{"class":3795},[3416,40503,30730],{"class":6330},[3416,40505,5861],{"class":3795},[3416,40507,40508],{"class":6397},"ITaskRepository",[3416,40510,4384],{"class":3795},[3416,40512,40513],{"class":6397},"DynamoDBTaskRepository",[3416,40515,30708],{"class":3795},[3416,40517,40518],{"class":3418,"line":3631},[3416,40519,3441],{"emptyLinePlaceholder":3440},[3416,40521,40522,40524,40527,40529,40531,40533,40536],{"class":3418,"line":3636},[3416,40523,6384],{"class":4368},[3416,40525,40526],{"class":6387}," app",[3416,40528,6391],{"class":3795},[3416,40530,30645],{"class":6387},[3416,40532,4043],{"class":3795},[3416,40534,40535],{"class":6330},"Build",[3416,40537,6401],{"class":3795},[3416,40539,40540],{"class":3418,"line":3641},[3416,40541,3441],{"emptyLinePlaceholder":3440},[3416,40543,40544],{"class":3418,"line":3647},[3416,40545,40546],{"class":3789},"\u002F\u002F Автоматична ініціалізація бази під час запуску (лише для локальної розробки)\n",[3416,40548,40549,40551,40553,40555],{"class":3418,"line":3653},[3416,40550,30796],{"class":11427},[3416,40552,11431],{"class":3795},[3416,40554,40251],{"class":6387},[3416,40556,9656],{"class":3795},[3416,40558,40559],{"class":3418,"line":3659},[3416,40560,3796],{"class":3795},[3416,40562,40563,40566,40568,40571,40573,40576,40578,40580,40582,40585],{"class":3418,"line":3665},[3416,40564,40565],{"class":11427},"    using",[3416,40567,36608],{"class":4368},[3416,40569,40570],{"class":6387}," scope",[3416,40572,6391],{"class":3795},[3416,40574,40575],{"class":6387},"app",[3416,40577,4043],{"class":3795},[3416,40579,30666],{"class":6387},[3416,40581,4043],{"class":3795},[3416,40583,40584],{"class":6330},"CreateScope",[3416,40586,6401],{"class":3795},[3416,40588,40589,40591,40594,40596,40599,40601,40604,40606,40609,40611,40613],{"class":3418,"line":3671},[3416,40590,11444],{"class":4368},[3416,40592,40593],{"class":6387}," initializer",[3416,40595,6391],{"class":3795},[3416,40597,40598],{"class":6387},"scope",[3416,40600,4043],{"class":3795},[3416,40602,40603],{"class":6387},"ServiceProvider",[3416,40605,4043],{"class":3795},[3416,40607,40608],{"class":6330},"GetRequiredService",[3416,40610,5861],{"class":3795},[3416,40612,40489],{"class":6397},[3416,40614,30708],{"class":3795},[3416,40616,40617,40619,40621,40623,40626],{"class":3418,"line":3677},[3416,40618,11603],{"class":4368},[3416,40620,40593],{"class":6387},[3416,40622,4043],{"class":3795},[3416,40624,40625],{"class":6330},"InitializeAsync",[3416,40627,6401],{"class":3795},[3416,40629,40630],{"class":3418,"line":3683},[3416,40631,3507],{"class":3795},[3416,40633,40634],{"class":3418,"line":3688},[3416,40635,3441],{"emptyLinePlaceholder":3440},[3416,40637,40638,40640,40642,40645,40647,40650,40653,40656],{"class":3418,"line":3693},[3416,40639,40575],{"class":6387},[3416,40641,4043],{"class":3795},[3416,40643,40644],{"class":6330},"MapGet",[3416,40646,6423],{"class":3795},[3416,40648,40649],{"class":3808},"\"\u002F\"",[3416,40651,40652],{"class":3795},", () => ",[3416,40654,40655],{"class":3808},"\"Task Manager API is running!\"",[3416,40657,11465],{"class":3795},[3416,40659,40660],{"class":3418,"line":3698},[3416,40661,3441],{"emptyLinePlaceholder":3440},[3416,40663,40664],{"class":3418,"line":3704},[3416,40665,40666],{"class":3789},"\u002F\u002F Наші ендпоінти будуть додані у Кроці 5...\n",[3416,40668,40669],{"class":3418,"line":3710},[3416,40670,3441],{"emptyLinePlaceholder":3440},[3416,40672,40673,40675,40677,40680],{"class":3418,"line":3715},[3416,40674,40575],{"class":6387},[3416,40676,4043],{"class":3795},[3416,40678,40679],{"class":6330},"Run",[3416,40681,6401],{"class":3795},[3720,40683],{},[3727,40685,40687],{"id":40686},"крок-4-реалізація-crud-репозиторію","Крок 4: Реалізація CRUD репозиторію",[3353,40689,40690,40691,40693],{},"Створимо рівень доступу до даних (Data Access Layer), який приховує деталі взаємодії з ",[3413,40692,30279],{}," за допомогою чистого інтерфейсу.",[38250,40695,40696,40700,40706,40889,40893,40901],{},[3727,40697,40699],{"id":40698},"_1-створення-інтерфейсу-репозиторію","1. Створення інтерфейсу репозиторію",[3353,40701,40702,40703,40705],{},"Створимо інтерфейс ",[3413,40704,40508],{}," для основних операцій над завданнями:",[38843,40707,40708],{},[3406,40709,40712],{"className":6375,"code":40710,"filename":40711,"language":6377,"meta":3411,"style":3411},"using TaskManager.Api.Models;\n\nnamespace TaskManager.Api.Repositories;\n\npublic interface ITaskRepository\n{\n    Task\u003CTaskItem?> GetTaskAsync(string userId, string taskId);\n    Task\u003CIEnumerable\u003CTaskItem>> GetUserTasksAsync(string userId);\n    Task\u003CIEnumerable\u003CTaskItem>> GetTasksByStatusAsync(string status);\n    Task CreateOrUpdateTaskAsync(TaskItem item);\n    Task DeleteTaskAsync(string userId, string taskId);\n}\n","Repositories\u002FITaskRepository.cs",[3413,40713,40714,40730,40734,40750,40754,40764,40768,40798,40823,40849,40864,40885],{"__ignoreMap":3411},[3416,40715,40716,40718,40720,40722,40724,40726,40728],{"class":3418,"line":3419},[3416,40717,17433],{"class":11427},[3416,40719,38877],{"class":6397},[3416,40721,4043],{"class":3795},[3416,40723,38882],{"class":6397},[3416,40725,4043],{"class":3795},[3416,40727,38887],{"class":6397},[3416,40729,11594],{"class":3795},[3416,40731,40732],{"class":3418,"line":3425},[3416,40733,3441],{"emptyLinePlaceholder":3440},[3416,40735,40736,40738,40740,40742,40744,40746,40748],{"class":3418,"line":3431},[3416,40737,36194],{"class":4368},[3416,40739,38877],{"class":6397},[3416,40741,4043],{"class":3795},[3416,40743,38882],{"class":6397},[3416,40745,4043],{"class":3795},[3416,40747,40149],{"class":6397},[3416,40749,11594],{"class":3795},[3416,40751,40752],{"class":3418,"line":3437},[3416,40753,3441],{"emptyLinePlaceholder":3440},[3416,40755,40756,40758,40761],{"class":3418,"line":3444},[3416,40757,31180],{"class":4368},[3416,40759,40760],{"class":4368}," interface",[3416,40762,40763],{"class":6397}," ITaskRepository\n",[3416,40765,40766],{"class":3418,"line":3450},[3416,40767,3796],{"class":3795},[3416,40769,40770,40773,40775,40777,40779,40782,40784,40786,40789,40791,40793,40796],{"class":3418,"line":3456},[3416,40771,40772],{"class":6397},"    Task",[3416,40774,5861],{"class":3795},[3416,40776,38840],{"class":6397},[3416,40778,32880],{"class":3795},[3416,40780,40781],{"class":6330},"GetTaskAsync",[3416,40783,6423],{"class":3795},[3416,40785,6461],{"class":4368},[3416,40787,40788],{"class":6387}," userId",[3416,40790,4384],{"class":3795},[3416,40792,6461],{"class":4368},[3416,40794,40795],{"class":6387}," taskId",[3416,40797,11465],{"class":3795},[3416,40799,40800,40802,40804,40806,40808,40810,40812,40815,40817,40819,40821],{"class":3418,"line":3462},[3416,40801,40772],{"class":6397},[3416,40803,5861],{"class":3795},[3416,40805,34855],{"class":6397},[3416,40807,5861],{"class":3795},[3416,40809,38840],{"class":6397},[3416,40811,34862],{"class":3795},[3416,40813,40814],{"class":6330},"GetUserTasksAsync",[3416,40816,6423],{"class":3795},[3416,40818,6461],{"class":4368},[3416,40820,40788],{"class":6387},[3416,40822,11465],{"class":3795},[3416,40824,40825,40827,40829,40831,40833,40835,40837,40840,40842,40844,40847],{"class":3418,"line":3468},[3416,40826,40772],{"class":6397},[3416,40828,5861],{"class":3795},[3416,40830,34855],{"class":6397},[3416,40832,5861],{"class":3795},[3416,40834,38840],{"class":6397},[3416,40836,34862],{"class":3795},[3416,40838,40839],{"class":6330},"GetTasksByStatusAsync",[3416,40841,6423],{"class":3795},[3416,40843,6461],{"class":4368},[3416,40845,40846],{"class":6387}," status",[3416,40848,11465],{"class":3795},[3416,40850,40851,40853,40856,40858,40860,40862],{"class":3418,"line":3474},[3416,40852,40772],{"class":6397},[3416,40854,40855],{"class":6330}," CreateOrUpdateTaskAsync",[3416,40857,6423],{"class":3795},[3416,40859,38840],{"class":6397},[3416,40861,34645],{"class":6387},[3416,40863,11465],{"class":3795},[3416,40865,40866,40868,40871,40873,40875,40877,40879,40881,40883],{"class":3418,"line":3480},[3416,40867,40772],{"class":6397},[3416,40869,40870],{"class":6330}," DeleteTaskAsync",[3416,40872,6423],{"class":3795},[3416,40874,6461],{"class":4368},[3416,40876,40788],{"class":6387},[3416,40878,4384],{"class":3795},[3416,40880,6461],{"class":4368},[3416,40882,40795],{"class":6387},[3416,40884,11465],{"class":3795},[3416,40886,40887],{"class":3418,"line":3486},[3416,40888,3507],{"class":3795},[3727,40890,40892],{"id":40891},"_2-реалізація-репозиторію-за-допомогою-opm-orm","2. Реалізація репозиторію за допомогою OPM ORM",[3353,40894,38837,40895,40897,40898,40900],{},[3413,40896,40513],{},". Він використовуватиме ",[3413,40899,30735],{}," для CRUD, а також локальне перевизначення конфігурації для пошуку за індексом GSI:",[38843,40902,40903],{},[3406,40904,40907],{"className":6375,"code":40905,"filename":40906,"language":6377,"meta":3411,"style":3411},"using Amazon.DynamoDBv2.DataModel;\nusing TaskManager.Api.Models;\n\nnamespace TaskManager.Api.Repositories;\n\npublic class DynamoDBTaskRepository : ITaskRepository\n{\n    private readonly IDynamoDBContext _context;\n\n    public DynamoDBTaskRepository(IDynamoDBContext context) => _context = context;\n\n    \u002F\u002F Зчитування окремого завдання за HASH + RANGE ключем\n    public async Task\u003CTaskItem?> GetTaskAsync(string userId, string taskId)\n    {\n        return await _context.LoadAsync\u003CTaskItem>(userId, taskId);\n    }\n\n    \u002F\u002F Отримання всіх завдань користувача (Query за HASH-ключем)\n    public async Task\u003CIEnumerable\u003CTaskItem>> GetUserTasksAsync(string userId)\n    {\n        var search = _context.QueryAsync\u003CTaskItem>(userId);\n        return await search.GetRemainingAsync();\n    }\n\n    \u002F\u002F Отримання завдань за статусом (Query за GSI \"Status-index\")\n    public async Task\u003CIEnumerable\u003CTaskItem>> GetTasksByStatusAsync(string status)\n    {\n        var config = new DynamoDBOperationConfig\n        {\n            IndexName = \"Status-index\",\n            ConsistentRead = false \u002F\u002F GSIs підтримують лише Eventually Consistent Read\n        };\n\n        var search = _context.QueryAsync\u003CTaskItem>(status, config);\n        return await search.GetRemainingAsync();\n    }\n\n    \u002F\u002F Створення або оновлення (Upsert). Задіює Optimistic Locking за версією\n    public async Task CreateOrUpdateTaskAsync(TaskItem item)\n    {\n        await _context.SaveAsync(item);\n    }\n\n    \u002F\u002F Видалення завдання\n    public async Task DeleteTaskAsync(string userId, string taskId)\n    {\n        await _context.DeleteAsync\u003CTaskItem>(userId, taskId);\n    }\n}\n","Repositories\u002FDynamoDBTaskRepository.cs",[3413,40908,40909,40925,40941,40945,40961,40965,40979,40983,40995,40999,41021,41025,41030,41060,41064,41092,41096,41100,41105,41133,41137,41161,41175,41179,41183,41188,41216,41220,41232,41236,41246,41257,41261,41265,41294,41308,41312,41316,41321,41339,41343,41359,41363,41367,41372,41396,41400,41424,41428],{"__ignoreMap":3411},[3416,40910,40911,40913,40915,40917,40919,40921,40923],{"class":3418,"line":3419},[3416,40912,17433],{"class":11427},[3416,40914,17436],{"class":6397},[3416,40916,4043],{"class":3795},[3416,40918,17441],{"class":6397},[3416,40920,4043],{"class":3795},[3416,40922,30594],{"class":6397},[3416,40924,11594],{"class":3795},[3416,40926,40927,40929,40931,40933,40935,40937,40939],{"class":3418,"line":3425},[3416,40928,17433],{"class":11427},[3416,40930,38877],{"class":6397},[3416,40932,4043],{"class":3795},[3416,40934,38882],{"class":6397},[3416,40936,4043],{"class":3795},[3416,40938,38887],{"class":6397},[3416,40940,11594],{"class":3795},[3416,40942,40943],{"class":3418,"line":3431},[3416,40944,3441],{"emptyLinePlaceholder":3440},[3416,40946,40947,40949,40951,40953,40955,40957,40959],{"class":3418,"line":3437},[3416,40948,36194],{"class":4368},[3416,40950,38877],{"class":6397},[3416,40952,4043],{"class":3795},[3416,40954,38882],{"class":6397},[3416,40956,4043],{"class":3795},[3416,40958,40149],{"class":6397},[3416,40960,11594],{"class":3795},[3416,40962,40963],{"class":3418,"line":3444},[3416,40964,3441],{"emptyLinePlaceholder":3440},[3416,40966,40967,40969,40971,40974,40976],{"class":3418,"line":3450},[3416,40968,31180],{"class":4368},[3416,40970,31183],{"class":4368},[3416,40972,40973],{"class":6397}," DynamoDBTaskRepository",[3416,40975,31747],{"class":3795},[3416,40977,40978],{"class":6397},"ITaskRepository\n",[3416,40980,40981],{"class":3418,"line":3456},[3416,40982,3796],{"class":3795},[3416,40984,40985,40987,40989,40991,40993],{"class":3418,"line":3462},[3416,40986,31195],{"class":4368},[3416,40988,31198],{"class":4368},[3416,40990,34507],{"class":6397},[3416,40992,34510],{"class":6387},[3416,40994,11594],{"class":3795},[3416,40996,40997],{"class":3418,"line":3468},[3416,40998,3441],{"emptyLinePlaceholder":3440},[3416,41000,41001,41003,41005,41007,41009,41011,41013,41015,41017,41019],{"class":3418,"line":3474},[3416,41002,31235],{"class":4368},[3416,41004,40973],{"class":6330},[3416,41006,6423],{"class":3795},[3416,41008,30735],{"class":6397},[3416,41010,34530],{"class":6387},[3416,41012,31247],{"class":3795},[3416,41014,34535],{"class":6387},[3416,41016,6391],{"class":3795},[3416,41018,34540],{"class":6387},[3416,41020,11594],{"class":3795},[3416,41022,41023],{"class":3418,"line":3480},[3416,41024,3441],{"emptyLinePlaceholder":3440},[3416,41026,41027],{"class":3418,"line":3486},[3416,41028,41029],{"class":3789},"    \u002F\u002F Зчитування окремого завдання за HASH + RANGE ключем\n",[3416,41031,41032,41034,41036,41038,41040,41042,41044,41046,41048,41050,41052,41054,41056,41058],{"class":3418,"line":3492},[3416,41033,31235],{"class":4368},[3416,41035,31273],{"class":4368},[3416,41037,11606],{"class":6397},[3416,41039,5861],{"class":3795},[3416,41041,38840],{"class":6397},[3416,41043,32880],{"class":3795},[3416,41045,40781],{"class":6330},[3416,41047,6423],{"class":3795},[3416,41049,6461],{"class":4368},[3416,41051,40788],{"class":6387},[3416,41053,4384],{"class":3795},[3416,41055,6461],{"class":4368},[3416,41057,40795],{"class":6387},[3416,41059,9656],{"class":3795},[3416,41061,41062],{"class":3418,"line":3498},[3416,41063,6474],{"class":3795},[3416,41065,41066,41068,41070,41072,41074,41076,41078,41080,41082,41085,41087,41090],{"class":3418,"line":3504},[3416,41067,30902],{"class":11427},[3416,41069,32913],{"class":4368},[3416,41071,34510],{"class":6387},[3416,41073,4043],{"class":3795},[3416,41075,34600],{"class":6330},[3416,41077,5861],{"class":3795},[3416,41079,38840],{"class":6397},[3416,41081,30838],{"class":3795},[3416,41083,41084],{"class":6387},"userId",[3416,41086,4384],{"class":3795},[3416,41088,41089],{"class":6387},"taskId",[3416,41091,11465],{"class":3795},[3416,41093,41094],{"class":3418,"line":3510},[3416,41095,4167],{"class":3795},[3416,41097,41098],{"class":3418,"line":3515},[3416,41099,3441],{"emptyLinePlaceholder":3440},[3416,41101,41102],{"class":3418,"line":3521},[3416,41103,41104],{"class":3789},"    \u002F\u002F Отримання всіх завдань користувача (Query за HASH-ключем)\n",[3416,41106,41107,41109,41111,41113,41115,41117,41119,41121,41123,41125,41127,41129,41131],{"class":3418,"line":3527},[3416,41108,31235],{"class":4368},[3416,41110,31273],{"class":4368},[3416,41112,11606],{"class":6397},[3416,41114,5861],{"class":3795},[3416,41116,34855],{"class":6397},[3416,41118,5861],{"class":3795},[3416,41120,38840],{"class":6397},[3416,41122,34862],{"class":3795},[3416,41124,40814],{"class":6330},[3416,41126,6423],{"class":3795},[3416,41128,6461],{"class":4368},[3416,41130,40788],{"class":6387},[3416,41132,9656],{"class":3795},[3416,41134,41135],{"class":3418,"line":3533},[3416,41136,6474],{"class":3795},[3416,41138,41139,41141,41143,41145,41147,41149,41151,41153,41155,41157,41159],{"class":3418,"line":3539},[3416,41140,30853],{"class":4368},[3416,41142,33218],{"class":6387},[3416,41144,6391],{"class":3795},[3416,41146,34535],{"class":6387},[3416,41148,4043],{"class":3795},[3416,41150,7748],{"class":6330},[3416,41152,5861],{"class":3795},[3416,41154,38840],{"class":6397},[3416,41156,30838],{"class":3795},[3416,41158,41084],{"class":6387},[3416,41160,11465],{"class":3795},[3416,41162,41163,41165,41167,41169,41171,41173],{"class":3418,"line":3545},[3416,41164,30902],{"class":11427},[3416,41166,32913],{"class":4368},[3416,41168,33218],{"class":6387},[3416,41170,4043],{"class":3795},[3416,41172,34988],{"class":6330},[3416,41174,6401],{"class":3795},[3416,41176,41177],{"class":3418,"line":3551},[3416,41178,4167],{"class":3795},[3416,41180,41181],{"class":3418,"line":3557},[3416,41182,3441],{"emptyLinePlaceholder":3440},[3416,41184,41185],{"class":3418,"line":3563},[3416,41186,41187],{"class":3789},"    \u002F\u002F Отримання завдань за статусом (Query за GSI \"Status-index\")\n",[3416,41189,41190,41192,41194,41196,41198,41200,41202,41204,41206,41208,41210,41212,41214],{"class":3418,"line":3569},[3416,41191,31235],{"class":4368},[3416,41193,31273],{"class":4368},[3416,41195,11606],{"class":6397},[3416,41197,5861],{"class":3795},[3416,41199,34855],{"class":6397},[3416,41201,5861],{"class":3795},[3416,41203,38840],{"class":6397},[3416,41205,34862],{"class":3795},[3416,41207,40839],{"class":6330},[3416,41209,6423],{"class":3795},[3416,41211,6461],{"class":4368},[3416,41213,40846],{"class":6387},[3416,41215,9656],{"class":3795},[3416,41217,41218],{"class":3418,"line":3574},[3416,41219,6474],{"class":3795},[3416,41221,41222,41224,41226,41228,41230],{"class":3418,"line":3579},[3416,41223,30853],{"class":4368},[3416,41225,30856],{"class":6387},[3416,41227,6391],{"class":3795},[3416,41229,6394],{"class":4368},[3416,41231,34891],{"class":6397},[3416,41233,41234],{"class":3418,"line":3584},[3416,41235,8611],{"class":3795},[3416,41237,41238,41240,41242,41244],{"class":3418,"line":3590},[3416,41239,15683],{"class":6387},[3416,41241,6391],{"class":3795},[3416,41243,39114],{"class":3808},[3416,41245,3812],{"class":3795},[3416,41247,41248,41250,41252,41254],{"class":3418,"line":3596},[3416,41249,31685],{"class":6387},[3416,41251,6391],{"class":3795},[3416,41253,4042],{"class":4368},[3416,41255,41256],{"class":3789}," \u002F\u002F GSIs підтримують лише Eventually Consistent Read\n",[3416,41258,41259],{"class":3418,"line":3602},[3416,41260,30897],{"class":3795},[3416,41262,41263],{"class":3418,"line":3608},[3416,41264,3441],{"emptyLinePlaceholder":3440},[3416,41266,41267,41269,41271,41273,41275,41277,41279,41281,41283,41285,41288,41290,41292],{"class":3418,"line":3614},[3416,41268,30853],{"class":4368},[3416,41270,33218],{"class":6387},[3416,41272,6391],{"class":3795},[3416,41274,34535],{"class":6387},[3416,41276,4043],{"class":3795},[3416,41278,7748],{"class":6330},[3416,41280,5861],{"class":3795},[3416,41282,38840],{"class":6397},[3416,41284,30838],{"class":3795},[3416,41286,41287],{"class":6387},"status",[3416,41289,4384],{"class":3795},[3416,41291,30912],{"class":6387},[3416,41293,11465],{"class":3795},[3416,41295,41296,41298,41300,41302,41304,41306],{"class":3418,"line":3620},[3416,41297,30902],{"class":11427},[3416,41299,32913],{"class":4368},[3416,41301,33218],{"class":6387},[3416,41303,4043],{"class":3795},[3416,41305,34988],{"class":6330},[3416,41307,6401],{"class":3795},[3416,41309,41310],{"class":3418,"line":3626},[3416,41311,4167],{"class":3795},[3416,41313,41314],{"class":3418,"line":3631},[3416,41315,3441],{"emptyLinePlaceholder":3440},[3416,41317,41318],{"class":3418,"line":3636},[3416,41319,41320],{"class":3789},"    \u002F\u002F Створення або оновлення (Upsert). Задіює Optimistic Locking за версією\n",[3416,41322,41323,41325,41327,41329,41331,41333,41335,41337],{"class":3418,"line":3641},[3416,41324,31235],{"class":4368},[3416,41326,31273],{"class":4368},[3416,41328,11606],{"class":6397},[3416,41330,40855],{"class":6330},[3416,41332,6423],{"class":3795},[3416,41334,38840],{"class":6397},[3416,41336,34645],{"class":6387},[3416,41338,9656],{"class":3795},[3416,41340,41341],{"class":3418,"line":3647},[3416,41342,6474],{"class":3795},[3416,41344,41345,41347,41349,41351,41353,41355,41357],{"class":3418,"line":3653},[3416,41346,31512],{"class":4368},[3416,41348,34510],{"class":6387},[3416,41350,4043],{"class":3795},[3416,41352,33508],{"class":6330},[3416,41354,6423],{"class":3795},[3416,41356,34691],{"class":6387},[3416,41358,11465],{"class":3795},[3416,41360,41361],{"class":3418,"line":3659},[3416,41362,4167],{"class":3795},[3416,41364,41365],{"class":3418,"line":3665},[3416,41366,3441],{"emptyLinePlaceholder":3440},[3416,41368,41369],{"class":3418,"line":3671},[3416,41370,41371],{"class":3789},"    \u002F\u002F Видалення завдання\n",[3416,41373,41374,41376,41378,41380,41382,41384,41386,41388,41390,41392,41394],{"class":3418,"line":3677},[3416,41375,31235],{"class":4368},[3416,41377,31273],{"class":4368},[3416,41379,11606],{"class":6397},[3416,41381,40870],{"class":6330},[3416,41383,6423],{"class":3795},[3416,41385,6461],{"class":4368},[3416,41387,40788],{"class":6387},[3416,41389,4384],{"class":3795},[3416,41391,6461],{"class":4368},[3416,41393,40795],{"class":6387},[3416,41395,9656],{"class":3795},[3416,41397,41398],{"class":3418,"line":3683},[3416,41399,6474],{"class":3795},[3416,41401,41402,41404,41406,41408,41410,41412,41414,41416,41418,41420,41422],{"class":3418,"line":3688},[3416,41403,31512],{"class":4368},[3416,41405,34510],{"class":6387},[3416,41407,4043],{"class":3795},[3416,41409,34815],{"class":6330},[3416,41411,5861],{"class":3795},[3416,41413,38840],{"class":6397},[3416,41415,30838],{"class":3795},[3416,41417,41084],{"class":6387},[3416,41419,4384],{"class":3795},[3416,41421,41089],{"class":6387},[3416,41423,11465],{"class":3795},[3416,41425,41426],{"class":3418,"line":3693},[3416,41427,4167],{"class":3795},[3416,41429,41430],{"class":3418,"line":3698},[3416,41431,3507],{"class":3795},[3727,41433,41435],{"id":41434},"крок-5-додавання-minimal-api-ендпоінтів-та-верифікація-роботи","Крок 5: Додавання Minimal API ендпоінтів та верифікація роботи",[3353,41437,41438],{},"На завершальному кроці ми додамо REST-ендпоінти для взаємодії з завданнями та протестуємо всі сценарії, включно з валідацією оптимістичного блокування при паралельному оновленні.",[38250,41440,41441,41445,41451,42440,42444,42454,42458,42464,42531,42539,42644,42652,42656,42673,42680,42755,42759,42775,42784,42788,42797,42865,42871,42924,42934,42942,42997,43004,43027,43030,43034,43051],{},[3727,41442,41444],{"id":41443},"_1-додавання-ендпоінтів-у-programcs","1. Додавання ендпоінтів у Program.cs",[3353,41446,41447,41448,41450],{},"Оновіть файл ",[3413,41449,30562],{},", додавши групу ендпоінтів для роботи з завданнями. Зверніть увагу на обробку помилок при оновленні записів з невірною версією (Optimistic Locking):",[38843,41452,41453],{},[3406,41454,41457],{"className":6375,"code":41455,"filename":41456,"language":6377,"meta":3411,"style":3411},"\u002F\u002F ... попереднє налаштування з Кроку 3\n\nvar app = builder.Build();\n\nif (localMode)\n{\n    using var scope = app.Services.CreateScope();\n    var initializer = scope.ServiceProvider.GetRequiredService\u003CDynamoDbInitializer>();\n    await initializer.InitializeAsync();\n}\n\napp.MapGet(\"\u002F\", () => \"Task Manager API is running!\");\n\n\u002F\u002F Група ендпоінтів для задач\nvar tasksApi = app.MapGroup(\"\u002Fapi\u002Ftasks\");\n\n\u002F\u002F 1. Створення завдання\ntasksApi.MapPost(\"\u002F\", async (TaskItem task, ITaskRepository repository) =>\n{\n    task.TaskId = Guid.NewGuid().ToString(\"N\");\n    task.CreatedAt = DateTime.UtcNow;\n    task.Version = 1; \u002F\u002F Початкова версія для оптимістичного блокування\n\n    await repository.CreateOrUpdateTaskAsync(task);\n    return Results.Created($\"\u002Fapi\u002Ftasks\u002F{task.UserId}\u002F{task.TaskId}\", task);\n});\n\n\u002F\u002F 2. Отримання конкретного завдання\ntasksApi.MapGet(\"\u002F{userId}\u002F{taskId}\", async (string userId, string taskId, ITaskRepository repository) =>\n{\n    var task = await repository.GetTaskAsync(userId, taskId);\n    return task is not null ? Results.Ok(task) : Results.NotFound();\n});\n\n\u002F\u002F 3. Отримання всіх завдань користувача\ntasksApi.MapGet(\"\u002F{userId}\", async (string userId, ITaskRepository repository) =>\n{\n    var tasks = await repository.GetUserTasksAsync(userId);\n    return Results.Ok(tasks);\n});\n\n\u002F\u002F 4. Отримання завдань за статусом (задіяння GSI)\ntasksApi.MapGet(\"\u002Fstatus\u002F{status}\", async (string status, ITaskRepository repository) =>\n{\n    var tasks = await repository.GetTasksByStatusAsync(status);\n    return Results.Ok(tasks);\n});\n\n\u002F\u002F 5. Оновлення завдання (із перевіркою версії)\ntasksApi.MapPut(\"\u002F\", async (TaskItem task, ITaskRepository repository) =>\n{\n    try\n    {\n        \u002F\u002F Для успішного оновлення клієнт має передати поточне значення поля Version.\n        \u002F\u002F Якщо версія у базі вже змінилася, виникне ConditionalCheckFailedException.\n        await repository.CreateOrUpdateTaskAsync(task);\n        return Results.Ok(task);\n    }\n    catch (Amazon.DynamoDBv2.AmazonDynamoDBException ex) when (ex.ErrorCode == \"ConditionalCheckFailedException\")\n    {\n        return Results.Conflict(new { message = \"Конфлікт паралельного оновлення. Версія запису у базі була змінена іншим процесом.\" });\n    }\n});\n\n\u002F\u002F 6. Видалення завдання\ntasksApi.MapDelete(\"\u002F{userId}\u002F{taskId}\", async (string userId, string taskId, ITaskRepository repository) =>\n{\n    var task = await repository.GetTaskAsync(userId, taskId);\n    if (task is null)\n    {\n        return Results.NotFound();\n    }\n\n    await repository.DeleteTaskAsync(userId, taskId);\n    return Results.NoContent();\n});\n\napp.Run();\n","Program.cs (продовження)",[3413,41458,41459,41464,41468,41484,41488,41498,41502,41524,41548,41560,41564,41568,41586,41590,41595,41618,41622,41627,41663,41667,41695,41713,41730,41734,41752,41801,41805,41809,41814,41851,41855,41881,41920,41924,41928,41933,41964,41968,41991,42008,42012,42016,42021,42052,42056,42078,42094,42098,42102,42107,42138,42142,42147,42151,42156,42161,42177,42193,42197,42234,42238,42266,42270,42274,42278,42283,42320,42324,42350,42364,42368,42380,42384,42388,42409,42422,42426,42430],{"__ignoreMap":3411},[3416,41460,41461],{"class":3418,"line":3419},[3416,41462,41463],{"class":3789},"\u002F\u002F ... попереднє налаштування з Кроку 3\n",[3416,41465,41466],{"class":3418,"line":3425},[3416,41467,3441],{"emptyLinePlaceholder":3440},[3416,41469,41470,41472,41474,41476,41478,41480,41482],{"class":3418,"line":3431},[3416,41471,6384],{"class":4368},[3416,41473,40526],{"class":6387},[3416,41475,6391],{"class":3795},[3416,41477,30645],{"class":6387},[3416,41479,4043],{"class":3795},[3416,41481,40535],{"class":6330},[3416,41483,6401],{"class":3795},[3416,41485,41486],{"class":3418,"line":3437},[3416,41487,3441],{"emptyLinePlaceholder":3440},[3416,41489,41490,41492,41494,41496],{"class":3418,"line":3444},[3416,41491,30796],{"class":11427},[3416,41493,11431],{"class":3795},[3416,41495,40251],{"class":6387},[3416,41497,9656],{"class":3795},[3416,41499,41500],{"class":3418,"line":3450},[3416,41501,3796],{"class":3795},[3416,41503,41504,41506,41508,41510,41512,41514,41516,41518,41520,41522],{"class":3418,"line":3456},[3416,41505,40565],{"class":11427},[3416,41507,36608],{"class":4368},[3416,41509,40570],{"class":6387},[3416,41511,6391],{"class":3795},[3416,41513,40575],{"class":6387},[3416,41515,4043],{"class":3795},[3416,41517,30666],{"class":6387},[3416,41519,4043],{"class":3795},[3416,41521,40584],{"class":6330},[3416,41523,6401],{"class":3795},[3416,41525,41526,41528,41530,41532,41534,41536,41538,41540,41542,41544,41546],{"class":3418,"line":3462},[3416,41527,11444],{"class":4368},[3416,41529,40593],{"class":6387},[3416,41531,6391],{"class":3795},[3416,41533,40598],{"class":6387},[3416,41535,4043],{"class":3795},[3416,41537,40603],{"class":6387},[3416,41539,4043],{"class":3795},[3416,41541,40608],{"class":6330},[3416,41543,5861],{"class":3795},[3416,41545,40489],{"class":6397},[3416,41547,30708],{"class":3795},[3416,41549,41550,41552,41554,41556,41558],{"class":3418,"line":3468},[3416,41551,11603],{"class":4368},[3416,41553,40593],{"class":6387},[3416,41555,4043],{"class":3795},[3416,41557,40625],{"class":6330},[3416,41559,6401],{"class":3795},[3416,41561,41562],{"class":3418,"line":3474},[3416,41563,3507],{"class":3795},[3416,41565,41566],{"class":3418,"line":3480},[3416,41567,3441],{"emptyLinePlaceholder":3440},[3416,41569,41570,41572,41574,41576,41578,41580,41582,41584],{"class":3418,"line":3486},[3416,41571,40575],{"class":6387},[3416,41573,4043],{"class":3795},[3416,41575,40644],{"class":6330},[3416,41577,6423],{"class":3795},[3416,41579,40649],{"class":3808},[3416,41581,40652],{"class":3795},[3416,41583,40655],{"class":3808},[3416,41585,11465],{"class":3795},[3416,41587,41588],{"class":3418,"line":3492},[3416,41589,3441],{"emptyLinePlaceholder":3440},[3416,41591,41592],{"class":3418,"line":3498},[3416,41593,41594],{"class":3789},"\u002F\u002F Група ендпоінтів для задач\n",[3416,41596,41597,41599,41602,41604,41606,41608,41611,41613,41616],{"class":3418,"line":3504},[3416,41598,6384],{"class":4368},[3416,41600,41601],{"class":6387}," tasksApi",[3416,41603,6391],{"class":3795},[3416,41605,40575],{"class":6387},[3416,41607,4043],{"class":3795},[3416,41609,41610],{"class":6330},"MapGroup",[3416,41612,6423],{"class":3795},[3416,41614,41615],{"class":3808},"\"\u002Fapi\u002Ftasks\"",[3416,41617,11465],{"class":3795},[3416,41619,41620],{"class":3418,"line":3510},[3416,41621,3441],{"emptyLinePlaceholder":3440},[3416,41623,41624],{"class":3418,"line":3515},[3416,41625,41626],{"class":3789},"\u002F\u002F 1. Створення завдання\n",[3416,41628,41629,41632,41634,41637,41639,41641,41643,41646,41648,41650,41653,41655,41657,41660],{"class":3418,"line":3521},[3416,41630,41631],{"class":6387},"tasksApi",[3416,41633,4043],{"class":3795},[3416,41635,41636],{"class":6330},"MapPost",[3416,41638,6423],{"class":3795},[3416,41640,40649],{"class":3808},[3416,41642,4384],{"class":3795},[3416,41644,41645],{"class":4368},"async",[3416,41647,11431],{"class":3795},[3416,41649,38840],{"class":6397},[3416,41651,41652],{"class":6387}," task",[3416,41654,4384],{"class":3795},[3416,41656,40508],{"class":6397},[3416,41658,41659],{"class":6387}," repository",[3416,41661,41662],{"class":3795},") =>\n",[3416,41664,41665],{"class":3418,"line":3527},[3416,41666,3796],{"class":3795},[3416,41668,41669,41672,41674,41676,41678,41680,41682,41684,41687,41689,41691,41693],{"class":3418,"line":3533},[3416,41670,41671],{"class":6387},"    task",[3416,41673,4043],{"class":3795},[3416,41675,37225],{"class":6387},[3416,41677,6391],{"class":3795},[3416,41679,35347],{"class":6387},[3416,41681,4043],{"class":3795},[3416,41683,35352],{"class":6330},[3416,41685,41686],{"class":3795},"().",[3416,41688,28214],{"class":6330},[3416,41690,6423],{"class":3795},[3416,41692,37700],{"class":3808},[3416,41694,11465],{"class":3795},[3416,41696,41697,41699,41701,41703,41705,41707,41709,41711],{"class":3418,"line":3539},[3416,41698,41671],{"class":6387},[3416,41700,4043],{"class":3795},[3416,41702,14378],{"class":6387},[3416,41704,6391],{"class":3795},[3416,41706,11644],{"class":6387},[3416,41708,4043],{"class":3795},[3416,41710,28050],{"class":6387},[3416,41712,11594],{"class":3795},[3416,41714,41715,41717,41719,41721,41723,41725,41727],{"class":3418,"line":3545},[3416,41716,41671],{"class":6387},[3416,41718,4043],{"class":3795},[3416,41720,33897],{"class":6387},[3416,41722,6391],{"class":3795},[3416,41724,13510],{"class":3870},[3416,41726,8900],{"class":3795},[3416,41728,41729],{"class":3789},"\u002F\u002F Початкова версія для оптимістичного блокування\n",[3416,41731,41732],{"class":3418,"line":3551},[3416,41733,3441],{"emptyLinePlaceholder":3440},[3416,41735,41736,41738,41740,41742,41745,41747,41750],{"class":3418,"line":3557},[3416,41737,11603],{"class":4368},[3416,41739,41659],{"class":6387},[3416,41741,4043],{"class":3795},[3416,41743,41744],{"class":6330},"CreateOrUpdateTaskAsync",[3416,41746,6423],{"class":3795},[3416,41748,41749],{"class":6387},"task",[3416,41751,11465],{"class":3795},[3416,41753,41754,41757,41760,41762,41765,41767,41770,41772,41774,41776,41778,41780,41783,41785,41787,41789,41791,41793,41795,41797,41799],{"class":3418,"line":3563},[3416,41755,41756],{"class":11427},"    return",[3416,41758,41759],{"class":6387}," Results",[3416,41761,4043],{"class":3795},[3416,41763,41764],{"class":6330},"Created",[3416,41766,6423],{"class":3795},[3416,41768,41769],{"class":3808},"$\"\u002Fapi\u002Ftasks\u002F",[3416,41771,11177],{"class":11533},[3416,41773,41749],{"class":6387},[3416,41775,4043],{"class":11533},[3416,41777,4494],{"class":6387},[3416,41779,11302],{"class":11533},[3416,41781,41782],{"class":3808},"\u002F",[3416,41784,11177],{"class":11533},[3416,41786,41749],{"class":6387},[3416,41788,4043],{"class":11533},[3416,41790,37225],{"class":6387},[3416,41792,11302],{"class":11533},[3416,41794,24569],{"class":3808},[3416,41796,4384],{"class":3795},[3416,41798,41749],{"class":6387},[3416,41800,11465],{"class":3795},[3416,41802,41803],{"class":3418,"line":3569},[3416,41804,6537],{"class":3795},[3416,41806,41807],{"class":3418,"line":3574},[3416,41808,3441],{"emptyLinePlaceholder":3440},[3416,41810,41811],{"class":3418,"line":3579},[3416,41812,41813],{"class":3789},"\u002F\u002F 2. Отримання конкретного завдання\n",[3416,41815,41816,41818,41820,41822,41824,41827,41829,41831,41833,41835,41837,41839,41841,41843,41845,41847,41849],{"class":3418,"line":3584},[3416,41817,41631],{"class":6387},[3416,41819,4043],{"class":3795},[3416,41821,40644],{"class":6330},[3416,41823,6423],{"class":3795},[3416,41825,41826],{"class":3808},"\"\u002F{userId}\u002F{taskId}\"",[3416,41828,4384],{"class":3795},[3416,41830,41645],{"class":4368},[3416,41832,11431],{"class":3795},[3416,41834,6461],{"class":4368},[3416,41836,40788],{"class":6387},[3416,41838,4384],{"class":3795},[3416,41840,6461],{"class":4368},[3416,41842,40795],{"class":6387},[3416,41844,4384],{"class":3795},[3416,41846,40508],{"class":6397},[3416,41848,41659],{"class":6387},[3416,41850,41662],{"class":3795},[3416,41852,41853],{"class":3418,"line":3590},[3416,41854,3796],{"class":3795},[3416,41856,41857,41859,41861,41863,41865,41867,41869,41871,41873,41875,41877,41879],{"class":3418,"line":3596},[3416,41858,11444],{"class":4368},[3416,41860,41652],{"class":6387},[3416,41862,6391],{"class":3795},[3416,41864,6413],{"class":4368},[3416,41866,41659],{"class":6387},[3416,41868,4043],{"class":3795},[3416,41870,40781],{"class":6330},[3416,41872,6423],{"class":3795},[3416,41874,41084],{"class":6387},[3416,41876,4384],{"class":3795},[3416,41878,41089],{"class":6387},[3416,41880,11465],{"class":3795},[3416,41882,41883,41885,41887,41889,41891,41894,41896,41899,41901,41904,41906,41908,41911,41913,41915,41918],{"class":3418,"line":3602},[3416,41884,41756],{"class":11427},[3416,41886,41652],{"class":6387},[3416,41888,34216],{"class":4368},[3416,41890,34219],{"class":4368},[3416,41892,41893],{"class":4368}," null",[3416,41895,31736],{"class":3795},[3416,41897,41898],{"class":6387},"Results",[3416,41900,4043],{"class":3795},[3416,41902,41903],{"class":6330},"Ok",[3416,41905,6423],{"class":3795},[3416,41907,41749],{"class":6387},[3416,41909,41910],{"class":3795},") : ",[3416,41912,41898],{"class":6387},[3416,41914,4043],{"class":3795},[3416,41916,41917],{"class":6330},"NotFound",[3416,41919,6401],{"class":3795},[3416,41921,41922],{"class":3418,"line":3608},[3416,41923,6537],{"class":3795},[3416,41925,41926],{"class":3418,"line":3614},[3416,41927,3441],{"emptyLinePlaceholder":3440},[3416,41929,41930],{"class":3418,"line":3620},[3416,41931,41932],{"class":3789},"\u002F\u002F 3. Отримання всіх завдань користувача\n",[3416,41934,41935,41937,41939,41941,41943,41946,41948,41950,41952,41954,41956,41958,41960,41962],{"class":3418,"line":3626},[3416,41936,41631],{"class":6387},[3416,41938,4043],{"class":3795},[3416,41940,40644],{"class":6330},[3416,41942,6423],{"class":3795},[3416,41944,41945],{"class":3808},"\"\u002F{userId}\"",[3416,41947,4384],{"class":3795},[3416,41949,41645],{"class":4368},[3416,41951,11431],{"class":3795},[3416,41953,6461],{"class":4368},[3416,41955,40788],{"class":6387},[3416,41957,4384],{"class":3795},[3416,41959,40508],{"class":6397},[3416,41961,41659],{"class":6387},[3416,41963,41662],{"class":3795},[3416,41965,41966],{"class":3418,"line":3631},[3416,41967,3796],{"class":3795},[3416,41969,41970,41972,41975,41977,41979,41981,41983,41985,41987,41989],{"class":3418,"line":3636},[3416,41971,11444],{"class":4368},[3416,41973,41974],{"class":6387}," tasks",[3416,41976,6391],{"class":3795},[3416,41978,6413],{"class":4368},[3416,41980,41659],{"class":6387},[3416,41982,4043],{"class":3795},[3416,41984,40814],{"class":6330},[3416,41986,6423],{"class":3795},[3416,41988,41084],{"class":6387},[3416,41990,11465],{"class":3795},[3416,41992,41993,41995,41997,41999,42001,42003,42006],{"class":3418,"line":3641},[3416,41994,41756],{"class":11427},[3416,41996,41759],{"class":6387},[3416,41998,4043],{"class":3795},[3416,42000,41903],{"class":6330},[3416,42002,6423],{"class":3795},[3416,42004,42005],{"class":6387},"tasks",[3416,42007,11465],{"class":3795},[3416,42009,42010],{"class":3418,"line":3647},[3416,42011,6537],{"class":3795},[3416,42013,42014],{"class":3418,"line":3653},[3416,42015,3441],{"emptyLinePlaceholder":3440},[3416,42017,42018],{"class":3418,"line":3659},[3416,42019,42020],{"class":3789},"\u002F\u002F 4. Отримання завдань за статусом (задіяння GSI)\n",[3416,42022,42023,42025,42027,42029,42031,42034,42036,42038,42040,42042,42044,42046,42048,42050],{"class":3418,"line":3665},[3416,42024,41631],{"class":6387},[3416,42026,4043],{"class":3795},[3416,42028,40644],{"class":6330},[3416,42030,6423],{"class":3795},[3416,42032,42033],{"class":3808},"\"\u002Fstatus\u002F{status}\"",[3416,42035,4384],{"class":3795},[3416,42037,41645],{"class":4368},[3416,42039,11431],{"class":3795},[3416,42041,6461],{"class":4368},[3416,42043,40846],{"class":6387},[3416,42045,4384],{"class":3795},[3416,42047,40508],{"class":6397},[3416,42049,41659],{"class":6387},[3416,42051,41662],{"class":3795},[3416,42053,42054],{"class":3418,"line":3671},[3416,42055,3796],{"class":3795},[3416,42057,42058,42060,42062,42064,42066,42068,42070,42072,42074,42076],{"class":3418,"line":3677},[3416,42059,11444],{"class":4368},[3416,42061,41974],{"class":6387},[3416,42063,6391],{"class":3795},[3416,42065,6413],{"class":4368},[3416,42067,41659],{"class":6387},[3416,42069,4043],{"class":3795},[3416,42071,40839],{"class":6330},[3416,42073,6423],{"class":3795},[3416,42075,41287],{"class":6387},[3416,42077,11465],{"class":3795},[3416,42079,42080,42082,42084,42086,42088,42090,42092],{"class":3418,"line":3683},[3416,42081,41756],{"class":11427},[3416,42083,41759],{"class":6387},[3416,42085,4043],{"class":3795},[3416,42087,41903],{"class":6330},[3416,42089,6423],{"class":3795},[3416,42091,42005],{"class":6387},[3416,42093,11465],{"class":3795},[3416,42095,42096],{"class":3418,"line":3688},[3416,42097,6537],{"class":3795},[3416,42099,42100],{"class":3418,"line":3693},[3416,42101,3441],{"emptyLinePlaceholder":3440},[3416,42103,42104],{"class":3418,"line":3698},[3416,42105,42106],{"class":3789},"\u002F\u002F 5. Оновлення завдання (із перевіркою версії)\n",[3416,42108,42109,42111,42113,42116,42118,42120,42122,42124,42126,42128,42130,42132,42134,42136],{"class":3418,"line":3704},[3416,42110,41631],{"class":6387},[3416,42112,4043],{"class":3795},[3416,42114,42115],{"class":6330},"MapPut",[3416,42117,6423],{"class":3795},[3416,42119,40649],{"class":3808},[3416,42121,4384],{"class":3795},[3416,42123,41645],{"class":4368},[3416,42125,11431],{"class":3795},[3416,42127,38840],{"class":6397},[3416,42129,41652],{"class":6387},[3416,42131,4384],{"class":3795},[3416,42133,40508],{"class":6397},[3416,42135,41659],{"class":6387},[3416,42137,41662],{"class":3795},[3416,42139,42140],{"class":3418,"line":3710},[3416,42141,3796],{"class":3795},[3416,42143,42144],{"class":3418,"line":3715},[3416,42145,42146],{"class":11427},"    try\n",[3416,42148,42149],{"class":3418,"line":12799},[3416,42150,6474],{"class":3795},[3416,42152,42153],{"class":3418,"line":12822},[3416,42154,42155],{"class":3789},"        \u002F\u002F Для успішного оновлення клієнт має передати поточне значення поля Version.\n",[3416,42157,42158],{"class":3418,"line":12827},[3416,42159,42160],{"class":3789},"        \u002F\u002F Якщо версія у базі вже змінилася, виникне ConditionalCheckFailedException.\n",[3416,42162,42163,42165,42167,42169,42171,42173,42175],{"class":3418,"line":12832},[3416,42164,31512],{"class":4368},[3416,42166,41659],{"class":6387},[3416,42168,4043],{"class":3795},[3416,42170,41744],{"class":6330},[3416,42172,6423],{"class":3795},[3416,42174,41749],{"class":6387},[3416,42176,11465],{"class":3795},[3416,42178,42179,42181,42183,42185,42187,42189,42191],{"class":3418,"line":12837},[3416,42180,30902],{"class":11427},[3416,42182,41759],{"class":6387},[3416,42184,4043],{"class":3795},[3416,42186,41903],{"class":6330},[3416,42188,6423],{"class":3795},[3416,42190,41749],{"class":6387},[3416,42192,11465],{"class":3795},[3416,42194,42195],{"class":3418,"line":12843},[3416,42196,4167],{"class":3795},[3416,42198,42199,42202,42204,42206,42208,42210,42212,42214,42216,42218,42220,42222,42224,42226,42228,42230,42232],{"class":3418,"line":12860},[3416,42200,42201],{"class":11427},"    catch",[3416,42203,11431],{"class":3795},[3416,42205,22807],{"class":6397},[3416,42207,4043],{"class":3795},[3416,42209,17441],{"class":6397},[3416,42211,4043],{"class":3795},[3416,42213,34707],{"class":6397},[3416,42215,34710],{"class":6387},[3416,42217,34713],{"class":3795},[3416,42219,34716],{"class":11427},[3416,42221,11431],{"class":3795},[3416,42223,34721],{"class":6387},[3416,42225,4043],{"class":3795},[3416,42227,34726],{"class":6387},[3416,42229,11488],{"class":3795},[3416,42231,34731],{"class":3808},[3416,42233,9656],{"class":3795},[3416,42235,42236],{"class":3418,"line":12865},[3416,42237,6474],{"class":3795},[3416,42239,42240,42242,42244,42246,42249,42251,42253,42255,42258,42260,42263],{"class":3418,"line":12876},[3416,42241,30902],{"class":11427},[3416,42243,41759],{"class":6387},[3416,42245,4043],{"class":3795},[3416,42247,42248],{"class":6330},"Conflict",[3416,42250,6423],{"class":3795},[3416,42252,6394],{"class":4368},[3416,42254,6492],{"class":3795},[3416,42256,42257],{"class":6387},"message",[3416,42259,6391],{"class":3795},[3416,42261,42262],{"class":3808},"\"Конфлікт паралельного оновлення. Версія запису у базі була змінена іншим процесом.\"",[3416,42264,42265],{"class":3795}," });\n",[3416,42267,42268],{"class":3418,"line":12897},[3416,42269,4167],{"class":3795},[3416,42271,42272],{"class":3418,"line":12902},[3416,42273,6537],{"class":3795},[3416,42275,42276],{"class":3418,"line":12925},[3416,42277,3441],{"emptyLinePlaceholder":3440},[3416,42279,42280],{"class":3418,"line":12948},[3416,42281,42282],{"class":3789},"\u002F\u002F 6. Видалення завдання\n",[3416,42284,42285,42287,42289,42292,42294,42296,42298,42300,42302,42304,42306,42308,42310,42312,42314,42316,42318],{"class":3418,"line":12953},[3416,42286,41631],{"class":6387},[3416,42288,4043],{"class":3795},[3416,42290,42291],{"class":6330},"MapDelete",[3416,42293,6423],{"class":3795},[3416,42295,41826],{"class":3808},[3416,42297,4384],{"class":3795},[3416,42299,41645],{"class":4368},[3416,42301,11431],{"class":3795},[3416,42303,6461],{"class":4368},[3416,42305,40788],{"class":6387},[3416,42307,4384],{"class":3795},[3416,42309,6461],{"class":4368},[3416,42311,40795],{"class":6387},[3416,42313,4384],{"class":3795},[3416,42315,40508],{"class":6397},[3416,42317,41659],{"class":6387},[3416,42319,41662],{"class":3795},[3416,42321,42322],{"class":3418,"line":20609},[3416,42323,3796],{"class":3795},[3416,42325,42326,42328,42330,42332,42334,42336,42338,42340,42342,42344,42346,42348],{"class":3418,"line":20614},[3416,42327,11444],{"class":4368},[3416,42329,41652],{"class":6387},[3416,42331,6391],{"class":3795},[3416,42333,6413],{"class":4368},[3416,42335,41659],{"class":6387},[3416,42337,4043],{"class":3795},[3416,42339,40781],{"class":6330},[3416,42341,6423],{"class":3795},[3416,42343,41084],{"class":6387},[3416,42345,4384],{"class":3795},[3416,42347,41089],{"class":6387},[3416,42349,11465],{"class":3795},[3416,42351,42352,42354,42356,42358,42360,42362],{"class":3418,"line":20619},[3416,42353,11470],{"class":11427},[3416,42355,11431],{"class":3795},[3416,42357,41749],{"class":6387},[3416,42359,34216],{"class":4368},[3416,42361,41893],{"class":4368},[3416,42363,9656],{"class":3795},[3416,42365,42366],{"class":3418,"line":20624},[3416,42367,6474],{"class":3795},[3416,42369,42370,42372,42374,42376,42378],{"class":3418,"line":20630},[3416,42371,30902],{"class":11427},[3416,42373,41759],{"class":6387},[3416,42375,4043],{"class":3795},[3416,42377,41917],{"class":6330},[3416,42379,6401],{"class":3795},[3416,42381,42382],{"class":3418,"line":20647},[3416,42383,4167],{"class":3795},[3416,42385,42386],{"class":3418,"line":20652},[3416,42387,3441],{"emptyLinePlaceholder":3440},[3416,42389,42390,42392,42394,42396,42399,42401,42403,42405,42407],{"class":3418,"line":20663},[3416,42391,11603],{"class":4368},[3416,42393,41659],{"class":6387},[3416,42395,4043],{"class":3795},[3416,42397,42398],{"class":6330},"DeleteTaskAsync",[3416,42400,6423],{"class":3795},[3416,42402,41084],{"class":6387},[3416,42404,4384],{"class":3795},[3416,42406,41089],{"class":6387},[3416,42408,11465],{"class":3795},[3416,42410,42411,42413,42415,42417,42420],{"class":3418,"line":20684},[3416,42412,41756],{"class":11427},[3416,42414,41759],{"class":6387},[3416,42416,4043],{"class":3795},[3416,42418,42419],{"class":6330},"NoContent",[3416,42421,6401],{"class":3795},[3416,42423,42424],{"class":3418,"line":20689},[3416,42425,6537],{"class":3795},[3416,42427,42428],{"class":3418,"line":20712},[3416,42429,3441],{"emptyLinePlaceholder":3440},[3416,42431,42432,42434,42436,42438],{"class":3418,"line":20735},[3416,42433,40575],{"class":6387},[3416,42435,4043],{"class":3795},[3416,42437,40679],{"class":6330},[3416,42439,6401],{"class":3795},[3727,42441,42443],{"id":42442},"_2-верифікація-роботи-через-http-запити-curl","2. Верифікація роботи через HTTP-запити (cURL)",[3353,42445,42446,42447,42450,42451,4043],{},"Для тестування розробленого API запустіть проєкт за допомогою команди ",[3413,42448,42449],{},"dotnet run",". Протестуємо основні сценарії за допомогою ",[3413,42452,42453],{},"curl",[4584,42455,42457],{"id":42456},"а-створення-нового-завдання","А. Створення нового завдання",[3353,42459,42460,42461,10458],{},"Відправте POST-запит для створення завдання для користувача ",[3413,42462,42463],{},"user-100",[3406,42465,42467],{"className":6316,"code":42466,"language":6318,"meta":3411,"style":3411},"curl -X POST http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"UserId\": \"user-100\",\n    \"Title\": \"Вивчити AWS DynamoDB SDK\",\n    \"Description\": \"Розібрати Low-Level, Document та OPM інтерфейси\",\n    \"Status\": \"IN_PROGRESS\",\n    \"Priority\": \"HIGH\"\n  }'\n",[3413,42468,42469,42484,42494,42501,42506,42511,42516,42521,42526],{"__ignoreMap":3411},[3416,42470,42471,42473,42476,42479,42482],{"class":3418,"line":3419},[3416,42472,42453],{"class":6330},[3416,42474,42475],{"class":4368}," -X",[3416,42477,42478],{"class":3808}," POST",[3416,42480,42481],{"class":3808}," http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks",[3416,42483,6341],{"class":6340},[3416,42485,42486,42489,42492],{"class":3418,"line":3425},[3416,42487,42488],{"class":4368},"  -H",[3416,42490,42491],{"class":3808}," \"Content-Type: application\u002Fjson\"",[3416,42493,6341],{"class":6340},[3416,42495,42496,42499],{"class":3418,"line":3431},[3416,42497,42498],{"class":4368},"  -d",[3416,42500,6661],{"class":3808},[3416,42502,42503],{"class":3418,"line":3437},[3416,42504,42505],{"class":3808},"    \"UserId\": \"user-100\",\n",[3416,42507,42508],{"class":3418,"line":3444},[3416,42509,42510],{"class":3808},"    \"Title\": \"Вивчити AWS DynamoDB SDK\",\n",[3416,42512,42513],{"class":3418,"line":3450},[3416,42514,42515],{"class":3808},"    \"Description\": \"Розібрати Low-Level, Document та OPM інтерфейси\",\n",[3416,42517,42518],{"class":3418,"line":3456},[3416,42519,42520],{"class":3808},"    \"Status\": \"IN_PROGRESS\",\n",[3416,42522,42523],{"class":3418,"line":3462},[3416,42524,42525],{"class":3808},"    \"Priority\": \"HIGH\"\n",[3416,42527,42528],{"class":3418,"line":3468},[3416,42529,42530],{"class":3808},"  }'\n",[3353,42532,42533],{},[3363,42534,42535,42536,32096],{},"Очікувана відповідь (",[3413,42537,42538],{},"201 Created",[3406,42540,42542],{"className":3780,"code":42541,"language":3782,"meta":3411,"style":3411},"{\n  \"userId\": \"user-100\",\n  \"taskId\": \"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\",\n  \"title\": \"Вивчити AWS DynamoDB SDK\",\n  \"description\": \"Розібрати Low-Level, Document та OPM інтерфейси\",\n  \"status\": \"IN_PROGRESS\",\n  \"priority\": \"HIGH\",\n  \"createdAt\": \"2026-06-04T12:00:00Z\",\n  \"version\": 1\n}\n",[3413,42543,42544,42548,42560,42572,42584,42596,42608,42619,42631,42640],{"__ignoreMap":3411},[3416,42545,42546],{"class":3418,"line":3419},[3416,42547,3796],{"class":3795},[3416,42549,42550,42553,42555,42558],{"class":3418,"line":3425},[3416,42551,42552],{"class":3801},"  \"userId\"",[3416,42554,3805],{"class":3795},[3416,42556,42557],{"class":3808},"\"user-100\"",[3416,42559,3812],{"class":3795},[3416,42561,42562,42565,42567,42570],{"class":3418,"line":3431},[3416,42563,42564],{"class":3801},"  \"taskId\"",[3416,42566,3805],{"class":3795},[3416,42568,42569],{"class":3808},"\"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\"",[3416,42571,3812],{"class":3795},[3416,42573,42574,42577,42579,42582],{"class":3418,"line":3437},[3416,42575,42576],{"class":3801},"  \"title\"",[3416,42578,3805],{"class":3795},[3416,42580,42581],{"class":3808},"\"Вивчити AWS DynamoDB SDK\"",[3416,42583,3812],{"class":3795},[3416,42585,42586,42589,42591,42594],{"class":3418,"line":3444},[3416,42587,42588],{"class":3801},"  \"description\"",[3416,42590,3805],{"class":3795},[3416,42592,42593],{"class":3808},"\"Розібрати Low-Level, Document та OPM інтерфейси\"",[3416,42595,3812],{"class":3795},[3416,42597,42598,42601,42603,42606],{"class":3418,"line":3450},[3416,42599,42600],{"class":3801},"  \"status\"",[3416,42602,3805],{"class":3795},[3416,42604,42605],{"class":3808},"\"IN_PROGRESS\"",[3416,42607,3812],{"class":3795},[3416,42609,42610,42613,42615,42617],{"class":3418,"line":3456},[3416,42611,42612],{"class":3801},"  \"priority\"",[3416,42614,3805],{"class":3795},[3416,42616,37784],{"class":3808},[3416,42618,3812],{"class":3795},[3416,42620,42621,42624,42626,42629],{"class":3418,"line":3462},[3416,42622,42623],{"class":3801},"  \"createdAt\"",[3416,42625,3805],{"class":3795},[3416,42627,42628],{"class":3808},"\"2026-06-04T12:00:00Z\"",[3416,42630,3812],{"class":3795},[3416,42632,42633,42636,42638],{"class":3418,"line":3468},[3416,42634,42635],{"class":3801},"  \"version\"",[3416,42637,3805],{"class":3795},[3416,42639,6614],{"class":3870},[3416,42641,42642],{"class":3418,"line":3474},[3416,42643,3507],{"class":3795},[3353,42645,42646],{},[4091,42647,42648,42649,42651],{},"Примітка: скопіюйте згенерований ",[3413,42650,41089],{}," для наступних запитів.",[4584,42653,42655],{"id":42654},"б-отримання-завдань-користувача-query-за-hash-ключем","Б. Отримання завдань користувача (Query за Hash-ключем)",[3406,42657,42659],{"className":6316,"code":42658,"language":6318,"meta":3411,"style":3411},"curl -X GET http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks\u002Fuser-100\n",[3413,42660,42661],{"__ignoreMap":3411},[3416,42662,42663,42665,42667,42670],{"class":3418,"line":3419},[3416,42664,42453],{"class":6330},[3416,42666,42475],{"class":4368},[3416,42668,42669],{"class":3808}," GET",[3416,42671,42672],{"class":3808}," http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks\u002Fuser-100\n",[3353,42674,42675],{},[3363,42676,42535,42677,32096],{},[3413,42678,42679],{},"200 OK",[3406,42681,42683],{"className":3780,"code":42682,"language":3782,"meta":3411,"style":3411},"[\n  {\n    \"userId\": \"user-100\",\n    \"taskId\": \"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\",\n    \"title\": \"Вивчити AWS DynamoDB SDK\",\n    \"status\": \"IN_PROGRESS\",\n    \"version\": 1\n  }\n]\n",[3413,42684,42685,42689,42694,42705,42716,42727,42738,42747,42751],{"__ignoreMap":3411},[3416,42686,42687],{"class":3418,"line":3419},[3416,42688,18149],{"class":3795},[3416,42690,42691],{"class":3418,"line":3425},[3416,42692,42693],{"class":3795},"  {\n",[3416,42695,42696,42699,42701,42703],{"class":3418,"line":3431},[3416,42697,42698],{"class":3801},"    \"userId\"",[3416,42700,3805],{"class":3795},[3416,42702,42557],{"class":3808},[3416,42704,3812],{"class":3795},[3416,42706,42707,42710,42712,42714],{"class":3418,"line":3437},[3416,42708,42709],{"class":3801},"    \"taskId\"",[3416,42711,3805],{"class":3795},[3416,42713,42569],{"class":3808},[3416,42715,3812],{"class":3795},[3416,42717,42718,42721,42723,42725],{"class":3418,"line":3444},[3416,42719,42720],{"class":3801},"    \"title\"",[3416,42722,3805],{"class":3795},[3416,42724,42581],{"class":3808},[3416,42726,3812],{"class":3795},[3416,42728,42729,42732,42734,42736],{"class":3418,"line":3450},[3416,42730,42731],{"class":3801},"    \"status\"",[3416,42733,3805],{"class":3795},[3416,42735,42605],{"class":3808},[3416,42737,3812],{"class":3795},[3416,42739,42740,42743,42745],{"class":3418,"line":3456},[3416,42741,42742],{"class":3801},"    \"version\"",[3416,42744,3805],{"class":3795},[3416,42746,6614],{"class":3870},[3416,42748,42749],{"class":3418,"line":3462},[3416,42750,30530],{"class":3795},[3416,42752,42753],{"class":3418,"line":3468},[3416,42754,18183],{"class":3795},[4584,42756,42758],{"id":42757},"в-вибірка-за-статусом-query-через-gsi-status-index","В. Вибірка за статусом (Query через GSI \"Status-index\")",[3406,42760,42762],{"className":6316,"code":42761,"language":6318,"meta":3411,"style":3411},"curl -X GET http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks\u002Fstatus\u002FIN_PROGRESS\n",[3413,42763,42764],{"__ignoreMap":3411},[3416,42765,42766,42768,42770,42772],{"class":3418,"line":3419},[3416,42767,42453],{"class":6330},[3416,42769,42475],{"class":4368},[3416,42771,42669],{"class":3808},[3416,42773,42774],{"class":3808}," http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks\u002Fstatus\u002FIN_PROGRESS\n",[3353,42776,42777,42778,42780,42781,42783],{},"Поверне всі завдання з бази, у яких поле ",[3413,42779,5147],{}," дорівнює ",[3413,42782,38738],{}," (навіть якщо вони належать різним користувачам).",[4584,42785,42787],{"id":42786},"г-оновлення-та-тест-optimistic-locking-конфлікт-версій","Г. Оновлення та тест Optimistic Locking (Конфлікт версій)",[3353,42789,42790,42791,42793,42794,10458],{},"Спробуємо оновити статус завдання на ",[3413,42792,38741],{},". Спочатку відправимо коректний запит з ",[3413,42795,42796],{},"version: 1",[3406,42798,42800],{"className":6316,"code":42799,"language":6318,"meta":3411,"style":3411},"curl -X PUT http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"UserId\": \"user-100\",\n    \"TaskId\": \"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\",\n    \"Title\": \"Вивчити AWS DynamoDB SDK\",\n    \"Description\": \"Розібрати Low-Level, Document та OPM інтерфейси\",\n    \"Status\": \"DONE\",\n    \"Priority\": \"HIGH\",\n    \"Version\": 1\n  }'\n",[3413,42801,42802,42815,42823,42829,42833,42838,42842,42846,42851,42856,42861],{"__ignoreMap":3411},[3416,42803,42804,42806,42808,42811,42813],{"class":3418,"line":3419},[3416,42805,42453],{"class":6330},[3416,42807,42475],{"class":4368},[3416,42809,42810],{"class":3808}," PUT",[3416,42812,42481],{"class":3808},[3416,42814,6341],{"class":6340},[3416,42816,42817,42819,42821],{"class":3418,"line":3425},[3416,42818,42488],{"class":4368},[3416,42820,42491],{"class":3808},[3416,42822,6341],{"class":6340},[3416,42824,42825,42827],{"class":3418,"line":3431},[3416,42826,42498],{"class":4368},[3416,42828,6661],{"class":3808},[3416,42830,42831],{"class":3418,"line":3437},[3416,42832,42505],{"class":3808},[3416,42834,42835],{"class":3418,"line":3444},[3416,42836,42837],{"class":3808},"    \"TaskId\": \"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\",\n",[3416,42839,42840],{"class":3418,"line":3450},[3416,42841,42510],{"class":3808},[3416,42843,42844],{"class":3418,"line":3456},[3416,42845,42515],{"class":3808},[3416,42847,42848],{"class":3418,"line":3462},[3416,42849,42850],{"class":3808},"    \"Status\": \"DONE\",\n",[3416,42852,42853],{"class":3418,"line":3468},[3416,42854,42855],{"class":3808},"    \"Priority\": \"HIGH\",\n",[3416,42857,42858],{"class":3418,"line":3474},[3416,42859,42860],{"class":3808},"    \"Version\": 1\n",[3416,42862,42863],{"class":3418,"line":3480},[3416,42864,42530],{"class":3808},[3353,42866,42867],{},[3363,42868,42535,42869,32096],{},[3413,42870,42679],{},[3406,42872,42874],{"className":3780,"code":42873,"language":3782,"meta":3411,"style":3411},"{\n  \"userId\": \"user-100\",\n  \"taskId\": \"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\",\n  \"status\": \"DONE\",\n  \"version\": 2\n}\n",[3413,42875,42876,42880,42890,42900,42911,42920],{"__ignoreMap":3411},[3416,42877,42878],{"class":3418,"line":3419},[3416,42879,3796],{"class":3795},[3416,42881,42882,42884,42886,42888],{"class":3418,"line":3425},[3416,42883,42552],{"class":3801},[3416,42885,3805],{"class":3795},[3416,42887,42557],{"class":3808},[3416,42889,3812],{"class":3795},[3416,42891,42892,42894,42896,42898],{"class":3418,"line":3431},[3416,42893,42564],{"class":3801},[3416,42895,3805],{"class":3795},[3416,42897,42569],{"class":3808},[3416,42899,3812],{"class":3795},[3416,42901,42902,42904,42906,42909],{"class":3418,"line":3437},[3416,42903,42600],{"class":3801},[3416,42905,3805],{"class":3795},[3416,42907,42908],{"class":3808},"\"DONE\"",[3416,42910,3812],{"class":3795},[3416,42912,42913,42915,42917],{"class":3418,"line":3444},[3416,42914,42635],{"class":3801},[3416,42916,3805],{"class":3795},[3416,42918,42919],{"class":3870},"2\n",[3416,42921,42922],{"class":3418,"line":3450},[3416,42923,3507],{"class":3795},[3353,42925,42926],{},[4091,42927,42928,42929,42931,42932,4043],{},"Зверніть увагу: поле ",[3413,42930,38516],{}," автоматично збільшилось на ",[3413,42933,3955],{},[3353,42935,42936,42937,42939,42940,32096],{},"Тепер змоделюємо конфлікт паралельного доступу. Спробуємо знову виконати оновлення, але передамо застарілу версію ",[3413,42938,42796],{}," (хоча у базі вже збережена версія ",[3413,42941,3955],{},[3406,42943,42945],{"className":6316,"code":42944,"language":6318,"meta":3411,"style":3411},"curl -X PUT http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"UserId\": \"user-100\",\n    \"TaskId\": \"7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\",\n    \"Title\": \"Вивчити AWS DynamoDB SDK\",\n    \"Status\": \"DONE\",\n    \"Version\": 1\n  }'\n",[3413,42946,42947,42959,42967,42973,42977,42981,42985,42989,42993],{"__ignoreMap":3411},[3416,42948,42949,42951,42953,42955,42957],{"class":3418,"line":3419},[3416,42950,42453],{"class":6330},[3416,42952,42475],{"class":4368},[3416,42954,42810],{"class":3808},[3416,42956,42481],{"class":3808},[3416,42958,6341],{"class":6340},[3416,42960,42961,42963,42965],{"class":3418,"line":3425},[3416,42962,42488],{"class":4368},[3416,42964,42491],{"class":3808},[3416,42966,6341],{"class":6340},[3416,42968,42969,42971],{"class":3418,"line":3431},[3416,42970,42498],{"class":4368},[3416,42972,6661],{"class":3808},[3416,42974,42975],{"class":3418,"line":3437},[3416,42976,42505],{"class":3808},[3416,42978,42979],{"class":3418,"line":3444},[3416,42980,42837],{"class":3808},[3416,42982,42983],{"class":3418,"line":3450},[3416,42984,42510],{"class":3808},[3416,42986,42987],{"class":3418,"line":3456},[3416,42988,42850],{"class":3808},[3416,42990,42991],{"class":3418,"line":3462},[3416,42992,42860],{"class":3808},[3416,42994,42995],{"class":3418,"line":3468},[3416,42996,42530],{"class":3808},[3353,42998,42999],{},[3363,43000,42535,43001,32096],{},[3413,43002,43003],{},"409 Conflict",[3406,43005,43007],{"className":3780,"code":43006,"language":3782,"meta":3411,"style":3411},"{\n  \"message\": \"Конфлікт паралельного оновлення. Версія запису у базі була змінена іншим процесом.\"\n}\n",[3413,43008,43009,43013,43023],{"__ignoreMap":3411},[3416,43010,43011],{"class":3418,"line":3419},[3416,43012,3796],{"class":3795},[3416,43014,43015,43018,43020],{"class":3418,"line":3425},[3416,43016,43017],{"class":3801},"  \"message\"",[3416,43019,3805],{"class":3795},[3416,43021,43022],{"class":3808},"\"Конфлікт паралельного оновлення. Версія запису у базі була змінена іншим процесом.\"\n",[3416,43024,43025],{"class":3418,"line":3431},[3416,43026,3507],{"class":3795},[3353,43028,43029],{},"Це доводить, що механізм оптимістичного блокування успішно спрацював, і база відхилила перезапис застарілими даними!",[4584,43031,43033],{"id":43032},"д-видалення-завдання","Д. Видалення завдання",[3406,43035,43037],{"className":6316,"code":43036,"language":6318,"meta":3411,"style":3411},"curl -X DELETE http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks\u002Fuser-100\u002F7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\n",[3413,43038,43039],{"__ignoreMap":3411},[3416,43040,43041,43043,43045,43048],{"class":3418,"line":3419},[3416,43042,42453],{"class":6330},[3416,43044,42475],{"class":4368},[3416,43046,43047],{"class":3808}," DELETE",[3416,43049,43050],{"class":3808}," http:\u002F\u002Flocalhost:5000\u002Fapi\u002Ftasks\u002Fuser-100\u002F7f8b9c2d6e3f4a5b8c9d0e1f2a3b4c5d\n",[3353,43052,43053],{},[3363,43054,42535,43055,13590],{},[3413,43056,43057],{},"204 No Content",[3727,43059,43061],{"id":43060},"підсумок-модуля","Підсумок модуля",[3353,43063,43064],{},"У цьому навчальному модулі ми детально розглянули архітектурні засади, правила проектування та програмну реалізацію систем на базі Amazon DynamoDB:",[3353,43066,43067,43070],{},[3363,43068,43069],{},"Частина 1 — Основи:"," Досліджено реляційну та NoSQL парадигми, типи первинних ключів (Simple HASH проти Composite HASH+RANGE), базові CRUD операції на рівні запитів, розрахунок RCU\u002FWCU для Strongly та Eventually consistent читання та запису.",[3353,43072,43073,43076],{},[3363,43074,43075],{},"Частина 2 — Вторинні індекси:"," Порівняно архітектурні особливості LSI (Local Secondary Index) та GSI (Global Secondary Index), розібрано патерн Sparse Index для оптимізації витрат та Single-Table design.",[3353,43078,43079,43082],{},[3363,43080,43081],{},"Частина 3 — Режими керування ємністю:"," Вивчено специфіку роботи режимів Provisioned (з автоматичним масштабуванням CloudWatch Alarms) та On-Demand (PAY_PER_REQUEST), механізми Burst Capacity та експоненціальної затримки Full Jitter.",[3353,43084,43085,43088],{},[3363,43086,43087],{},"Частина 4 — Streams та Транзакції:"," Деталізовано CDC-рішення DynamoDB Streams з його Shards та інтеграцією через ESM з AWS Lambda, а також реалізацію ACID транзакцій за протоколом 2PC (Two-Phase Commit).",[3353,43090,43091,43094],{},[3363,43092,43093],{},"Частина 5 — TTL, Global Tables та Best Practices:"," Досліджено механізм автоматичного безкоштовного очищення застарілих даних за допомогою TTL, налаштування геореплікації Global Tables (Active-Active) та стратегії уникнення гарячих партицій.",[3353,43096,43097,43100],{},[3363,43098,43099],{},"Частина 6 — Інтеграція з .NET:"," Розглянуто архітектурні рівні інтеграції C# клієнтів (Low-Level, Document, Object Persistence Model), розробку CRUD репозиторіїв та обробників Streams подій у Lambda.",[8456,43102,43103,43106,43107,43110],{},[3363,43104,43105],{},"Наступний архітектурний крок:"," Для високонавантажених читанням систем (Read-Heavy workloads) розгляньте впровадження ",[3363,43108,43109],{},"DynamoDB Accelerator (DAX)"," — повністю сумісного in-memory кеш-сервісу, який знижує час відгуку до мікросекундного рівня без необхідності зміни бізнес-коду додатка.",[43112,43113,43114],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .sLwNe, html code.shiki .sLwNe{--shiki-light:#0451A5;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .sjcCO, html code.shiki .sjcCO{--shiki-light:#EE0000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .s8xlr, html code.shiki .s8xlr{--shiki-light:#AF00DB;--shiki-default:#C586C0;--shiki-dark:#C586C0}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .sKtos, html code.shiki .sKtos{--shiki-light:#800000;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .su9tN, html code.shiki .su9tN{--shiki-light:#0000FF;--shiki-default:#CE9178;--shiki-dark:#CE9178}",{"title":3411,"searchDepth":3425,"depth":3425,"links":43116},[43117,43118,43123,43128,43133,43138,43143,43144,43152,43160,43163,43171,43179,43184,43194,43203],{"id":3350,"depth":3425,"text":3351},{"id":3724,"depth":3425,"text":3725,"children":43119},[43120,43121,43122],{"id":3729,"depth":3431,"text":3730},{"id":3760,"depth":3431,"text":3761},{"id":3992,"depth":3431,"text":3993},{"id":4549,"depth":3425,"text":4550,"children":43124},[43125,43126,43127],{"id":4567,"depth":3431,"text":4568},{"id":5157,"depth":3431,"text":5158},{"id":6173,"depth":3431,"text":6174},{"id":6286,"depth":3425,"text":6287,"children":43129},[43130,43131,43132],{"id":6300,"depth":3431,"text":6301},{"id":7643,"depth":3431,"text":7644},{"id":8464,"depth":3431,"text":8465},{"id":10431,"depth":3425,"text":10432,"children":43134},[43135,43136,43137],{"id":10435,"depth":3431,"text":10436},{"id":10669,"depth":3431,"text":10670},{"id":11891,"depth":3431,"text":11892},{"id":13528,"depth":3425,"text":13529,"children":43139},[43140,43141,43142],{"id":13551,"depth":3431,"text":13541},{"id":13781,"depth":3431,"text":13545},{"id":13986,"depth":3431,"text":13987},{"id":14312,"depth":3425,"text":14313},{"id":14752,"depth":3425,"text":14753,"children":43145},[43146,43147,43148,43149,43150,43151],{"id":14768,"depth":3431,"text":14769},{"id":15005,"depth":3431,"text":15006},{"id":15055,"depth":3431,"text":15056},{"id":15128,"depth":3431,"text":15129},{"id":15245,"depth":3431,"text":15246},{"id":16150,"depth":3431,"text":16151},{"id":16675,"depth":3425,"text":16676,"children":43153},[43154,43155,43156,43157,43158,43159],{"id":16688,"depth":3431,"text":16689},{"id":16926,"depth":3431,"text":16927},{"id":17185,"depth":3431,"text":17186},{"id":18186,"depth":3431,"text":18187},{"id":18739,"depth":3431,"text":18740},{"id":18852,"depth":3431,"text":18853},{"id":19030,"depth":3425,"text":19031,"children":43161},[43162],{"id":19285,"depth":3431,"text":19286},{"id":21444,"depth":3425,"text":21445,"children":43164},[43165,43166,43167,43168,43169,43170],{"id":21622,"depth":3431,"text":21623},{"id":21830,"depth":3431,"text":21831},{"id":22028,"depth":3431,"text":22029},{"id":22093,"depth":3431,"text":22094},{"id":22193,"depth":3431,"text":22194},{"id":22363,"depth":3431,"text":22364},{"id":24031,"depth":3425,"text":24032,"children":43172},[43173,43174,43175,43176,43177,43178],{"id":24035,"depth":3431,"text":24036},{"id":24267,"depth":3431,"text":24268},{"id":24347,"depth":3431,"text":24348},{"id":24398,"depth":3431,"text":24399},{"id":25393,"depth":3431,"text":25394},{"id":25665,"depth":3431,"text":25666},{"id":27405,"depth":3425,"text":27406,"children":43180},[43181,43182,43183],{"id":27409,"depth":3431,"text":27410},{"id":28784,"depth":3431,"text":28785},{"id":29978,"depth":3431,"text":29979},{"id":30140,"depth":3425,"text":30141,"children":43185},[43186,43187,43188,43189,43190,43191,43192,43193],{"id":30156,"depth":3431,"text":30157},{"id":30417,"depth":3431,"text":30418},{"id":30981,"depth":3431,"text":30982},{"id":32401,"depth":3431,"text":32402},{"id":33375,"depth":3431,"text":33376},{"id":35003,"depth":3431,"text":35004},{"id":36024,"depth":3431,"text":36025},{"id":36965,"depth":3431,"text":36966},{"id":37102,"depth":3425,"text":37103,"children":43195},[43196,43197,43198,43199,43200,43201,43202],{"id":37124,"depth":3431,"text":37125},{"id":37211,"depth":3431,"text":37212},{"id":37509,"depth":3431,"text":37510},{"id":37623,"depth":3431,"text":37624},{"id":37841,"depth":3431,"text":37842},{"id":38000,"depth":3431,"text":38001},{"id":38146,"depth":3431,"text":38147},{"id":38222,"depth":3425,"text":38223,"children":43204},[43205,43206,43207,43208,43209,43210,43211,43212,43213,43214,43215,43216,43217,43218,43219,43220,43221,43222],{"id":38244,"depth":3431,"text":38245},{"id":38254,"depth":3431,"text":38255},{"id":38412,"depth":3431,"text":38413},{"id":38491,"depth":3431,"text":38492},{"id":38709,"depth":3431,"text":38710},{"id":38756,"depth":3431,"text":38757},{"id":38833,"depth":3431,"text":38834},{"id":39279,"depth":3431,"text":39280},{"id":39298,"depth":3431,"text":39299},{"id":39435,"depth":3431,"text":39436},{"id":40076,"depth":3431,"text":40077},{"id":40686,"depth":3431,"text":40687},{"id":40698,"depth":3431,"text":40699},{"id":40891,"depth":3431,"text":40892},{"id":41434,"depth":3431,"text":41435},{"id":41443,"depth":3431,"text":41444},{"id":42442,"depth":3431,"text":42443},{"id":43060,"depth":3431,"text":43061},"Фундаментальний посібник з Amazon DynamoDB для .NET розробників. Від моделі даних та первинних ключів до вторинних індексів, транзакцій, Streams, TTL, Global Tables та інтеграції через AWS SDK for .NET — з акцентом на проектування схем для реальних production-сценаріїв.","md",null,{},{"title":3258,"description":43223},"_OkPJylk-fRAg0Z0VUnR956rcW5u4wGD9VuEJIBh5yw",[43230,43232],{"title":3254,"path":3255,"stem":3256,"description":43231,"children":-1},"Повний посібник з Amazon RDS для .NET розробників. PostgreSQL, MySQL, SQL Server, Multi-AZ, Read Replicas, Aurora, RDS Proxy, підключення через Entity Framework Core та Code-First міграції.",{"title":3262,"path":3263,"stem":3264,"description":43233,"children":-1},"Глибоке дослідження AWS Lambda — від фундаментальних принципів serverless архітектури до продакшн-оптимізації .NET функцій. Runtimes, Layers, Triggers, Cold Start, Provisioned Concurrency, Lambda Destinations та повна інтеграція з екосистемою AWS для .NET 10 розробників.",1782371306432]