برنامه نویسی

یک الگوی جدید برای مستندسازی الگوهای دسترسی DynamoDB

این پست وبلاگ راهی برای مستندسازی الگوهای دسترسی برای DynamoDB در قالب JSON برای به‌روزرسانی و استفاده آسان در NodeJS lambdas معرفی و بررسی می‌کند. من این سازه را ندیده ام که استفاده شده باشد، اما اگر آن بیرون وجود دارد و من آن را از دست دادم، دوست دارم در مورد آن صحبت کنم!

همانطور که من این را در آخرین روز سال 2024 می نویسم، امیدوارم کسانی که می خوانند سال جدید خوبی داشته باشند (یا داشته اند)!

من سال هاست که با DynamoDB کار می کنم. وقتی صحبت از DynamoDB و استفاده از آن برای موفقیت بیشتر می‌شود، به نظر می‌رسد همیشه چیزهای بیشتری برای یادگیری وجود دارد، همیشه چیزهای بیشتری برای بهبود وجود دارد. من نمی توانم افرادی مانند الکس دبری، ریک هولیهان، خواجه شمس و پیت نایلور را به خاطر به اشتراک گذاشتن دانش خود در طول سال ها از طریق پست های وبلاگ، ارائه ها، کتاب ها، چت ها و گفتگوهای حضوری تحسین کنم.

هرکسی که با DynamoDB از طریق مواد فوق‌العاده‌ای که قبلاً وجود دارد آشنا شده باشد، احتمالاً در مورد پتن‌های دسترسی می‌داند. الگوهای دسترسی راهی است که ما برای دسترسی به داده ها نیاز داریم و به شدت بر نحوه ساختار داده ها و ذخیره آنها برای عملیات خواندن و نوشتن تأثیر می گذارد. اگر محتوایی را در این فرآیند دیده‌اید، احتمالاً صفحات گسترده مدل‌سازی داده‌های DynamoDB آن الگوهای دسترسی را می‌شناسید. من سفر DynamoDB خود را با استفاده از صفحات گسترده برای مدل‌سازی داده‌هایم شروع کردم، اما در عوض به سمت JSON حرکت کردم زیرا حرکت بین کد و مدل‌سازی برای من آسان‌تر بود. همچنین اصلاح الگوهای دسترسی و جابجایی چیزها در صورتی که در قالب JSON به جای صفحات گسترده بود، بسیار آسان تر بود. من این مدل‌سازی سبک JSON را برای جایگزینی یا حمایت نکردن از صفحه‌گسترده‌ها به اشتراک نمی‌گذارم، اما به نظرم برای من بهتر کار می‌کند، بنابراین فکر کردم به اشتراک بگذارم و ببینم آیا با سبک آنها و نظر دیگران در مورد موضوع مطابقت دارد یا خیر. من عاشق به اشتراک گذاشتن دانش در مورد استفاده از فناوری هستم و این با آن مطابقت دارد. فکر نمی‌کنم بتوانم محتوای جدیدی ایجاد کنم که با محتوای کوهستانی در مورد الگوهای دسترسی و نحوه ایجاد آنها مقایسه شود، بنابراین مجموعه‌ای از سطح را بیان می‌کنم و می‌گویم که این پست وبلاگ برای کسانی است که درک خوبی از الگوهای دسترسی دارند. قبلا و نحوه مدلسازی در DynamoDB.

بدون هیچ مقدمه ای وارد محتوای اصلی شوید.

ابتدا باید داده هایی برای مدل سازی داشته باشیم. من در این مورد رفتم و برگشتم، اما فکر می‌کنم یک شرکت اجاره کایاک در سراسر کشور ممکن است برای مدل‌سازی الگوهای دسترسی و نمایش روش مستندسازی آن‌ها در JSON، برنده‌های آسانی به ما بدهد.

توضیحات تصویر

