Shopping Mall directory
Lets look at the needs of application used to manage Shopping Mall properties. The application assists employees in the day-to-day operations of multiple Shopping Malls.
Requirements
- As a Maintenance Worker, I need to know which stores are currently in each Mall down to the Building they are located.
- As a Helpdesk Employee, I need to locate related stores in Mall locations by Store Category.
- As a Property Manager, I need to identify upcoming leases in need of renewal.
Example Setup
Example Setup
Table Definition
{ "TableName": "electro", "KeySchema":[ { "AttributeName":"pk", "KeyType":"HASH" }, { "AttributeName":"sk", "KeyType":"RANGE" } ], "AttributeDefinitions":[ { "AttributeName":"pk", "AttributeType":"S" }, { "AttributeName":"sk", "AttributeType":"S" }, { "AttributeName":"gsi1pk", "AttributeType":"S" }, { "AttributeName":"gsi1sk", "AttributeType":"S" } ], "GlobalSecondaryIndexes":[ { "IndexName":"gsi1pk-gsi1sk-index", "KeySchema":[ { "AttributeName":"gsi1pk", "KeyType":"HASH" }, { "AttributeName":"gsi1sk", "KeyType":"RANGE" } ], "Projection":{ "ProjectionType":"ALL" } } ], "BillingMode":"PAY_PER_REQUEST" }
(Example code on this page that references the entityExample Entity
import DynamoDB from "aws-sdk/clients/dynamodb"; import { Entity } from 'electrodb'; const client = new DynamoDB.DocumentClient(); const table = 'electro'; const StoreLocations = new Entity({ model: { service: "MallStoreDirectory", entity: "MallStore", version: "1", }, attributes: { cityId: { type: "string", required: true, }, mallId: { type: "string", required: true, }, storeId: { type: "string", required: true, }, buildingId: { type: "string", required: true, }, unitId: { type: "string", required: true, }, category: { type: [ "spite store", "food/coffee", "food/meal", "clothing", "electronics", "department", "misc" ], required: true }, leaseEndDate: { type: "string", required: true }, rent: { type: "string", required: true, validate: /^(\d+\.\d{2})$/ }, discount: { type: "string", required: false, default: "0.00", validate: /^(\d+\.\d{2})$/ } }, indexes: { stores: { pk: { field: "pk", composite: ["cityId", "mallId"] }, sk: { field: "sk", composite: ["buildingId", "storeId"] } }, units: { index: "gis1pk-gsi1sk-index", pk: { field: "gis1pk", composite: ["mallId"] }, sk: { field: "gsi1sk", composite: ["buildingId", "unitId"] } }, leases: { index: "gis2pk-gsi2sk-index", pk: { field: "gis2pk", composite: ["storeId"] }, sk: { field: "gsi2sk", composite: ["leaseEndDate"] } } } }, {table, client});
StoreLocations
uses the following Entity and Table Definition found below)
Mutations
Add a new Store to the Mall
await StoreLocations.create({
mallId: "EastPointe",
storeId: "LatteLarrys",
buildingId: "BuildingA1",
unitId: "B47",
category: "spite store",
leaseEndDate: "2020-02-29",
rent: "5000.00",
}).go();
Returns the following:
{
"data": {
"mallId": "EastPointe",
"storeId": "LatteLarrys",
"buildingId": "BuildingA1",
"unitId": "B47",
"category": "spite store",
"leaseEndDate": "2020-02-29",
"rent": "5000.00",
"discount": "0.00"
}
}
Change the Stores Lease Date
When updating a record, you must include all Composite Attributes associated with the table’s primary PK and SK.
let storeId = "LatteLarrys";
let mallId = "EastPointe";
let buildingId = "BuildingA1";
let unitId = "B47";
await StoreLocations
.patch({ storeId, mallId, buildingId, unitId })
.set({ leaseEndDate: "2021-02-28" })
.go();
Returns the following:
{
"data": {
"leaseEndDate": "2021-02-28"
}
}
Retrieve a specific Store in a Mall
When retrieving a specific record, you must include all Composite Attributes associated with the table’s primary PK and SK.
let storeId = "LatteLarrys";
let mallId = "EastPointe";
let buildingId = "BuildingA1";
let unitId = "B47";
await StoreLocations
.get({ storeId, mallId, buildingId, unitId })
.go();
Returns the following:
{
"data": {
"mallId": "EastPointe",
"storeId": "LatteLarrys",
"buildingId": "BuildingA1",
"unitId": "B47",
"category": "spite store",
"leaseEndDate": "2021-02-28",
"rent": "5000.00",
"discount": "0.00"
}
}
Remove a Store location from the Mall
When removing a specific record, you must include all Composite Attributes associated with the table’s primary PK and SK.
let storeId = "LatteLarrys";
let mallId = "EastPointe";
let buildingId = "BuildingA1";
let unitId = "B47";
let storeId = "LatteLarrys";
await StoreLocations
.delete({ storeId, mallId, buildingId, unitId })
.go();
Returns the following:
{ "data": {} }
Queries
All Stores in a particular mall
Fulfilling Requirement #1.
let mallId = "EastPointe";
let stores = await StoreLocations.query
.malls({ mallId })
.go();
All Stores in a particular mall building
Fulfilling Requirement #1.
let mallId = "EastPointe";
let buildingId = "BuildingA1";
let stores = await StoreLocations.query
.malls({ mallId, buildingId })
.go();
Find the store located in unit B47
Fulfilling Requirement #1.
let mallId = "EastPointe";
let buildingId = "BuildingA1";
let unitId = "B47";
let stores = await StoreLocations.query
.malls({ mallId, buildingId, unitId })
.go();
Stores by Category at Mall
Fulfilling Requirement #2.
let mallId = "EastPointe";
let category = "food/coffee";
let stores = await StoreLocations.query
.malls({mallId})
.where((attr, op) => op.eq(attr.category, category))
.go();
Stores by upcoming lease
Fulfilling Requirement #3.
let mallId = "EastPointe";
let q2StartDate = "2020-04-01";
let stores = await StoreLocations.query
.leases({mallId})
.lt({leaseEndDate: q2StateDate})
.go();
Stores will renewals for Q4
Fulfilling Requirement #3.
let mallId = "EastPointe";
let q4StartDate = "2020-10-01";
let q4EndDate = "2020-12-31";
let stores = await StoreLocations.leases(mallId)
.between(
{ leaseEndDate: q4StartDate },
{ leaseEndDate: q4EndDate })
.go();
Spite-stores with release renewals this year
Fulfilling Requirement #3.
let mallId = "EastPointe";
let yearStarDate = "2020-01-01";
let yearEndDate = "2020-12-31";
let storeId = "LatteLarrys";
let stores = await StoreLocations.leases(mallId)
.between (
{ leaseEndDate: yearStarDate },
{ leaseEndDate: yearEndDate })
.where((attr, op) => op.eq(attr.category, "Spite Store"))
.go();
All Latte Larry’s in a particular mall building
let mallId = "EastPointe";
let buildingId = "BuildingA1";
let unitId = "B47";
let storeId = "LatteLarrys";
let stores = await StoreLocations.query
.malls({ mallId, buildingId, storeId })
.go();