بیایید فرض کنیم که تقریباً در تمام ایالات ایالات متحده آمریکا یک مکان اجاره کایاک وجود دارد، ما آن را 40 می نامیم. هر مکان یک آدرس خواهد داشت. بیایید فرض کنیم این آدرس ها در طول زمان ثابت هستند و تغییر نخواهند کرد. هر مکان به طور متوسط ​​5 کارمند خواهد داشت، هر کارمند دارای عنوان شغلی و پاداش، نام و آدرس و جزئیات دیگری است که در حال حاضر نگران آنها نخواهیم بود. کارمندان مردم هستند و افراد احتمالاً جابه‌جا می‌شوند، بنابراین آدرس احتمالاً در طول زمان تغییر می‌کند. هر فروشگاه دارای موجودی است که روز به روز تغییر می کند. هر فروشگاه دارای سوابق اجاره است. مشتریانی هستند و در حال حاضر چه اجاره هایی دارند. ما می‌توانیم به چیزهای بیشتری وارد شویم که برای اجرای حق‌انچایز اجاره‌ای کایاک لازم است، اما بیایید در اینجا متوقف شویم زیرا این به ما بیش از اندازه کافی می‌دهد تا از داده‌هایمان سؤال بپرسیم، و بنابراین می‌توانیم الگوهای دسترسی خود را تعریف کنیم. .

من ترجیح می‌دهم سؤالات الگوی دسترسی تا حد امکان به مدل‌سازی داده‌ها نزدیک باشد تا همه چیز گسترده و یافتن آن سخت نباشد. برای این قسمت بعدی به JSON تغییر می‌دهم و محتوا را در آنجا پیاده‌سازی می‌کنم:

{
    "Access Patterns": [
        "get the location of all rental stores",
        "get the inventory of a store",
        "get the current employees of a store",
        "get all employees who have worked at a store",
        "get all stores an employee has worked at",
        "get all rentals a customer has out",
        "get customer rental history for a location",
        "get customer rental history for all locations"
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای این پست وبلاگ، من فکر نمی کنم ما از همه چیز عبور کنیم. بیایید چند موضوع را انتخاب کنیم و مدل سازی را شروع کنیم! ابتدا، بیایید در مورد طراحی جدول تک صحبت کنیم: جایی که همه موارد ما در یک جدول DynamoDB قرار دارند. این بدان معنی است که ما باید مدل سازی داده ها را به گونه ای پیگیری کنیم که همه موارد ما بتوانند همزمان وجود داشته باشند و تضاد نداشته باشند. دقیق بودن در مستندسازی الگوهای دسترسی و مدل‌های داده برای اطمینان از اینکه کارها به خوبی کار می‌کنند، کلیدی است. الگوهای دسترسی که ما تعریف کرده‌ایم نیاز به معرفی مختصری از کاردینالیته دارند. مدل‌سازی سنتی داده‌های DynamoDB در ایجاد الگوهایی برای داده‌ها با روابط 1:1، many:1 و many: many بسیار خوب است، با توجه به اینکه در روابط many: many، هر جفت از موارد فقط یک بار اتفاق می‌افتد. مجموعه‌های آیتم مدل 1:1، many:1، و many(1):(1)به خوبی روابط دارند، و چیزهای زیادی در آن وجود دارد. روابطی که می‌توانید در آن‌ها (1..n): (1..m) موقعیت‌های زیادی داشته باشید، که در آن هر مورد می‌تواند تعداد زیادی رابطه با هر آیتم دیگری 1 یا چندین بار داشته باشد، مدل‌سازی با مجموعه‌های آیتم‌ها واقعاً سخت است، بارگذاری بیش از حد فهرست ، یا شاخص های ثانویه جهانی روی آیتم های منفرد. این در حال وارد شدن به موقعیت‌های پیچیده‌ای است که می‌توان درباره آن به طور انتزاعی صحبت کرد، بنابراین بیایید یک مثال در دنیای واقعی ارائه دهیم: یک کارمند 20 سال برای شرکت کار کرده است. آنها تقریباً سالی یک بار به مکان دیگری نقل مکان کرده اند، با 10 مکان مختلف از طریق تبلیغات یا جابجایی های جانبی از طریق شرکت، و چند بار در همان مکان ها کار کرده اند. بگویید آنها در مکان “A” 5 بار مختلف کار کرده اند. وضعیت دیگر، این است که یک کارمند ممکن است در مکانی زندگی کند که نزدیک به 2 فروشگاه است و ممکن است همزمان در هر دو کار کند. زمانی که نیاز دارید آن رابطه را بیش از یک بار تعریف کنید، این مشکل ایجاد می کند. استفاده از PK/SK معکوس (SK به عنوان کلید پارتیشن و PK به عنوان کلید مرتب سازی در فهرست ثانویه جهانی) می تواند برای بسیاری از روابط (1):(1) به خوبی کار کند. من برای بسیاری از موقعیت ها (1..n):(1..m) با آنها مشکل داشته ام و به الگوهای دیگر رفته ام. برای این، من متوجه شدم که نمودارهای Materialized بسیار عالی هستند
الگویی برای استفاده که چیزها را عمومی و قابل درک نگه می دارد و برای پرس و جو قدرتمند است. در «کتاب DynamoDB» الکس دبری، او بخشی در مورد نمودارهای متریال شده دارد، و اگر قبلاً این کار را نکرده اید، به شدت توصیه می کنم آن را بررسی کنید. برای مدل‌سازی امروز، از آن‌ها برای برخی موقعیت‌ها استفاده می‌کنیم، و به مجموعه‌های اقلام سنتی و بارگذاری بیش از حد فهرست برای دیگران نگاه می‌کنیم.

مدت ها پیش تصمیم گرفتم شاخص ها و کلیدها را عمومی نگه دارم. این امر برخی از الگوهای دسترسی را که کاملاً معتبر هستند قطع می‌کند، اما همچنین به من اجازه می‌دهد تا یکبار موارد را تنظیم کنم و بدون نیاز به انجام مجدد کارها یا اضافه کردن سفارشی‌سازی‌ها و نگرانی در مورد تأثیر آنها بر مدل‌سازی داده‌های قبلی، در آن مسیر ادامه دهم. بنابراین، من فهرست اولیه (آنچه به طور منحصربه‌فرد هر مورد را مشخص می‌کند) دارم که از “PK” به عنوان رشته کلید پارتیشن و “SK” به عنوان رشته کلید مرتب‌سازی استفاده می‌کند. من از نمایه های ثانویه محلی استفاده نمی کنم. من جداول خود را طوری تنظیم کردم که با 6 شاخص جهانی ثانویه شروع شود، زیرا این به طور کلی 1 GSI بیشتر از چیزی است که در بیشتر پروژه ها با رشد آنها نیاز داشتم. هر فهرست ثانویه جهانی برای استفاده از PK{x} و SK{x} به عنوان کلیدهای پارتیشن و مرتب‌سازی تنظیم شده است. از آنجایی که شاخص‌های ثانویه جهانی پراکنده هستند و تنها در صورتی پر می‌شوند که مورد حاوی PK{x} و SK{x} باشد، می‌توانم این موارد را در ابتدا اضافه کنم و از نظر عملکرد یا هزینه در شروع کار جریمه نخواهم شد، و در آنجا خواهند بود. وقتی به آنها نیاز دارم از آنجایی که من شاخص‌های جهانی ثانویه را بیش از حد بارگذاری می‌کنم، فیلدهای خاصی را در هر کدام پروژه نمی‌دهم، از پیش‌فرض تمام فیلدهایی که در جدول سایه‌ای شاخص ثانویه جهانی پیش‌بینی می‌شوند استفاده می‌کنم.

بسیار خوب، اکنون که آن دو پاراگراف توضیحات اولیه و تنظیم سطح را در اختیار داریم، بیایید مدل سازی برخی از موجودیت های اساسی را شروع کنیم.

{
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata"
                }
            }
        }
    ],
    "person": [
        {
            "PK": "${version}#person#personULID#${personULID}",
            "SK": {
                "metadata": {
                    "entityType": "personMetadata"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا ما فروشگاه و شخص داریم. من تصمیم گرفتم با شخص به عنوان یک موجودیت همراه شوم زیرا ما کارمندان داریم و مشتریان داریم، بنابراین این به ما امکان می دهد هر دو را مدل کنیم. ممکن است در این مورد بمانیم یا نمانیم، اما برای شروع، این تصمیمی است که من می توانم از آن حمایت کنم. من همچنین از ULID استفاده خواهم کرد. ULIDS مانند UUID ها هستند، اما زمان را به گونه ای در بر می گیرند تا بر اساس زمان ایجاد آنها قابل مرتب سازی باشند.

برای هر PK، من عادت کرده ام که نسخه ای را اضافه کنم، در صورتی که در آینده نیاز به تغییر به نسخه جدیدی از داده ها در حین کار با داده های قدیمی داشته باشم. من هنوز واقعاً به این نیاز ندارم، اما آن را حفظ کردم. موقعیت‌هایی وجود دارد که می‌توانید در نسخه مدل‌سازی کنید تا آخرین آیتم‌ها را در حین به‌روزرسانی نگه‌دارید و تغییرات را در هر یک از آن‌ها با تغییر نسخه در پرواز به دست آورید، اما من در اینجا به آن نمی‌پردازم.

برای هر دسته یا اغلب موجودیت ها، یک مدخل در فرهنگ لغت یا شیء JSON با عنوان ایجاد می کنم. این می‌تواند چیزی باشد که می‌توانیم به آن اشاره کنیم، اما در مورد نام‌گذاری خیلی سخت‌گیرانه نیست و اگر چیز دیگری منطقی‌تر باشد، می‌تواند به دلخواه تغییر کند. برای هر دسته از اقلام (به عنوان مثال فروشگاه و شخص) من آرایه ای از اشیاء دارم که یک PK و حداقل یک SK هستند. PK یک رشته است، SK یک فرهنگ لغت است، با هر الگوی SK منحصر به فرد به عنوان کلید. در حال حاضر، فقط دو الگوی جفت منحصر به فرد PK/SK وجود دارد، اما ما بیشتر خواهیم ساخت. هر الگوی جفت PK/SK منحصربه‌فرد یک موجودیت است و ما فیلد “entityType” را داریم تا یک نام موجودیت منحصر به فرد به آن بدهیم. در یک مقطع زمانی پرس‌و‌جوها را انجام می‌دادم، PK و SK را تجزیه می‌کردم و از منطق استفاده می‌کردم تا بفهمم کدام موجودیت است. این به خوبی کار می‌کرد، اما انجام آن بسیار گیج‌کننده بود، کدهای دیگ بخار زیادی داشت، و اگر با موارد موجود در کنسول وب AWS DynamoDB، بدون کمک این توابع کمکی کار می‌کردید، کمک چندانی نمی‌کرد. بنابراین، من به این قانون تغییر دادم که همه موارد در جدول DynamoDB دارای یک نوع نهاد هستند. ما اکنون یک موجودیت storeMetadata و همچنین یک نهاد personMetadata داریم.

در مرحله بعد، بیایید کارمندان را اضافه کنیم.

{
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata"
                },
                "employee#metadata#personULID#${personULID}":{
                    "entityType": "storeEmployee"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا ما از personULID استفاده می‌کنیم، و آن را با چند فیلد مانند نام و شناسه پر می‌کنیم، چیزهایی که اغلب تغییر نمی‌کنند (و زمانی که تغییر می‌کنند، به‌روزرسانی سریع است). این مورد را با استخدام کارمندان اضافه می کنیم و اگر دیگر در فروشگاه کار نمی کنند آنها را حذف می کنیم.

بعد بیایید موجودی را اضافه کنیم. بسیار شبیه به کارمندان است، اما ما جلوتر می رویم و ضربه می زنیم و تمام ابرداده ها را برای هر آیتم، حتی اگر تکراری، برای هر آیتم موجودی در اختیار داریم. بعداً می‌توانیم اینها را به افرادی مانند افراد خاص خود منتقل کنیم، اما در حال حاضر برای یک شرکت اجاره‌ای، ردیابی جزئیات هر کدام و داشتن جزئیات تکراری مزایایی دارد. که قبلاً به مدت 11 سال در خرده‌فروشی کار کرده‌ام، می‌توانم به شما بگویم که حتی با محصولات خاص، اغلب تنوع‌های بی‌شماری از آن وجود دارد که جستجوی واحد برای کالایی را که تکرار را حذف می‌کند، گاهی اوقات بی‌فایده می‌سازد.

{
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata"
                },
                "employee#metadata#personULID#${personULID}":{
                    "entityType": "storeEmployee"
                },
                "inventory#metadata#inventoryULID#${inventoryULID}":{
                    "entityType": "storeInventoryItem"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بیایید الگوهای دسترسی را بررسی کنیم و ببینیم مدل فعلی چگونه مطابقت دارد و مدل از چه جستارهایی پشتیبانی می کند. تا اینجا 2 از 8 است: “موجودی یک فروشگاه را دریافت کنید” و “کارمندان فعلی یک فروشگاه را دریافت کنید”. برای دریافت موجودی یک فروشگاه، می توانیم PK را پرس و جو کنیم "${version}#store#storeULID#${storeULID}" و برای SK که انجام می دهیم SK با آن شروع می شود "inventory#metadata#inventoryULID#". برای این پرس و جو به نسخه و storeULID نیاز داریم. پرس و جو بسیار مشابه برای کارمندان فعلی یک فروشگاه: PK "${version}#store#storeULID#${storeULID}" و SK با شروع می شود "employee#metadata#personULID#".

اکنون، بیایید از یک شاخص جهانی ثانویه (GSI) برای گرفتن همه فروشگاه ها استفاده کنیم. با افزودن PK1 و SK1 به storeMetadata، می‌توانیم توسط PK1 در نمایه GSI1 پرس و جو کنیم و همه فروشگاه‌ها را در اختیار ما قرار دهد. اینجاست که JSON واقعاً شروع به درخشش در صفحات گسترده برای سبک من می کند. هر موجودیت مختلف دارای شاخص‌های ثانویه جهانی است که به صراحت تعریف می‌شوند، همانطور که ممکن است در DynamoDB با نمای JSON ظاهر شوند (الگو). برای من، دیدن اینکه داده‌های خام چگونه به نظر می‌رسند را بسیار آسان می‌کند، و ما می‌توانیم بسیاری از قسمت‌ها را در صورت نیاز کپی و در کد خود جایگذاری کنیم. اغلب، می‌توانیم رشته‌های الگو را همانطور که هست بچسبانیم، و متغیرهایی را که آنها استفاده می‌کنند، تعریف کنیم، مثلاً «storeULID#${storeULID}» تبدیل شود. storeULID#${storeULID} و فقط باید متغیر storeULID برای تکمیل رشته وجود داشته باشد. توجه داشته باشید که اکنون فقط موجودیت فراداده دارای مقادیر GSI1 است. کارمند و موجودی ندارند.

{
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata",
                    "PK1": "${version}#stores",
                    "SK1": "storeULID#${storeULID}",
                    "_commentGSI1": "GSI to grab all the stores at once."
                },
                "employee#metadata#personULID#${personULID}":{
                    "entityType": "storeEmployee"
                },
                "inventory#metadata#inventoryULID#${inventoryULID}":{
                    "entityType": "storeInventoryItem"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حال بیایید به این بپردازیم که چگونه می‌توانیم مسئله many(1..n):(1..m) many را با الگوی گراف مادی شده حل کنیم. در این الگو، یال‌هایی بین گره‌ها یا یک آیتم رابطه در پایگاه داده ایجاد می‌کنیم که به هر دو مورد اشاره می‌کند و می‌تواند برخی از ویژگی‌ها را روی آن داشته باشد. گره‌ها مواردی هستند که ما می‌خواهیم با هم مرتبط کنیم، مثلاً یک فرد و شغل، و لبه‌ها همان رابطه هستند، مثلاً شخص A که در شرکت B کار می‌کرد. این الگو با استفاده از یک جفت شاخص ثانویه جهانی تنظیم می‌شود که در آن هر یک به شما امکان می‌دهد پرس و جو کنید معکوس دیگر شاخص ثانویه جهانی. بیایید ببینیم که چگونه این ممکن است با یک گروه بندی روابط تنظیم شود.

{
    "relationships": [
        {
            "PK": "${version}#employment#employmentULID#${employmentULID}",
            "SK": {
                "metadata": {
                    "entityType": "employmentRelationship",
                    "PK2": "${version}#employment#${xULID}",
                    "SK2": "${version}#employment#${yULID}",
                    "_commentGSI2": "Can query by xULID, and get all employment for x. Company location is x, person is y",
                    "PK3": "${version}#employment#${yULID}",
                    "SK3": "${version}#employment#${xULID}",
                    "_commentGSI3": "Can query by yULID, and get all employment for y, Company location is x, person is y"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بخش کلیدی این 2 شاخص ثانویه جهانی 2 و 3 است. هر کدام یک نسخه برگردانده شده از خود هستند. ما می‌توانیم اینها را در یک شاخص جهانی ثانویه خاص قرار دهیم که فقط آنها را با ما عوض می‌کند، اما می‌دانم تا زمانی که به مقیاس بزرگ نرسید، این الگو خوب است. ما تعریف می کنیم که در روابط کاری، x محل شرکت و y فرد خواهد بود. هر زمان که شخصی شروع به کار در یک مکان اجاره کایاک می کند، یکی از این موارد ایجاد می شود. این مورد همچنین می‌تواند شامل زمینه‌های زیادی مانند موقعیت شغلی، حقوق، محدوده تاریخ استخدام و غیره باشد. در حال حاضر نگران پر کردن آن‌ها نخواهیم بود. با این حال، از آنجا که ما از ULID استفاده می کنیم، می توانیم آنها را مرتب کنیم و بدانیم که یک کارمند در یک مکان در مقایسه با مکان های دیگر چه زمانی شروع به کار کرده است، یا برعکس اگر بخواهیم ترتیب کلی زمان استخدام کارکنان یک مکان را بدانیم.

اکنون که این الگوی گراف متریال شده را داریم، می‌توانیم تعدادی پرس‌وجو بسازیم تا الگوهای دسترسی بیشتری را برآورده کنیم. "get all employees who have worked at a store" ما در GSI2 ​​با PK2 پرس و جو می کنیم "${version}#employment#${xULID}" با xULID که محل فروشگاه است. این همه سوابق استخدامی آن فروشگاه را به ما می دهد. می‌توانیم فیلدها را از شخص کپی کنیم و روی شی رابطه ذخیره کنیم، چیزهایی که احتمالاً تغییر چندانی نخواهند کرد، و این می‌تواند پایان کار باشد. گزینه دیگر این است که نتایج را مرور می کنیم و برای هر فرد یک پرس و جو انجام می دهیم تا اطلاعات کامل خود را دریافت کنیم. این می تواند در مقیاس گران باشد، اما هنوز هم بسیار کارآمد است و مقیاس پذیر است. با DynamoDB همچنین می‌توانید درخواست‌های متعددی را به صورت موازی برای بازگرداندن داده‌ها به آن ارسال کنید، بنابراین گزینه‌های ما در اینجا باز هستند. "get all stores an employee has worked at" ما دقیقاً مانند فروشگاه ها عمل می کنیم، اما از GSI3 با PK3 استفاده می کنیم "${version}#employment#${yULID}" که در آن yULID شخص ULID است. با این یکی، ما همچنین می‌توانیم فقط از همه فروشگاه‌ها پرس و جو کنیم و سپس آنها را به صورت محلی بفرستیم تا جستجوها را انجام دهند و نیاز به ایجاد بیش از 40 پرس و جو برای دریافت اطلاعات هر فروشگاه را دور بزنیم.

ما 5 مورد از 8 الگوی دسترسی را برآورده کرده ایم. اکنون به فاکتورهای اجاره و تاریخچه می پردازیم. ما اساساً روابط استخدامی را تکرار می کنیم و آن را برای رفع نیازهای اجاره تغییر می دهیم. همچنین به مجموعه‌های اقلام فروشگاه، جایی که اجاره‌های فعلی نگهداری می‌شوند، باز خواهیم گشت. ابتدا، در اینجا به‌روزرسانی مجموعه اقلام فروشگاه است.

{
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata",
                    "PK1": "${version}#stores",
                    "SK1": "storeULID#${storeULID}",
                    "_commentGSI1": "GSI to grab all the stores at once."
                },
                "employee#metadata#personULID#${personULID}":{
                    "entityType": "storeEmployee"
                },
                "inventory#metadata#inventoryULID#${inventoryULID}":{
                    "entityType": "storeInventoryItem"
                },
                "activeRentals#personULID#${personULID}#inventoryULID#${inventoryULID}":{
                    "entityType": "storeActiveRental"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر بار که شخصی یک کایاک اجاره می‌کند، سیستم یک رکورد با یک PK از “${version}#store#storeULID#${storeULID}” و یک SK از “activeRentals#personULID#${personULID}#inventoryULID#$ ایجاد می‌کند. {inventoryULID}”. این به ما امکان می‌دهد با PK پرس و جو کنیم و SK با “activeRentals#personULID#${personULID}#inventoryULID#” شروع می‌شود تا همه اجاره‌هایی را که یک فرد دارد، مشاهده کنیم و الگوی دسترسی ما را برآورده کنیم. اما صبر کنید، این فقط برای یک مکان است؟ ما باید برای همه مکان‌ها بدانیم، زیرا مکان یکی از الزامات الگوی دسترسی نیست. این را می توانیم با GSI حل کنیم. برای ساختن آن از GSI4 در همان مورد استفاده می‌کنیم تا بتوانیم در همه مکان‌ها پرس و جو کنیم.

{
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata",
                    "PK1": "${version}#stores",
                    "SK1": "storeULID#${storeULID}",
                    "_commentGSI1": "GSI to grab all the stores at once."
                },
                "employee#metadata#personULID#${personULID}":{
                    "entityType": "storeEmployee"
                },
                "inventory#metadata#inventoryULID#${inventoryULID}":{
                    "entityType": "storeInventoryItem"
                },
                "activeRentals#personULID#${personULID}#inventoryULID#${inventoryULID}":{
                    "entityType": "storeActiveRental",
                    "PK4": "${version}#activeRentals#personULID#${personULID}",
                    "SK4": "inventoryULID#${inventoryULID}",
                    "_commentGSI4": "GSI for looking up all rentals across all locations a person has out."
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون به یاد داشته باشید، می‌توانیم شروع به بارگذاری بیش از حد هر شاخص ثانویه جهانی کنیم و تا زمانی که مقادیر منحصربه‌فرد جدا هستند و به هر دو در یک موجودیت نیازی نداریم، از آنها برای موارد مختلف استفاده کنیم. من دوست دارم این کار را شروع کنم، اما به طور کلی الگوهای دسترسی کافی را دارم که با رفتن به 6 شاخص جهانی ثانویه و عدم استفاده مجدد از هر یک، ارضا می‌شوم.

تنها چیزی که در الگوهای دسترسی اولیه ما باقی مانده است، تنظیم تاریخچه اجاره است. ما دوباره می‌توانیم از الگوی نمودار مادی‌شده برای برآورده کردن آن استفاده کنیم. شخصی در یک مکان ممکن است همان کایاک را بارها در طول سالها اجاره کند. آن کایاک به طور بالقوه می تواند به مکان دیگری نیز منتقل شود و فرد آنقدر آن را دوست دارد که برای اجاره آن به آنجا رانندگی می کند. بیش از یک نفر می‌توانند یک کایاک را اجاره کنند، اگرچه نه در یک زمان، بنابراین ما رابطه‌ی چند به چند خود را داریم، با یک کاردینالیتی در دو طرف 0 (ورودی پایگاه داده با 0 ایجاد نمی‌شود) تا n. بازگشت به سوابق اجاره و الگوهای دسترسی، می‌توانیم از این برای مدیریت آن استفاده کنیم:

{
    "relationships": [
        {
            "PK": "${version}#rental#rentalULID#${rentalULID}",
            "SK": {
                "metadata": {
                    "entityType": "rentalRelationship",
                    "PK2": "${version}#rentalLocationPerson#${xULID}",
                    "SK2": "${version}#rentalPersonLocation#${yULID}",
                    "_commentGSI2": "Can query by xULID, and get all rental for x. Company location is x, person is y",
                    "PK3": "${version}#rentalPersonLocation#${yULID}",
                    "SK3": "${version}#rentalLocationPerson#${xULID}",
                    "_commentGSI3": "Can query by yULID, and get all rental for y, Company location is x, person is y",
                    "PK5": "${version}#rentalInventoryPerson#${xULID}",
                    "SK5": "${version}#rentalPersonInventory#${yULID}",
                    "_commentGSI5": "Can query by xULID, and get all rental for x. Inventory is x, person is y",
                    "PK6": "${version}#rentalPersonInventory#${yULID}",
                    "SK6": "${version}#rentalInventoryPerson#${xULID}",
                    "_commentGSI6": "Can query by yULID, and get all rental for y, Inventory is x, person is y"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در این مورد، ما دو شاخص جهانی ثانویه دیگر اضافه کرده‌ایم تا مجموعه دوم روابط را در یک تراکنش اجاره‌ای انجام دهیم، این به ما امکان می‌دهد یک شخص، یک مکان شرکت و موجودی در حال اجاره را پیوند دهیم.

بیایید جلو برویم و تعریف کنیم که پرس‌وجوها برای 2 الگوی دسترسی آخر شناسایی شده چه خواهد بود. "get customer rental history for a location" را می توان با پرس و جو در شاخص جهانی ثانویه 3، PK3 ارضا کرد "${version}#rentalPersonLocation#${yULID}" و SK3 "${version}#rentalLocationPerson#${xULID}" جایی که yULID شخص است و xULID مکان شرکت است. "get customer rental history for all locations" ما به سادگی استراتژی خود را به استفاده از PK3 تغییر می دهیم "${version}#rentalPersonLocation#${yULID}" که در آن yULID شخص است و تمام اجاره‌های یک شخص برای همه مکان‌ها را برمی‌گرداند.

در پایان، در اینجا تمام JSON با هم جمع شده است:

{
    "Access Patterns": [
        "get the location of all rental stores",
        "get the inventory of a store",
        "get the current employees of a store",
        "get all employees who have worked at a store",
        "get all stores an employee has worked at",
        "get all rentals a customer has out",
        "get customer rental history for a location",
        "get customer rental history for all locations"
    ],
    "store": [
        {
            "PK": "${version}#store#storeULID#${storeULID}",
            "SK": {
                "metadata": {
                    "entityType": "storeMetadata",
                    "PK1": "${version}#stores",
                    "SK1": "storeULID#${storeULID}",
                    "_commentGSI1": "GSI to grab all the stores at once."
                },
                "employee#metadata#personULID#${personULID}":{
                    "entityType": "storeEmployee"
                },
                "inventory#metadata#inventoryULID#${inventoryULID}":{
                    "entityType": "storeInventoryItem"
                },
                "activeRentals#personULID#${personULID}#inventoryULID#${inventoryULID}":{
                    "entityType": "storeActiveRental",
                    "PK4": "${version}#activeRentals#personULID#${personULID}",
                    "SK4": "inventoryULID#${inventoryULID}",
                    "_commentGSI4": "GSI for looking up all rentals across all locations a person has out."
                }
            }
        }
    ],
    "person": [
        {
            "PK": "${version}#person#personULID#${personULID}",
            "SK": {
                "metadata": {
                    "entityType": "personMetadata"
                }
            }
        }
    ],
    "relationships": [
        {
            "PK": "${version}#employment#employmentULID#${employmentULID}",
            "SK": {
                "metadata": {
                    "entityType": "employmentRelationship",
                    "PK2": "${version}#employment#${xULID}",
                    "SK2": "${version}#employment#${yULID}",
                    "_commentGSI2": "Can query by xULID, and get all employment for x. Company location is x, person is y",
                    "PK3": "${version}#employment#${yULID}",
                    "SK3": "${version}#employment#${xULID}",
                    "_commentGSI3": "Can query by yULID, and get all employment for y, Company location is x, person is y"
                }
            }
        },
        {
            "PK": "${version}#rental#rentalULID#${rentalULID}",
            "SK": {
                "metadata": {
                    "entityType": "rentalRelationship",
                    "PK2": "${version}#rentalLocationPerson#${xULID}",
                    "SK2": "${version}#rentalPersonLocation#${yULID}",
                    "_commentGSI2": "Can query by xULID, and get all rental for x. Company location is x, person is y",
                    "PK3": "${version}#rentalPersonLocation#${yULID}",
                    "SK3": "${version}#rentalLocationPerson#${xULID}",
                    "_commentGSI3": "Can query by yULID, and get all rental for y, Company location is x, person is y",
                    "PK5": "${version}#rentalInventoryPerson#${xULID}",
                    "SK5": "${version}#rentalPersonInventory#${yULID}",
                    "_commentGSI5": "Can query by xULID, and get all rental for x. Inventory is x, person is y",
                    "PK6": "${version}#rentalPersonInventory#${yULID}",
                    "SK6": "${version}#rentalInventoryPerson#${xULID}",
                    "_commentGSI6": "Can query by yULID, and get all rental for y, Inventory is x, person is y"
                }
            }
        }
    ]
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چیزهای بیشتری وجود دارد که می‌توانیم مدل‌سازی کنیم، و مطمئناً می‌توانیم برخی از این‌ها را بهتر الگوسازی کنیم، اما امسال سال نو میلادی است، و من برای انتشار این مطلب در سال 2024، همانطور که به خودم قول داده بودم، فرصت ندارم. آنچه را که می‌خواستم در مورد قرار دادن الگوهای دسترسی در قالب JSON به اشتراک بگذارم، به اشتراک گذاشتم، و امیدوارم مزایای انجام آن به این شکل دیده شود. به نظرم بهترین روش برای من است، اما ادعا نمی‌کنم که بهترین راه است. ساختار فعلی هنوز فاقد برخی از الگوهای ممکن (و رایج) است، به طوری که در صورت تمایل می توان آنها را بهبود بخشید. این ساختار همانطور که در 7 سال گذشته تکامل یافته به خوبی به من خدمت کرده است و برای من بسیار خوب کار می کند! امیدوارم کسانی که تا اینجای کار در این پست به آن رسیده‌اند، از نمونه دیگری از ارزیابی یک پروژه، تولید الگوهای دسترسی مورد نیاز، و پیاده‌سازی آن‌ها در پیاده‌سازی‌های آماده DynamoDB بتن قدردانی کرده باشند.

توضیحات تصویر

لطفاً با خیال راحت با من در لینکدین ارتباط برقرار کنید، یا به اختلاف اعتقاد به سرور بدون سرور بپیوندید، جایی که بیش از 1000 علاقه‌مند به سرور بدون سرور وجود دارد، از چند روز قبل تا افرادی که به معنای واقعی کلمه در این زمینه کتاب را نوشته‌اند.

سال نو مبارک!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا