electrodb 1.4.0 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,13 +9,17 @@
9
9
 
10
10
  *Please submit issues/feedback or reach out on Twitter [@tinkertamper](https://twitter.com/tinkertamper).*
11
11
 
12
- <h1 align="center">ElectroDB has now entered version 1.0!</h1>
12
+ ------------
13
13
 
14
- > ElectroDB now has a major version, and with that comes semantic versioning guarantees and improved CHANGELOG detail. To release 1.0 some breaking changes we're made to improve the longevity of the project. Please see the [ChangeLog](/CHANGELOG.md) for more information about relevant deprecations, changes, and new features.
14
+ <a href="https://electrodb.fun"><h1 align="center">Introducing: The NEW ElectroDB Playground</h1></a>
15
15
 
16
- ------------
16
+ <p align="center">
17
+ <a href="https://electrodb.fun"><img width="400" src="https://github.com/tywalch/electrodb/blob/master/assets/playground.jpg?raw=true"></a>
18
+ </p>
19
+
20
+ <p align="center">Try out and share ElectroDB Models, Services, and Single Table Design at <a href="https://electrodb.fun">electrodb.fun</a></p>
17
21
 
18
- ### Try it out for yourself! https://runkit.com/tywalch/electrodb-building-queries
22
+ ------------
19
23
 
20
24
  ## Features
21
25
  - [**Use with your existing tables**](#using-electrodb-with-existing-data) - ElectroDB simplifies building DocumentClient parameters, so you can use it with existing tables/data.
@@ -36,51 +40,70 @@
36
40
  ------------
37
41
 
38
42
  **Turn this**
39
- ```javascript
40
- StoreLocations.query
41
- .leases({storeId: "lattelarrys"})
42
- .gte({leaseEndDate: "2010"})
43
- .where((attr, op) => `
44
- ${op.eq(attr.cityId, "Atlanta1")} AND ${op.contains(attr.category, "food")}
45
- `)
46
- .params()
43
+ ```typescript
44
+ tasks
45
+ .patch({
46
+ team: "core",
47
+ task: "45-662",
48
+ project: "backend"
49
+ })
50
+ .set({ status: "open" })
51
+ .add({ points: 5 })
52
+ .append({
53
+ comments: [{
54
+ user: "janet",
55
+ body: "This seems half-baked."
56
+ }]
57
+ })
58
+ .where(( {status}, {eq} ) => eq(status, "in-progress"))
59
+ .go();
47
60
  ```
48
61
  **Into This**
49
62
  ```json
50
63
  {
51
- "TableName": "StoreDirectory",
64
+ "UpdateExpression": "SET #status = :status_u0, #points = #points + :points_u0, #comments = list_append(#comments, :comments_u0), #updatedAt = :updatedAt_u0, #gsi1sk = :gsi1sk_u0",
52
65
  "ExpressionAttributeNames": {
53
- "#cityId": "cityId",
54
- "#category": "category",
55
- "#pk": "gis2pk",
56
- "#sk1": "gsi2sk"
66
+ "#status": "status",
67
+ "#points": "points",
68
+ "#comments": "comments",
69
+ "#updatedAt": "updatedAt",
70
+ "#gsi1sk": "gsi1sk"
57
71
  },
58
72
  "ExpressionAttributeValues": {
59
- ":cityId_w1": "Atlanta1",
60
- ":category_w1": "food",
61
- ":pk": "$mallstoredirectory#storeid_lattelarrys",
62
- ":sk1": "$mallstore_1#leaseenddate_2010"
73
+ ":status0": "in-progress",
74
+ ":status_u0": "open",
75
+ ":points_u0": 5,
76
+ ":comments_u0": [
77
+ {
78
+ "user": "janet",
79
+ "body": "This seems half-baked."
80
+ }
81
+ ],
82
+ ":updatedAt_u0": 1630977029015,
83
+ ":gsi1sk_u0": "$assignments#tasks_1#status_open"
84
+ },
85
+ "TableName": "your_table_name",
86
+ "Key": {
87
+ "pk": "$taskapp#team_core",
88
+ "sk": "$tasks_1#project_backend#task_45-662"
63
89
  },
64
- "KeyConditionExpression": "#pk = :pk and #sk1 >= :sk1",
65
- "IndexName": "gis2pk-gsi2sk-index",
66
- "FilterExpression": "#cityId = :cityId_w1 AND contains(#category, :category_w1)"
90
+ "ConditionExpression": "attribute_exists(pk) AND attribute_exists(sk) AND #status = :status0"
67
91
  }
68
92
  ```
93
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/PQKgBAsg9gJgpgGzARwK5wE4Es4GcA0YuccYGeqCALgUQBYCG5YA7llXWAGbZwB2MXGBDAAUKKwBbAA5QMVMAG8wAUT5V2AT0IBlTADcsAY1IBfbhiiSwAIkRwjVSzABGNgNzijUPrgVUGFwRSAF5bTShUDAB9AKC4aL4GSTgPcVAwABUGXABrITUNKk1hMW9ffxz8sDC+OBZVdS0AClEwJTb2sElYRAAuDq6u-iLNAZsAvNwbfE6h-UxcLB9xgEYZua7iDEMTccnchmlpG03TWaGGKicsF1QqPAHFTfaH5KeXruLpOHG-bD4AHMNkMhuQ0FhyDABk50J9zp8Dh9QV9ND8-jcgSCUWQ4BCoTCMHCUQiUdJLAArBxUZE476-Wz-LBYi448GoSFwaFgWFweGsoaoba0lH0jEA4EC0Hsznc3n8xHsYIi0FixmYyWfdoygk8olwKXtUmg+C4IzYaQaFaDOlohk2JlYhUovxXIUqoZqgDaNigPz4M1szIAtOSoIDyLhpoRfXxg3QoAgYIGbEYEFBiMmALpgHJgcp+Q1deBcBiUGm2P38U4kouyZk0D2o9G2PioSQuTDYobGz0MQG4JuvO1-OBUbug9hwSSD9USmug3tdbySFLqWfPHE8ke2BBYPwToZTmdD5v2yRHQ+gsM-eQ4Dda0FCzCn0U7h0ahdbo1FlEuWBjDa35nuKzLAo+PYQWApiPjBtafOacBXFyACCFabraLY2G2HZdr+YAlmW1ADM0ACUNQAHxgAAIshAB0fBQCwZH4eQDAwAA8nwCCAfK8Eoqg0gwMhMBoaearYe2nYYFe7QsFcRh0OMICyUQY4keRIRUbRDwMUxLGPmxnHcbx+rwmcUrMvAAAejxAV0YZUo4D5btIuSvtwOBJuMbmqe0K6yEsDwDD6bySDYWawfheQeVwXncg6uR+WAwDAPmbEPPmViBVOYC5HAmhCFwchgNITAaAwSC4HICj5SUaCYPeUEBRmU4hTYjnUimBwRbBzqgjkSyAnU3IYSiqVZQgwSOMsvi5lNTHcCVDW8EIDDmhmQiSOWWDSMEYAjOwTVbt4U3UrN4yDVgw1rjQqlWXA1njAOWCrG5wYvaseTBg91mqW5HkTRe0g8lAYARFEYAAOI6AAkmAAASOR0MAAAK5VHT4eUFVBcWIAln2+fh-nZa1wVgD6z4yZFW5LkMMX2eNaXA6D4ORBg0Nw2AABKDBAnAwA6DV2OaLj8XPUsX1JcTWUyGTDI+q6VBCr1tPmZBP6dMocT7TBpGeKIE0AAZlVQilG2A+5gHu+VgEbgnCQ8FuPSYlqWwoz5CDYVw3HcDyJFAVDRI9+53aIBy4J0dGm4pzTKJsYXjN45ATkitgACwAKzBgAbDnABMgabJ1jjjC4635QIC6mKRUfEFQcdEAEyuzr6-o2NBtftHR7EwI39brgMmed1HRz+n38dDCut2zl6Y1dFT4wUnzY5Xv+MCATYmR0FbxDTkIjAIFwwbl-lMB0V+0E5p0NdRywdCYHAzTNEoStCucSh4uYmlUXizRv7QGwIYwwRjwNMUiXcwB0UBFAMi7ggA)
69
94
 
70
95
  ------------
71
96
 
72
- ### Try it out for yourself! https://runkit.com/tywalch/electrodb-building-queries
73
-
74
97
  ## Table of Contents
75
98
  - [ElectroDB](#electrodb)
76
99
  * [Features](#features)
77
100
  * [Table of Contents](#table-of-contents)
101
+ - [Project Goals](#project-goals)
78
102
  - [Installation](#installation)
79
103
  - [Usage](#usage)
80
104
  - [Entities and Services](#entities-and-services)
81
105
  - [Entities](#entities)
82
106
  - [Services](#services)
83
- - [Project Goals](#project-goals)
84
107
  * [TypeScript Support](#typescript-support)
85
108
  + [TypeScript Services](#typescript-services)
86
109
  * [Join](#join)
@@ -153,6 +176,7 @@ StoreLocations.query
153
176
  + [Put Record](#put-record)
154
177
  + [Batch Write Put Records](#batch-write-put-records)
155
178
  + [Update Record](#update-record)
179
+ - [Updates to Composite Attributes](#updates-to-composite-attributes)
156
180
  - [Update Method: Set](#update-method-set)
157
181
  - [Update Method: Remove](#update-method-remove)
158
182
  - [Update Method: Add](#update-method-add)
@@ -258,6 +282,14 @@ StoreLocations.query
258
282
 
259
283
  ----------
260
284
 
285
+ # Project Goals
286
+
287
+ ElectroDB focuses on simplifying the process of modeling, enforcing data constraints, querying across entities, and formatting complex DocumentClient parameters. Three important design considerations we're made with the development of ElectroDB:
288
+
289
+ 1. ElectroDB should be able to be useful without having to query the database itself [[read more](#params)].
290
+ 2. ElectroDB should be able to be added to a project that already has been established tables, data, and access patterns [[read more](#using-electrodb-with-existing-data)].
291
+ 3. ElectroDB should not require additional design considerations on top of those made for DynamoDB, and therefore should be able to be removed from a project at any time without sacrifice.
292
+
261
293
  # Installation
262
294
 
263
295
  Install from NPM
@@ -306,14 +338,6 @@ const {Service} = require("electrodb");
306
338
  import {Service} from "electrodb";
307
339
  ```
308
340
 
309
- # Project Goals
310
-
311
- ElectroDB focuses on simplifying the process of modeling, enforcing data constraints, querying across entities, and formatting complex DocumentClient parameters. Three important design considerations we're made with the development of ElectroDB:
312
-
313
- 1. ElectroDB should be able to be useful without having to query the database itself [[read more](#params)].
314
- 2. ElectroDB should be able to be added to a project that already has been established tables, data, and access patterns [[read more](#using-electrodb-with-existing-data)].
315
- 3. ElectroDB should not require additional design considerations on top of those made for DynamoDB, and therefore should be able to be removed from a project at any time without sacrifice.
316
-
317
341
  ## TypeScript Support
318
342
 
319
343
  Previously it was possible to generate type definition files (`.d.ts`) for you Models, Entities, and Services with the [Electro CLI](#electro-cli). New with version `0.10.0` is TypeScript support for Entities and Services.
@@ -824,25 +848,27 @@ myAttr: {
824
848
 
825
849
  In this example, we have an attribute `"fee"` that needs to be updated any time an item's `"price"` attribute is updated. The attribute `"fee"` uses `watch` to have its setter callback called any time `"price"` is updated via a `put`, `create`, `update`, or `patch` operation.
826
850
 
851
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=3&ssc=29&pln=37&pc=2#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3hgmAV3p84AXjioKAdxTpMWABQIOcOCAiNqALkTqNcCouz6yQ7aJh8yAGkMa+FKADdgtCuYoDQAQxhoe0c4Vxc+YF5zAEYyQ1wHDQCGYGZhGB99NSM4S0ZrLJCNbDAvcgEoYFQAczichJChDzLsnLgSsrJUYRBmF2C2uCgKAEdhYGHGfQZhChCGnIIKFqL2rFLzbt7+xLbZANoAC30AbQtKzzIAXV2c5xh9ZQB9O0Qmz1wASkkAPgNBjTDGDCKCoXIXChwABUcAAdAAmTiDXDzeK7Ko6AAemX+RneVWqhUGYAA1kSAQRgNQpuRSQMATxwBAIhlTucrPRrqsFm0+GTcYNKdTzHz6YNGZAWWUTlduaiNCiEoh2n5mDRzFgICCnjBVTQnqg-CAKGQ8J9OBw8tY+IZYWB0qpwRyHrTKugduDmvoACwAVjNtuqEGUny4VrEtuEYEYAQojvDLrIVD8YECYFNX1t93jEP00XhAAYCwGNLCgyGgA)
852
+
827
853
  ```javascript
828
854
  {
829
855
  model: {
830
- entity: "services",
831
- service: "costEstimator",
856
+ entity: "products",
857
+ service: "estimator",
832
858
  version: "1"
833
859
  },
834
860
  attributes: {
835
- service: {
861
+ product: {
836
862
  type: "string"
837
863
  },
838
864
  price: {
839
865
  type: "number",
840
- required: true
866
+ required: true
841
867
  },
842
868
  fee: {
843
869
  type: "number",
844
- watch: ["price"],
845
- set: (_, {price}) => {
870
+ watch: ["price"],
871
+ set: (_, {price}) => {
846
872
  return price * .2;
847
873
  }
848
874
  }
@@ -851,11 +877,11 @@ In this example, we have an attribute `"fee"` that needs to be updated any time
851
877
  pricing: {
852
878
  pk: {
853
879
  field: "pk",
854
- composite: ["service"]
880
+ composite: ["product"]
855
881
  },
856
882
  sk: {
857
883
  field: "sk",
858
- composite: []
884
+ composite: []
859
885
  }
860
886
  }
861
887
  }
@@ -1090,6 +1116,8 @@ When using indexes without Sort Keys, that should be expressed as an index *with
1090
1116
  }
1091
1117
  ```
1092
1118
 
1119
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gwAhnwDWfOAF44qCgHcU6TFgAUHOInUa4ICI2oAuTdu0Ul2I2WFi+ZADRaTANwpQ+wXpYCM9x9r6uTsC0FJbWokJgYGR+uA4mQjAMwMwArjAUfEYIfhrAjNm52thgoeQCUMCoAOa+JiZQFACOqcCNBXAMqRRFcUWoQiBlOfXFWKWWFVW18aNwjS1tFB1dPaO4sbN5qPoAHpmFo408UB0jc2Cih3MaBMDUHWSXdTdwPOAQ7hlGANpk+WQALpFDQbG4AenBKBo9GIABEAEJwKoZKBgRowCQwAAWFDgVCEtFEcAgBDgQlQcAABmIqSC4JC4OiIKVYDgRJ1cfjCcTSeS4HxoPBRBQcLxyfTGdVgC5KVU9gA6XqxLR9DRIYTMGiWLAQVJQAD6mpoBoGQzIeA4AEpONxeAJkYwpOQQFgDcdoIwDQDODx+PAzXjpGRXabBhQDczWdh2FxwnwtArqhQYCokPk8FbE9UICobXGROJE2B0mnHXYZOHM9nc-mOPGFS1XFhEx7TmWM7gsxok7W2EA)
1120
+
1093
1121
  ### Indexes With Sort Keys
1094
1122
  When using indexes with Sort Keys, that should be expressed as an index *with* an `sk` property. If you don't wish to use the Sort Key in your model, but it does exist on the table, simply use an empty for the `composite` property. An empty array is still very useful, and opens the door to more query opportunities and access patterns like [collections](#collections).
1095
1123
 
@@ -1111,6 +1139,8 @@ When using indexes with Sort Keys, that should be expressed as an index *with* a
1111
1139
  }
1112
1140
  ```
1113
1141
 
1142
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gwAhnwDWfOAF44qCgHcU6TFgAUHOInUa4ICI2oAuTdu0Ul2I2WFi+ZADRaTANwpQ+wXpYCM9x9r6uTsC0FJbWokJgYGR+uA4mQjAMwMwArjAUfEYIfhrAjNm52thgoeQCUMCoAOa+JiZQFACOqcCNBXAMqRRFcUWoQiBlOfXFWKWWFVW18aNwjS1tFB1dPaO4sbN5qPoAHpmFo408UB0jc2Cih3MaBMDUHWSXdTdwPOAQ7hlGANpk+WQALpFDR9G5ia43O4PSaiF43AD0CLgAEE4BRwNg3iRIF8KHAhFAoEIcMAJAJgFQqBoQdokXAqrR2ikqDhUgECKkqAA6OAAYQAFnRRHAIOlOkK4LSNPSKLtBmAaBJmNQIAoYBA4AF8QK1eiaPQmMwpa84PT2Zk4GBGnd9hJeBL8XxoDBRBQcBqTa96QMiXqYJK+DxSqKCHAWq57nxudLsR88b9gTcNutYlowYhOkJmDRLFgxVAAPrCHMUQsDIZkPAcACUnG4vAEDMYUnIICwheO0EYhYBnB4-HgFfx0jI7fLgzL1ogpVgWHYXHCfC03OqFBgKiQ+TwNZX1QgKjri5E4hXYHSm+bdhkk53e4PR44S+5EagWBXXdOl+3uF3GlXD5sEAA)
1143
+
1114
1144
  ### Numeric Keys
1115
1145
 
1116
1146
  If you have an index where the Partition or Sort Keys are expected to be numeric values, you can accomplish this with the `template` property on the index that requires numeric keys. Define the attribute used in the composite template as type "number", and then create a template string with only the attribute's name.
@@ -1147,6 +1177,8 @@ const schema = {
1147
1177
  }
1148
1178
  ```
1149
1179
 
1180
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gwAhnwDWfOAF44qCgHcU6TFgAUCDnDggIjagC5EGzXApLsBsqgCuIClGC0yAGiOa+dgG4OKFigA8hcBpnVzgPOz5gXgsARjIjXBdNIRgGYGYrGAo+A3VjGRtmOxjc0M0AenK4XQJgWUY4EQKQIqgyuGwwH3JrFrsyOFDE0N7WgCZS-IqqmrqKBqbRu3bO7stC-s0hhKS4Ot0-bMnjKDpoRmP8sFFLqdrqC-JrkKnjSrg5YCoqOAyvhoACgBpRoSXp2BxhIRUKwUdqaLJBFJrAAkCCWUBiuGcg1emh44AgkSyBgA2us+piyABddrDV5iW75e5UR5kMQvPHvT7fX5Wf5wADKIMWNghtChMLheI6FCRJPIaIxY2xTlxeIJkGJ3XJyppdO2mlwHESiA6QmYNAsWAgVigAH1hJaKPbUIEKANcABKTjcXgCZqtGJSOAxMYAZgALABWTg8fjwZUhgBsAHYABwATgADL7hGI+EYAHQAcwoMDUgeKaqT3uLJYgKh9XHz4mLYEylYxMRrGygYzwXvrjebHFbfCLAEdYVAsMXTjwoIwu33g3XNEWijA5BRTCpQkhlQYkwBaUPZ7N4XaaQ99iZV-twADU58v9LgQ43DabbCAA)
1181
+
1150
1182
  ### Index Casing
1151
1183
 
1152
1184
  DynamoDB is a case-sensitive data store, and therefore it is common to convert the casing of keys to uppercase or lowercase prior to saving, updating, or querying data to your table. ElectroDB, by default, will lowercase all keys when preparing query parameters. For those who are using ElectroDB with an existing dataset, have preferences on upper or lowercase, or wish to not convert case at all, this can be configured on an index key field basis.
@@ -1160,12 +1192,12 @@ In the example below, we are configuring the casing ElectroDB will use individua
1160
1192
  index: "gsi1",
1161
1193
  pk: {
1162
1194
  field: "gsi1pk",
1163
- casing: "upper",
1195
+ casing: "upper", // Acct_0120 -> ACCT_0120
1164
1196
  composite: ["organizationId"]
1165
1197
  },
1166
1198
  sk: {
1167
1199
  field: "gsi1sk",
1168
- casing: "none",
1200
+ casing: "none", // Acct_0120 -> Acct_0120
1169
1201
  composite: ["accountId"]
1170
1202
  }
1171
1203
  }
@@ -1173,6 +1205,8 @@ In the example below, we are configuring the casing ElectroDB will use individua
1173
1205
  }
1174
1206
  ```
1175
1207
 
1208
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gBXPhSh84AXjioKAdxTpMWABQIOcOCAiNqALkTqNcCouz6yw0WQA0hjSKgA3YLQrmYAQz4BrD2DA2dnCOonzAvOYAjGSGuLYaHjAMwMyCMBR8+mpGcOkeIACSjFlBGthgbuQCUMCoAOYxOXFBllBFJTllWBXm1bUNQc050HUeqMAAXonhqO0GnbndlWR99Y1GQ0bENB2d5curA03xRgTAYjAAcvmV2XtLvclrgycaVF5XN7s5+481z8cghQQB5gFRvkZflUnkcNq84IxEhQABLnCjFeb3HrQ-4NeG4WInWo6AAeGQhrUymJyYG8EJyZ2oGLItMCCw0PHAEDC6X0AG0yCMxpNprwimQALrwnIAehlcHetG8cAgBDgAANaF5+uq4GBiBVYDgdAQPIIqDBxDAIAqILJRFqRKU8NK4D56adgEzet42ezOZAeZUBa1xVLnRo5XBBP4HV4MnBvBQcMwKARoBQ3R5nPUZTHERhcwBHQSiLD9CNwR39cwxw3rJovILbcnUozEigk8x1MKRWkAWh7wEiPn7HZJfppdLbDK9VGZQ77vtdHJIgcwwbIeUKjElK7gUcYEAy6CrAAsxnVM0mcNX6nBZGeTFmc3U82AC-0ZSWyxX2VXtXqcxUF4CgbDgZ1Nhyd0Z09b1yEXHxJ06ANuQ3fkyBbcCyALFE0V3cN-yjOs4xEcQbzgVN0ygTM+GzL982mYtSygct6krO86lrWMoAbDZBliDg4kQXIPGYHZyCwCBBCgAB9TxxIoWTUBuMg8AASk4bheAEXIKHyIpJHIAAVfSQAAISoUsYh4fghAcQypDIABVBxIgAJgAZhsnT4CFcYpgwMVGCMshTNoM8AGFoACbS7LgFtQpALAACUIBoHz4rOC5rhATMnIAKQ8JVMt094BFy-LyAAQUYGheLi3TgVBKhQoAK2K7wADoPDq0QAAF0gingoDALrmEmUr4Fw1EaJCpz3IABncyJ+0WgB2Nboi4SlDC6sA0lUIJtyKeFQ0YeF-JFILZgu5t0ooeFsoqm54XKz48vhZqwXhGb8JOXB1L2uoIGUTSdocPgup-Vi9spVQrsCmYikB4HQfBjhKWhlisD2ls+FUE6LoSh7UY0caKBge0TGUIIED+ubzCWla1oANjIKDEAZ9EmeW9yto5wwgfJkGwbYIA)
1209
+
1176
1210
  > _NOTE: Casing is a very important decision when modeling your data in DynamoDB. While choosing upper/lower is largely a personal preference, once you have begun loading records in your table it can be difficult to change your casing after the fact. Unless you have good reason, allowing for mixed case keys can make querying data difficult because it will require database consumers to always have a knowledge of their data's case._
1177
1211
 
1178
1212
  Casing Option | Effect
@@ -1271,6 +1305,9 @@ indexes: {
1271
1305
  sk: '$mallstores#mid_mallvalue#bid_buildingvalue#uid_unitvalue'
1272
1306
  }
1273
1307
  ```
1308
+
1309
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gDoFPnAC8cVBQDuKdJiwAKBBzhwQERtQBciVWrgV52XWSFQRZADT61fClABuwWhVMgAhlSqNgF+tBY1rZwjg58wLymAIxk+rg2ah4wDMDMAK4wIroqBnDmFACSjDkhathgbuQCUMCoAObBeWpUHsw61cCMTQYJIZ7exaXNcBVVZqkNPXmt7VTuXdN4iQYZwD519UN6I2OmNZtLLW0dZMyLK2p9eemomNu5zXvVk42XBrOn6RchuPErdS0AA9sjsPhBaMlIvxhs0wABrWEjAjAaglcgIo4GHjgCARLK6ADaE2ExTIAF0yssqXxEWDkaifPt4Vi1DjIPiqsSBlQyVZyGsNg0+eRbvdupSRn88tK8BwEohRm0aKYsBB0lAAPowZUUTWoDwgChkPAASk4HAKfH0ADowJllCECtsyABlAAqAHkAErIABqAEEADIAVWQSx5LoAssGg4HQ+H3oLfML0WQAEIhwpBgAihQAcgBxeNhpZimAukP5wrukvh+Km231CCKc1AA)
1310
+
1274
1311
  ### Composite Attribute Templates
1275
1312
  In a Composite Template, you provide a formatted template for ElectroDB to use when making keys. Composite Attribute Templates allow for potential ElectroDB adoption on already established tables and records.
1276
1313
 
@@ -1333,6 +1370,8 @@ ElectroDB will continue to always add a trailing delimiter to composite attribut
1333
1370
  }
1334
1371
  ```
1335
1372
 
1373
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gDoFPnAC8cVBQDuKdJiwAKBBzhq4ICI2oAuRKvWGK87HrIBZAIZUqAZRjCAwgFchIMgBoDhtQDcKUHzAvGYAjJ7ePnwBvsC0FGYg1lRCUBSMwGn00FhkkbhehpYwDMDMzjAieio+6qkUAJKM1ZG1athgCeQCUMCoAOZ5bXiFbUk2TS3Dhh1dZD19g63qBctq5cBUGQOT+tPqs2YLA0Ntq8POqJi7Nftwh92lJ2t4+aNqfdoAHlV7bVQQWjFYL8KZ3MAAazBd3UBGA1Ga5EhERhMwo4CoxTmQUYAH0ACQIepNXAo1FqHjgCBBSp6ADa8wcaSaZAAui9DOc7nwoX9yXCEUcIWTyZUMVjEsA8YTxlQSQBiZhSgkIDZbRYK5zKwmXa6MUnvVGUyA0roM2UsjzkNXbfqW8i6mAs9kw3AvN2cjgFRD3SzMGhmLAQZxQXEwP00XGoSwgChkPAASk4HHqfAMADowBVlJFiYiyLYACoAeQASsgAGoAQQAMgBVZAijTJXYWWs16v1xuGm0a-MAITrDRrABEGgA5ADinYbTcdrbr44ahZnjYMuATGf6EEUSaAA)
1374
+
1336
1375
  #### Templates and Composite Attribute Arrays
1337
1376
 
1338
1377
  The example above shows indexes defined only with the `template` property. This property alone is enough to work with ElectroDB, however it can be useful to also include a `composite` array with the names of the Composite Attributes included in the `template` string. Doing so achieves the following benefits:
@@ -1362,6 +1401,8 @@ An example of using `template` while also using `composite`:
1362
1401
  }
1363
1402
  ```
1364
1403
 
1404
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3gDoFPnAC8cVBQDuKdJiwAKBBzhq4ICI2oAuRKvWGK87HrIBZAIZUqAZRjCAwgFchIMgBoDhtQDcKUHzAvGYAjJ7ePnwBvsC0FGYg1lRCUBSMwGn00FhkkbhehpYwDMDMzjAieio+6qkUAJKM1ZG1athgCeQCUMCoAOZ5bXiFbUk2TS3Dhh1dZD19g63qBctq5cBUGQOT+tPqs2YLA0Ntq8POqJi7Nftwh92lJ2t4+aNqfdoAHlV7bVQQWjFYL8KZ3MAAazBd3UBGA1Ga5EhERhMwo4CoxTmQUYAH0ACQIepNXAo1FqHjgCBBSp6ADa8wcaSaZAAui9DOc7nwoX9yXCEUcIWTyZUMVjEsA8YTxlQSQBiZhSgkIDZbRYK5zKwmXa6MUnvVGUyA0roM2UsjzkNXbfqW8i6mAs9kw3AvN2cjgFRD3SzMGhmLAQZxQXEwP00XGoSwgChkPAASk4HHqfAMADowBVlJFiYiyLYACoAeQASsgAGoAQQAMgBVZAijTJXYWWs16v1xuGm0a-MAITrDRrABEGgA5ADinYbTcdrbr44ahZnjYMuATGf6EEUSaAA)
1405
+
1365
1406
  ## Composite Attribute and Index Considerations
1366
1407
 
1367
1408
  As described in the above two sections ([Composite Attributes](#composite-attributes), [Indexes](#indexes)), ElectroDB builds your keys using the attribute values defined in your model and provided on your query. Here are a few considerations to take into account when thinking about how to model your indexes:
@@ -1391,21 +1432,29 @@ When your attribute's name, or [`field` property](#expanded-syntax) on an attrib
1391
1432
  },
1392
1433
  attributes: {
1393
1434
  accountId: {
1394
- type: "string" // string and number types are both supported
1395
- }
1435
+ type: "string"
1436
+ },
1437
+ productNumber: {
1438
+ type: "number"
1439
+ }
1396
1440
  },
1397
1441
  indexes: {
1398
- "your_access_pattern_name": {
1442
+ products: {
1399
1443
  pk: {
1400
1444
  field: "accountId",
1401
- composite: ["accountId"]
1445
+ composite: ["accountId"]
1402
1446
  },
1403
- sk: {...}
1447
+ sk: {
1448
+ field: "productNumber",
1449
+ composite: ["productNumber"]
1450
+ }
1404
1451
  }
1405
1452
  }
1406
1453
  }
1407
1454
  ```
1408
1455
 
1456
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3jBUANwrpoOALxxUFAO4p0mLAAoEHOJrggIjagC5EGrSbEZshslggBXKAH0zy)
1457
+
1409
1458
  **Using `template`**
1410
1459
 
1411
1460
  Another approach allows you to use the `template` property, which allows you to format exactly how your key should be built when interacting with DynamoDB. In this case `composite` is optional when using `template`, but including it helps with TypeScript typing.
@@ -1426,7 +1475,7 @@ Another approach allows you to use the `template` property, which allows you to
1426
1475
  "your_access_pattern_name": {
1427
1476
  pk: {
1428
1477
  field: "accountId",
1429
- composite: ["accountId"], // `composite` is optional when using `template` but helps with TypeScript typing
1478
+ composite: ["accountId"], // `composite` is optional when using `template` but is required when using TypeScript
1430
1479
  template: "${accountId}"
1431
1480
  },
1432
1481
  sk: {...}
@@ -1435,6 +1484,8 @@ Another approach allows you to use the `template` property, which allows you to
1435
1484
  }
1436
1485
  ```
1437
1486
 
1487
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3jBUANwrpoOALxxUFAO4p0mLAAoEHOJrggIjagC5EGrSbEZshslggBXKAH0zy+6gCGICmQA0xk5r4UUMLAtBSW1nb2AUEhFC7unj5+WqJQfMC8lgCMZL54SVquMAzAzDYwFHyG6smarrQ8NugAkozVebVw2GBh5AJQQgDmZHAdWrheyWOaYEw29AByNiDMge2dJt29ZKjLq1C5nRN5xyZCegAeleu1s7rzMFVGG1pgANY3LyYEwNRt5PVGi1GN5phsKuAqEVtgASBCA2zA3Cgr5+HjgCDpCqGADaZARTRgrTIAF0Ci9Tl8+B9nqitD8-pY7owHksVoEUXTNBCwFDseQ4czWXtAsjyXT0ZAsb08ULFiKDmSwSZcGDVSqOBNEF1XMwaOFbA4YLqaPEPCNcABKTjcXgCOAE4FwaT4howAC0ABYAKwAZgADOxbfx4HKYGz9s64AAmf3+rI2oSicRQLDGAB0YHKagdDURRMYkzDEcCeEtGcGEBU1q4SbMEnTAEcbIE0yZM3N6Hw1I6C1a8unK9XOEA)
1488
+
1438
1489
  **Advanced use of `template`**
1439
1490
 
1440
1491
  When your `string` attribute is also an index key, and using key templates, you can also add static prefixes and postfixes to your attribute. Under the covers, ElectroDB will leverage this template while interacting with DynamoDB but will allow you to maintain a relationship with the attribute value itself.
@@ -1475,6 +1526,8 @@ For example, given the following model:
1475
1526
  }
1476
1527
  ```
1477
1528
 
1529
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAnnAvnAMyghDgCIBTAGwoGMZiATAIzIG4AoD2iVAZ3jBUANwrpoOALxxUFAO4p0mLAAoEHOHBARG1AFyINmuGIzYDZLBACuUAPqnld1AEMQFMgBojmvhSjCwLQUFla2dn4BQRTObh7exnCiUHzAvBYAjGRGuAlwLjAMwMzWMBR8BuqJLrQ81ugAkoyVPsbYYCHkAlBCAOZkcAD0g3C8VDjdfXDt5flQFHDMEDAAFnB81mCQsBSMhNDTK8B8JgAebmA0rbmt0L0uqMAAXgVpqE0tiZozFpOo-dc8ppXO5Pl8fl0iv9solcDk8kJdKdymDNDU6ugKoYvsYwABrVE44wEYDUZrkO4PZ6vXhNLytIlwHjgCCpMoGADaZEpjxeGFpjDIAF0GcYboy+ATsYziaSqOSyOibI1BUCZczIGzOlylfUYHShWrGWVwFQCp0yGB5iTTnYACQIXUq3B2TUwG0wonisU5Di5RDTFzMGihGz2GBBmixdwDXAASk43F4AnytWV+r20kVtRgAFoACwAVgAzAAGdhJ-jwHnU-nvTMUqC9XMATjLWUTQlE4igWCMADowKU1KmMRnPKMm1S+W8mng4wPehAVAmuMM4HJMCsbPAnRn1ptLqTGBwu6YJP2AI7Wfx9xL9vd8NQ1mcC+OtftLleJ9d7ucbLYqGPfIThcchmAoXohD4bIzx7LArxvXsP0fZ8p15Gl63fe8IKg-g1D-RhsOMT9l1XDhfzTPV-0PIDdhA8gCGsKhxjgPFUAgORUFgkRz17RDbxQqjMTQ+4MLrJoJ0I4jNFI78gA)
1530
+
1478
1531
  ElectroDB will accept a `get` request like this:
1479
1532
 
1480
1533
  ```typescript
@@ -1631,6 +1684,8 @@ await TaskApp.collections
1631
1684
  }
1632
1685
  ```
1633
1686
 
1687
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAngGjgZQFMoA3YAY0LgF84AzKCEOAIkIBtDyZGATAIxYBuAFAjyEVAGd4MAIb9OcALyswjAFZcYIOajkBzQiELphYidPjGw7CFkKEpKuKkIB3FOkxYAFAhE4OBAIXg4ALkRAoLhTDGxItnA7BycWHGigkmIpYElEgEZ0zLgpYjJKRPkpAGs5MDBioOoMoLkYHmB+AFcYJ0iAmNjk+0cASV4BkqDsMEJEmShgVAMWEpaS6AM9YAAvdrzUCamhmaw5hc6VtaGNof0TE9PZ+dZF5dX11pi+uRAnoYvSIAbRYGm6YEwxHSrBMUHI3SgWBhLCk7URqBYAF11tE7nBlmEAB79KJDGRyOh0AExMA1GlDOjADiTNQ1JqnIIScAQXJ9EEsLY7fYYSQTbHTGjfcn0smc+jM9is1Hs6WnbmQPmvUE2FLjXgSznUL4lXWjV6DdUQdicbiHRJyKS5AyoEzoKQcoaEwhExIGXIAJk9tNlls5TJZfsDdODQw1vKhArNqXFWLVzXTpVDkqCEaVUeAAdqsZi8a1ILTkvxzTxIhaiDg8kUVGoAEoLJIZI3HTVnKo3J40PE-JaQmF2DS4j4qj2PWrslBcvlWEU1WVSBRXixqnUGhz8e1Oj0+lIaTvjnLAect+9riahsn9QzG9fLks77c1eoIFpuBewz8r5vFcnyfiU8ScM+QLAe+oExNWcD8KEWBQUBqIgTc8F4t83okqel5wN+v4wM+dLPrmirKjGmZckwmqJnAoJEdoqZVpmtTkQqkZvKqOZwGWDGgueBo4ka94xI6zpuKyAG0Ta2j2qwknAC6bowHOkq4QWQaZmRBGMpR2nUXxAn8oxSS2OaqaZghQQcfpMR5sq-qFsWNH8XRCZmUxmgsSJNlqsaNb1kgTZKG2ojiJ2sg9vUYAuAOBDlJu-iPk4eA7lIEViDucUAHQSPJdqdiIACQeXKapcRSKlIwpsqABSyBEhAGDkCwbZlXlBgQL4rZCEAA)
1688
+
1634
1689
  ### Collection Queries vs Entity Queries
1635
1690
 
1636
1691
  To query across entities, collection queries make use of ElectroDB's Sort Key structure, which prefixes Sort Key fields with the collection name. Unlike an Entity Query, Collection Queries only leverage [Composite Attributes](#composite-attributes) from an access pattern's Partition Key.
@@ -1657,6 +1712,8 @@ await TaskApp.entities
1657
1712
  }
1658
1713
  ```
1659
1714
 
1715
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAngGjgZQFMoA3YAY0LgF84AzKCEOAIkIBtDyZGATAIxYBuAFAjyEVAGd4MAIb9OcALyswjAFZcYIOajkBzQiELphYidPjGw7CFkKEpKuKkIB3FOkxYAFAhE4OBAIXg4ALkRAoLhTDGxItnA7BycWHGigkmIpYElEgEZ0zLgpYjJKRPkpAGs5MDBioOoMoLkYHmB+AFcYJ0iAmNjk+0cASV4BkqDsMEJEmShgVAMWEpaS6AM9YAAvdrzUCamhmaw5hc6VtaGNof0TE9PZ+dZF5dX11pi+uRAnoYvSIAbRYGm6YEwxHSrBMUHI3SgWBhLCk7URqBYAF11tE7nBlmEAB79KJDGRyOh0AExMA1GlDOjADiTNQ1JqnIIScAQXJ9EEsLY7fYYSQTbHTGjfcn0smc+jM9is1Hs6WnbmQPmvUE2FLjXgSznUL4lXWjV6DdUQdicbiHRJyKS5AyoEzoKQcoaEwhExIGXIAJk9tNlls5TJZfsDdODQw1vKhArNqXFWLVzXTpVDkqCEaVUeAAdqsZi8a1ILTkvxzTxIhaiDg8kUVGoAEoLJIZI3HTVnKo3J40PE-JaQmF2DS4j4qj2PWrslBcvlWEU1WVSBRXixqnUGhz8e1Oj0+lIaTvjnLAect+9riahsn9QzG9fLks77c1eoIFpuBewz8r5vFcnyfiU8ScM+QLAe+oExNWcD8KEWBQUBqIgTc8F4t83okqel5wN+v4wM+dLPrmirKjGmZckwmqJnAoJEdoqZVpmtTkQqkZvKqOZwGWDGgueBo4ka94xI6zpuKyAG0Ta2j2qwknAC6bowHOkq4QWQaZmRBGMpR2nUXxAn8oxSS2OaqaZghQQcfpMR5sq-qFsWNH8XRCZmUxmgsSJNlqsaNb1kgTZKG2ojiJ2sg9vUYAuAOBDlJu-iPk4eA7lIEViDucUAHRThgTjRHlmV5QAjt0xBYCIACQeXKS6hC8KlIwpsqABSyBEhAGDkCwbZ1XlBgQL4rZCEAA)
1716
+
1660
1717
  **Collection Query**
1661
1718
  ```javascript
1662
1719
  await TaskApp.collections
@@ -1673,6 +1730,8 @@ await TaskApp.collections
1673
1730
  }
1674
1731
  ```
1675
1732
 
1733
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbzgUQHY2DAngGjgZQFMoA3YAY0LgF84AzKCEOAIkIBtDyZGATAIxYBuAFAjyEVAGd4MAIb9OcALyswjAFZcYIOajkBzQiELphYidPjGw7CFkKEpKuKkIB3FOkxYAFAhE4OBAIXg4ALkRAoLhTDGxItnA7BycWHGigkmIpYElEgEZ0zLgpYjJKRPkpAGs5MDBioOoMoLkYHmB+AFcYJ0iAmNjk+0cASV4BkqDsMEJEmShgVAMWEpaS6AM9YAAvdrzUCamhmaw5hc6VtaGNof0TE9PZ+dZF5dX11pi+uRAnoYvSIAbRYGm6YEwxHSrBMUHI3SgWBhLCk7URqBYAF11tE7nBlmEAB79KJDGRyOh0AExMA1GlDOjADiTNQ1JqnIIScAQXJ9EEsLY7fYYSQTbHTGjfcn0smc+jM9is1Hs6WnbmQPmvUE2FLjXgSznUL4lXWjV6DdUQdicbiHRJyKS5AyoEzoKQcoaEwhExIGXIAJk9tNlls5TJZfsDdODQw1vKhArNqXFWLVzXTpVDkqCEaVUeAAdqsZi8a1ILTkvxzTxIhaiDg8kUVGoAEoLJIZI3HTVnKo3J40PE-JaQmF2DS4j4qj2PWrslBcvlWEU1WVSBRXixqnUGhz8e1Oj0+lIaTvjnLAect+9riahsn9QzG9fLks77c1eoIFpuBewz8r5vFcnyfiU8ScM+QLAe+oExNWcD8KEWBQUBqIgTc8F4t83okqel5wN+v4wM+dLPrmirKjGmZckwmqJnAoJEdoqZVpmtTkQqkZvKqOZwGWDGgueBo4ka94xI6zpuKyAG0Ta2j2qwknAC6bowHOkq4QWQaZmRBGMpR2nUXxAn8oxSS2OaqaZghQQcfpMR5sq-qFsWNH8XRCZmUxmgsSJNlqsaNb1kgTZKG2ojiJ2sg9vUYAuAOBDlJu-iPk4eA7lIEViDucUAHQSPJdqdiIACQeXKapcRSKlIwpsqABSyBEhAGDkCwbZlXlBgQL4rZCEAA)
1734
+
1676
1735
  The notable difference between the two is how much of the Sort Key is specified at query time.
1677
1736
 
1678
1737
  **Entity Query:**
@@ -1899,6 +1958,8 @@ const projectMembers = new Entity({
1899
1958
  const TaskApp = new Service({employees, tasks, projectMembers});
1900
1959
  ```
1901
1960
 
1961
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoMhBQBneDACGvdnAC8zMPQBWHGCEkpJAcwIgCaJgG4BQkeLh6wrCJgIFR8uCgIB3OKnRYAFAgFw4EAhuNgAuRH8AyzQMTHCWcBs7ByZsSIDiIlFgEXiARlT0uFEiUgp4qVEAa0kwMEKAyjSAyRguYF4AVxgHcL8oy0TbewBJbj6igKwwAnjxKGAUbUEBpqLobU1gAC9WnJQxiYGpzBm59qWVqLWBrX0j4+nZ5nnF5aKbqJ7JEAeBp-CAG1JlEmMpOmAMERUnAQQEmPooGROlBMDC4S9WiiUFcBgBdOCSRzCMQwD6RT6LEIAD16EQG4kkNBofyiYCqrIGNGAbHGiiqDWOAWE4Ag2R6QKYGy2u3QIjGTDxIM+DI59KFtB5rD5TGqgqFIsg4uegIS1mGBAVSqFlA+zSiViS9k5cGErHYnH28RJ7S6crE+qiVII1Pi2myACZAwF2S6AtzeWHI+zo1FDWKoZLHRarfbVnmotU45rE8xw8AI3qCwN08agXjq3AVU2KQImog4FIZAQmwBKUwkiyVKqOBQudyeWK+SJBEKsVkGLxxZjD0SBzJQbK5ZgFAslEjkZ5MYe1er2z6tX3dOn9L5EqqHdX-U5H16XO1FbPJR+359nF4XO8+ZFEoECqJwP4ggCAELO+wH-Bg7AutBuqAbiTYFrwwTLr+XwvucsFAdcFL2sGtKiKyoHgTALpuh6-rxBAG6kG4qaxk+xwJtq8Qpo2woMEamZwKaVFqFayqNkWHFclqOpVhitZCaaw7iTaH4DES2TaC4fK4fx7pqF6wkYkwPoLH6+xrrgJmacA2n6Gga4ggSRKuuYMCNmRSYVmxap6VEXE6uWEa8QpAkZhKwlmk6lrcIqjbNgEUn+fGsneZWAp8W5op1lFokQXFDYSeSjRtrgCCdtIsiUL2JhmKScD5TAACyei8FkTjjh4MQ+Les5hBxi6xDxKhqK1IDtZu65ZEZTC7kU+5lEeJ51IKF5tOZ14UYNQzfrpUH4TBbzoc2TWQUKKFvkRjQFnczz+ZdaHqRhkRkTeRT6BNWS0RABmetuUrMTyri+cWgU8ZlYU5UpTBnYVxVCslGLgy8kMatlgmRaaX6jPDanwWyo2cNt-l0YZ27AujpkiFe-pWbCVO2fZi5OUKLnEu5nkoDS6Wg9JAVpWWyZoxqilY9FOaFQlkl+cjgtMMF8no2LJpFTaBa2qV7YVV21W1bC9UWAAKveACCdSdW4+ClIevg4w4uCrrgTXjZNog1SYg7wPbYxOMeriSKwZAABbGKYJvVObYAAHRk-9YiRLHNObXTdu7bjNWJ9oEDeP2ATRzAwcGN43CtJI8gAHwcQA9NXbloCnlluX9-pwFABAwNijjt6InSsDAohFLXtD0Iwhc9jQv02K4bzRF4PIUUUXuIPbojO0TLVtVkjv3u7Til1IJiNP2AgR1UUdJy3lmJ0zKAOQPafmntmf59nueJ+PKAl2Xlc13XZkdG6E3OOrd26dygGINuDg+4DyHnXOgDBOxF1oFPCAM8lhzwwAvUIS93KIBdlvTcO9qh7wUAfSQR8+wmCAA)
1962
+
1902
1963
  > TypeScript Note: Use `as const` syntax when defining `collection` as a string array for improved type support
1903
1964
 
1904
1965
  The last line of the code block above creates a Service called `TaskApp` using the Entity instances created above its declaration. By creating a Service, ElectroDB will identify and validate the sub-collections defined across all three models. The result in this case are four unique collections: "overview", "contributions", and "assignments".
@@ -1926,6 +1987,8 @@ const results = await TaskApp.collections
1926
1987
  }
1927
1988
  ```
1928
1989
 
1990
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoMhBQBneDACGvdnAC8zMPQBWHGCEkpJAcwIgCaJgG4BQkeLh6wrCJgIFR8uCgIB3OKnRYAFAgFw4EAhuNgAuRH8AyzQMTHCWcBs7ByZsSIDiIlFgEXiARlT0uFEiUgp4qVEAa0kwMEKAyjSAyRguYF4AVxgHcL8oy0TbewBJbj6igKwwAnjxKGAUbUEBpqLobU1gAC9WnJQxiYGpzBm59qWVqLWBrX0j4+nZ5nnF5aKbqJ7JEAeBp-CAG1JlEmMpOmAMERUnAQQEmPooGROlBMDC4S9WiiUFcBgBdOCSRzCMQwD6RT6LEIAD16EQG4kkNBofyiYCqrIGNGAbHGiiqDWOAWE4Ag2R6QKYGy2u3QIjGTDxIM+DI59KFtB5rD5TGqgqFIsg4uegIS1mGBAVSqFlA+zSiViS9k5cGErHYnH28RJ7S6crE+qiVII1Pi2myACZAwF2S6AtzeWHI+zo1FDWKoZLHRarfbVnmotU45rE8xw8AI3qCwN08agXjq3AVU2KQImog4FIZAQmwBKUwkiyVKqOBQudyeWK+SJBEKsVkGLxxZjD0SBzJQbK5ZgFAslEjkZ5MYe1er2z6tX3dOn9L5EqqHdX-U5H16XO1FbPJR+359nF4XO8+ZFEoECqJwP4ggCAELO+wH-Bg7AutBuqAbiTYFrwwTLr+XwvucsFAdcFL2sGtKiKyoHgTALpuh6-rxBAG6kG4qaxk+xwJtq8Qpo2woMEamZwKaVFqFayqNkWHFclqOpVhitZCaaw7iTaH4DES2TaC4fK4fx7pqF6wkYkwPoLH6+xrrgJmacA2n6Gga4ggSRKuuYMCNmRSYVmxap6VEXE6uWEa8QpAkZhKwlmk6lrcIqjbNgEUn+fGsneZWAp8W5op1lFokQXFDYSeSjRtrgCCdtIsiUL2JhmKScD5TAACyei8FkTjjh4MQ+Les5hBxi6xDxKhqK1IDtZu65ZEZTC7kU+5lEeJ51IKF5tOZ14UYNQzfrpUH4TBbzoc2TWQUKKFvkRjQFnczz+ZdaHqRhkRkTeRT6BNWS0RABmetuUrMTyri+cWgU8ZlYU5UpTBnYVxVCslGLgy8kMatlgmRaaX6jPDanwWyo2cNt-l0YZ27AujpkiFe-pWbCVO2fZi5OUKLnEu5nkoDS6Wg9JAVpWWyZoxqilY9FOaFQlkl+cjgtMMF8no2LJpFTaBa2qV7YVV21W1bC9UWAAKveACCdSdW4+ClIevg4w4uCrrgTXjZNog1XVJvVObYAAHRk-9YhFL7TE224vhw-EeAACIALQRgADAALEwNXB9oEDeLVQA)
1991
+
1929
1992
  Unlike `overview`, the collections `contributions`, and `assignments` are more complex.
1930
1993
 
1931
1994
  In the case of `contributions`, _all three_ entities implement this collection on the `gsi2` index, and compose their Partition Key with the `employeeId` attribute. The `assignments` collection, however, is only implemented by the `tasks` and `projectMembers` Entities. Below is an example of using these collections:
@@ -1954,10 +2017,12 @@ const results = await TaskApp.collections
1954
2017
  }
1955
2018
  ```
1956
2019
 
2020
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=158&ssc=9&pln=157&pc=1#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoMhBQBneDACGvdnAC8zMPQBWHGCEkpJAcwIgCaJgG4BQkeLh6wrCJgIFR8uCgIB3OKnRYAFAgFw4EAhuNgAuRH8AyzQMTHCWcBs7ByZsSIDiIlFgEXiARlT0uFEiUgp4qVEAa0kwMEKAyjSAyRguYF4AVxgHcL8oy0TbewBJbj6igKwwAnjxKGAUbUEBpqLobU1gAC9WnJQxiYGpzBm59qWVqLWBrX0j4+nZ5nnF5aKbqJ7JEAeBp-CAG1JlEmMpOmAMERUnAQQEmPooGROlBMDC4S9WiiUFcBgBdOCSRzCMQwD6RT6LEIAD16EQG4kkNBofyiYCqrIGNGAbHGiiqDWOAWE4Ag2R6QKYGy2u3QIjGTDxIM+DI59KFtB5rD5TGqgqFIsg4uegIS1mGBAVSqFlA+zSiViS9k5cGErHYnH28RJ7S6crE+qiVII1Pi2myACZAwF2S6AtzeWHI+zo1FDWKoZLHRarfbVnmotU45rE8xw8AI3qCwN08agXjq3AVU2KQImog4FIZAQmwBKUwkiyVKqOBQudyeWK+SJBEKsVkGLxxZjD0SBzJQbK5ZgFAslEjkZ5MYe1er2z6tX3dOn9L5EqqHdX-U5H16XO1FbPJR+359nF4XO8+ZFEoECqJwP4ggCAELO+wH-Bg7AutBuqAbiTYFrwwTLr+XwvucsFAdcFL2sGtKiKyoHgTALpuh6-rxBAG6kG4qaxk+xwJtq8Qpo2woMEamZwKaVFqFayqNkWHFclqOpVhitZCaaw7iTaH4DES2TaC4fK4fx7pqF6wkYkwPoLH6+xrrgJmacA2n6Gga4ggSRKuuYMCNmRSYVmxap6VEXE6uWEa8QpAkZhKwlmk6lrcIqjbNgEUn+fGsneZWAp8W5op1lFokQXFDYSeSjRtrgCCdtIsiUL2JhmKScD5TAACyei8FkTjjh4MQ+Les5hBxi6xDxKhqK1IDtZu65ZEZTC7kU+5lEeJ51IKF5tOZ14UYNQzfrpUH4TBbzoc2TWQUKKFvkRjQFnczz+ZdaHqRhkRkTeRT6BNWS0RABmetuUrMTyri+cWgU8ZlYU5UpTBnYVxVCslGLgy8kMatlgmRaaX6jPDanwWyo2cNt-l0YZ27AujpkiFe-pWbCVO2fZi5OUKLnEu5nkoDS6Wg9JAVpWWyZoxqilY9FOaFQlkl+cjgtMMF8no2LJpFTaBa2qV7YVV21W1bC9UWAAKveACCdSdW4+ClIevg4w4uCrrgTXjZNog1XVJvVObYAAHRk-9YiRP7NObXTdu7bj8QAFJINSEDoGQTA1cH2gQN4tVAA)
2021
+
1957
2022
  ```typescript
1958
2023
  // assignments
1959
2024
  const results = await TaskApp.collections
1960
- .assignmenets({employeeId: "JExotic"})
2025
+ .assignments({employeeId: "JExotic"})
1961
2026
  .go();
1962
2027
 
1963
2028
  // results
@@ -1978,6 +2043,8 @@ const results = await TaskApp.collections
1978
2043
  }
1979
2044
  ```
1980
2045
 
2046
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoMhBQBneDACGvdnAC8zMPQBWHGCEkpJAcwIgCaJgG4BQkeLh6wrCJgIFR8uCgIB3OKnRYAFAgFw4EAhuNgAuRH8AyzQMTHCWcBs7ByZsSIDiIlFgEXiARlT0uFEiUgp4qVEAa0kwMEKAyjSAyRguYF4AVxgHcL8oy0TbewBJbj6igKwwAnjxKGAUbUEBpqLobU1gAC9WnJQxiYGpzBm59qWVqLWBrX0j4+nZ5nnF5aKbqJ7JEAeBp-CAG1JlEmMpOmAMERUnAQQEmPooGROlBMDC4S9WiiUFcBgBdOCSRzCMQwD6RT6LEIAD16EQG4kkNBofyiYCqrIGNGAbHGiiqDWOAWE4Ag2R6QKYGy2u3QIjGTDxIM+DI59KFtB5rD5TGqgqFIsg4uegIS1mGBAVSqFlA+zSiViS9k5cGErHYnH28RJ7S6crE+qiVII1Pi2myACZAwF2S6AtzeWHI+zo1FDWKoZLHRarfbVnmotU45rE8xw8AI3qCwN08agXjq3AVU2KQImog4FIZAQmwBKUwkiyVKqOBQudyeWK+SJBEKsVkGLxxZjD0SBzJQbK5ZgFAslEjkZ5MYe1er2z6tX3dOn9L5EqqHdX-U5H16XO1FbPJR+359nF4XO8+ZFEoECqJwP4ggCAELO+wH-Bg7AutBuqAbiTYFrwwTLr+XwvucsFAdcFL2sGtKiKyoHgTALpuh6-rxBAG6kG4qaxk+xwJtq8Qpo2woMEamZwKaVFqFayqNkWHFclqOpVhitZCaaw7iTaH4DES2TaC4fK4fx7pqF6wkYkwPoLH6+xrrgJmacA2n6Gga4ggSRKuuYMCNmRSYVmxap6VEXE6uWEa8QpAkZhKwlmk6lrcIqjbNgEUn+fGsneZWAp8W5op1lFokQXFDYSeSjRtrgCCdtIsiUL2JhmKScD5TAACyei8FkTjjh4MQ+Les5hBxi6xDxKhqK1IDtZu65ZEZTC7kU+5lEeJ51IKF5tOZ14UYNQzfrpUH4TBbzoc2TWQUKKFvkRjQFnczz+ZdaHqRhkRkTeRT6BNWS0RABmetuUrMTyri+cWgU8ZlYU5UpTBnYVxVCslGLgy8kMatlgmRaaX6jPDanwWyo2cNt-l0YZ27AujpkiFe-pWbCVO2fZi5OUKLnEu5nkoDS6Wg9JAVpWWyZoxqilY9FOaFQlkl+cjgtMMF8no2LJpFTaBa2qV7YVV21W1bC9UWAAKveACCdSdW4+ClIevg4w4uCrrgTXjZNog1XVJvVObYAAHRk-9YiRL7TMoA5MCiHbu24-EABSSDUhA6BkEwNXB9oEDeL2QA)
2047
+
1981
2048
  Looking above we can see that the `assignments` collection is actually a subset of the results that could be queried with the `contributions` collection. The power behind having the `assignments` sub-collection is the flexibility to further slice and dice your cross-entity queries into more specific and performant queries.
1982
2049
 
1983
2050
  > If you're interested in the naming used in the collection and access pattern definitions above, checkout the section on [Naming Conventions](#index-and-collection-naming-conventions)
@@ -2098,7 +2165,7 @@ Building thoughtful indexes can make queries simple and performant. Sometimes yo
2098
2165
  ```
2099
2166
  ### Defined on the model
2100
2167
 
2101
- > Deprecated but functional as with 1.0.
2168
+ > Deprecated but functional with 1.x
2102
2169
 
2103
2170
  Filters can be defined on the model and used in your query chain.
2104
2171
 
@@ -2151,6 +2218,9 @@ let stores = await MallStores.query
2151
2218
  }
2152
2219
  ```
2153
2220
  ### Defined via Filter method after query operators
2221
+
2222
+ > Filters are no longer the preferred way to add FilterExpressions. Checkout the [Where](#where) section to find out about how to apply FilterExpressions and ConditionExpressions.
2223
+
2154
2224
  The easiest way to use filters is to use them inline in your query chain.
2155
2225
 
2156
2226
  ```javascript
@@ -2211,6 +2281,9 @@ operator | example | result
2211
2281
  This functionality allows you to write the remaining logic of your `FilterExpression` with ease. Add complex nested `and`/`or` conditions or other `FilterExpression` logic while ElectroDB handles the `ExpressionAttributeNames` and `ExpressionAttributeValues`.
2212
2282
 
2213
2283
  ### Multiple Filters
2284
+
2285
+ > Filters are no longer the preferred way to add FilterExpressions. Checkout the [Where](#where) section to find out about how to apply FilterExpressions and ConditionExpressions.
2286
+
2214
2287
  It is possible to chain together multiple filters. The resulting FilterExpressions are concatenated with an implicit `AND` operator.
2215
2288
 
2216
2289
  ```javascript
@@ -2262,65 +2335,100 @@ Building thoughtful indexes can make queries simple and performant. Sometimes yo
2262
2335
  Below is the traditional way you would add a `FilterExpression` to Dynamo's DocumentClient directly alongside how you would accomplish the same using the `where` method.
2263
2336
 
2264
2337
  ```javascript
2338
+ animals.query
2339
+ .exhibit({habitat: "Africa"})
2340
+ .where(({isPregnant, offspring}, {exists, eq}) => `
2341
+ ${eq(isPregnant, true)} OR ${exists(offspring)}
2342
+ `)
2343
+ .go()
2344
+ ```
2345
+
2346
+ ```json
2265
2347
  {
2266
- KeyConditionExpression: '#pk = :pk and begins_with(#sk1, :sk1)',
2267
- TableName: 'zoodirectory',
2268
- ExpressionAttributeNames: {
2269
- '#animal': 'animal',
2270
- '#lastFed': 'lastFed',
2271
- '#pk': 'pk',
2272
- '#sk1': 'sk'
2348
+ "KeyConditionExpression": "#pk = :pk and begins_with(#sk1, :sk1)",
2349
+ "TableName": "zoo_manifest",
2350
+ "ExpressionAttributeNames": {
2351
+ "#isPregnant": "isPregnant",
2352
+ "#offspring": "offspring",
2353
+ "#pk": "gsi1pk",
2354
+ "#sk1": "gsi1sk"
2273
2355
  },
2274
- ExpressionAttributeValues: {
2275
- ':animal_w1': 'Warthog',
2276
- ':lastFed_w1': '2020-09-25',
2277
- ':lastFed_w2': '2020-09-28',
2278
- ':pk': '$zoodirectory_1#habitat_africa',
2279
- ':sk1': '$exibits#enclosure_'
2356
+ "ExpressionAttributeValues": {
2357
+ ":isPregnant0": true,
2358
+ ":pk": "$zoo#habitat_africa",
2359
+ ":sk1": "$animals_1#enclosure_"
2280
2360
  },
2281
- FilterExpression: '#animal = :animal_w1 AND (#lastFed between :lastFed_w1 and :lastFed_w2)'
2361
+ "IndexName": "gsi1pk-gsi1sk-index",
2362
+ "FilterExpression": "#isPregnant = :isPregnant0 OR attribute_exists(#offspring)"
2282
2363
  }
2283
2364
  ```
2284
2365
 
2285
- ```javascript
2286
- animals.query
2287
- .farm({habitat: "Africa"})
2288
- .where(({animal, dangerous}, {value, name, between}) => `
2289
- ${name(animal)} = ${value(animal, "Warthog")} AND ${between(dangerous, "2020-09-25", "2020-09-28")}
2290
- `)
2291
- .go()
2292
- ```
2366
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=91&ssc=8&pln=86&pc=1#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoAWQgoAzvACGKUJNZi4AXjgoCAdzip0WABQIBcOCAjc2ALkQHD1sUVIULTAF4QITbFetwCaDJkfSsvLuntbERGLAoo4AjCGGlB6GkjBcwLwArjAEYhb6XgAWkrwYKXmhhlhgBBYA2kwAgnTkku7MDVCc5G1MAEqSwCgAYtA5MEwAuklecFAEAI4ZwHPcFlwZBNMJW94oZKwQYhlz5TNwVTXMElCDAObx1omhgSBypzMXjtd3D15zi8sCKtzlANjsnl4UJIQJd8h9MNUvmkUPdQhDrKxJBIhkD3l5PldkaivOjDJjsUCAEL+SxnAlMb4owQknbcaS3IgQDK5WnwxHMXiudjSX5wUlwYBiAAKc1uULQeOs9MFEGFKGZjx2JVgBTZNLh+IRlwZRI121C3GABBgisqRq+1tFhgwBBAPJNNyZaJ2EBoNDEYE9t1t53tzFYkvGO2d2TdIbt-KYrzATusgYg1VgVp5BrOKmhsIqefpjOJefN5cM2pgusk+qLdLDHp+Dc1rcMKAg2XjfONpbNecoraHZxHbYrEpQpgAHjlFQGOKAfCGwABrHuGGhW1jAphr1NeETgQ4uupMF5ySbRsXXsTr3nlrdsXd3g-WI+QSLduD1KEwyZFmOE6GAQ04FOkGAhoMM6OLckQxGuAC0cHADEd6IdBoGpmuG60Nuu4oQhq5voYH4nt+9RFCUMApFegG3veuZnE+O6wfBr7XoeDCfqeP4sHsBxHHMPTkjAOLcABo7elYTyJIgNG8OwjguBAAD6rwyDQYxMJQACUADcQgXvIAB0ixEJgVgmaB4HUXoVGlDa7TNGQrR6VZagFEQBA6HokoygQcrSDAuC+v6gZ3HJCCgZGYi4AselKAAfHAAAGoQACTRfMOj+bK8ohSCGy6dQADyvRwFlMUSGIOhhQGQYlVYqW6VZtwQDoBkCEAA)
2293
2367
 
2294
2368
  ### ConditionExpressions
2295
2369
 
2296
2370
  Below is the traditional way you would add a `ConditionExpression` to Dynamo's DocumentClient directly alongside how you would accomplish the same using the `where` method.
2297
2371
 
2298
2372
  ```javascript
2373
+ animals.update({
2374
+ animal: "blackbear",
2375
+ name: "Isabelle"
2376
+ })
2377
+ // no longer pregnant because Ernesto was born!
2378
+ .set({
2379
+ isPregnant: false,
2380
+ lastEvaluation: "2021-09-12",
2381
+ lastEvaluationBy: "stephanie.adler"
2382
+ })
2383
+ // welcome to the world Ernesto!
2384
+ .append({
2385
+ offspring: [{
2386
+ name: "Ernesto",
2387
+ birthday: "2021-09-12",
2388
+ note: "healthy birth, mild pollen allergy"
2389
+ }]
2390
+ })
2391
+ // using the where clause can guard against making
2392
+ // updates against stale data
2393
+ .where(({isPregnant, lastEvaluation}, {lt, eq}) => `
2394
+ ${eq(isPregnant, true)} AND ${lt(lastEvaluation, "2021-09-12")}
2395
+ `)
2396
+ .go()
2397
+ ```
2398
+
2399
+ ```json
2299
2400
  {
2300
- UpdateExpression: 'SET #dangerous = :dangerous',
2301
- ExpressionAttributeNames: { '#animal': 'animal', '#dangerous': 'dangerous' },
2302
- ExpressionAttributeValues: {
2303
- ':animal_w1': 'Zebra',
2304
- ':dangerous_w1': false,
2305
- ':dangerous': true
2401
+ "UpdateExpression": "SET #isPregnant = :isPregnant_u0, #lastEvaluation = :lastEvaluation_u0, #lastEvaluationBy = :lastEvaluationBy_u0, #offspring = list_append(#offspring, :offspring_u0)",
2402
+ "ExpressionAttributeNames": {
2403
+ "#isPregnant": "isPregnant",
2404
+ "#lastEvaluation": "lastEvaluation",
2405
+ "#lastEvaluationBy": "lastEvaluationBy",
2406
+ "#offspring": "offspring"
2306
2407
  },
2307
- TableName: 'zoodirectory',
2308
- Key: {
2309
- pk: '$zoodirectory_1#habitat_africa',
2310
- sk: '$exibits#enclosure_5b'
2408
+ "ExpressionAttributeValues": {
2409
+ ":isPregnant0": true,
2410
+ ":lastEvaluation0": "2021-09-12",
2411
+ ":isPregnant_u0": false,
2412
+ ":lastEvaluation_u0": "2021-09-12",
2413
+ ":lastEvaluationBy_u0": "stephanie.adler",
2414
+ ":offspring_u0": [
2415
+ {
2416
+ "name": "Ernesto",
2417
+ "birthday": "2021-09-12",
2418
+ "note": "healthy birth, mild pollen allergy"
2419
+ }
2420
+ ]
2311
2421
  },
2312
- ConditionExpression: '#animal = :animal_w1 AND #dangerous = :dangerous_w1'
2422
+ "TableName": "zoo_manifest",
2423
+ "Key": {
2424
+ "pk": "$zoo#animal_blackbear",
2425
+ "sk": "$animals_1#name_isabelle"
2426
+ },
2427
+ "ConditionExpression": "#isPregnant = :isPregnant0 AND #lastEvaluation < :lastEvaluation0"
2313
2428
  }
2314
2429
  ```
2315
2430
 
2316
- ```javascript
2317
- animals.update({habitat: "Africa", enclosure: "5b"})
2318
- .set({dangerous: true})
2319
- .where(({animal, dangerous}, {value, name, eq}) => `
2320
- ${name(animal)} = ${value(animal, "Zebra")} AND ${eq(dangerous)}
2321
- `)
2322
- .go()
2323
- ```
2431
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=96&ssc=50&pln=96&pc=3#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoAWQgoAzvACGKUJNZi4AXjgoCAdzip0WABQIBcOCAjc2ALkQHD1sUVIULTAF4QITbFetwCaDJkfSsvLuntbERGLAoo4AjCGGlB6GkjBcwLwArjAEYhb6XgAWkrwYKXmhhlhgBBYA2kwAgnTkku7MDVCc5G1MAEqSwCgAYtA5MEwAuklecFAEAI4ZwHPcFlwZBNMJW94oZKwQYhlz5TNwVTXMElCDAObx1omhgSBypzMXjtd3D15zi8sCKtzlANjsnl4UJIQJd8h9MNUvmkUPdQhDrNxpLciBAMrlLGdPsxeK52NJfnB0YZgGIAApzW5QtDvLxEpgkiBklCCLxUuAlWAFTH+AnwxFXZGo3k7bjAAgwFnWNm2cY7anZED4pjfFE8x47CA0GhiMA3FGKyoIy5MVg01UVOAYAiai1Kq2OV5gCleU0QaqwOX4uFnQxQmGuwnuiVmqUh7YOrwCmBCyQi4Nx85R7WSvVxvlnFAQbIRsXWnWxvMJykOyhonasSQSIZA13KnN10INptAgBCaYdbZjucp9cbMCQxDkGRSURQraz5eHfK748nrGn6FEffn4uzQ7RVnRg1MAA8coqTRxQD5XWAANYlww0OWsYFMe-emYicCHJ11JgvHIkxqiODpiA+opxs+bBvuBn5eN+kCRMWcD1GGBCTDWHZeAQJ4FOkGCuseuGOLckQxPeAC0ZHADE4GUcRJ6fvej60C+b40RRd7wdYiG-ih9RFCUMApMBNYgeBrHQa+pHkXBIEIQwSF-qhLB7AcRxzD0K7NtwmFnLW0qHh4iSICJvDsI4LgQAA+q8Mg0GMTCUAAlAA3EIgHyAAdBkYCYtkejPDIrysI4FmSGQd68AQkhQBS6GOAAkmIxRsOwequVYAD02UqBAcAHCiRBwKaBCMtI8AxWQkh4gQmhQKoEgFWojb8tAKAAIRWN5Kp6HAoQ0vS5VMgqtByLYo4SBOU4ztEzAAEwAAwLTElFLQAnJRMQLRSK4zeuc0oNuEoEGARQyAQ3mSNw7DxYeLk5XlahsN+9UwAVyb1Wo0Cvg1TUfd1hjXWA1QoNw-WhIaxqmncdTpqG0LWkgjVjG4IFJimIpMMtq3rVtO2foWKFMAUsWsMmmD8ssya4CAwB-ZArDsCgcByHdtyYEuEwPU9cB4nc5xk3Aahk3McD7LVtgS9IcC3NOUDcGztwDOI8CvHedx835AU5MrqsSHAEhyPVAWSD1otEAQOh6ENDKjbg+1rhus6mQgFO4AsrlKAAfHAAAGoQACQIAsOh2yNlW4OsBAudQDQAHIACJwCHFM6E7s2biguA4yta2bdtu1x1Y-uPcDtwQDo7kCEAA)
2324
2432
 
2325
2433
  ### Where with Complex Attributes
2326
2434
 
@@ -2333,29 +2441,23 @@ The following are examples on how to filter on complex attributes:
2333
2441
  ```javascript
2334
2442
  animals.query
2335
2443
  .farm({habitat: "Africa"})
2336
- .where(({veterinarian}, {eq, between}) => eq(veterinarian.name, "Herb Peterson"))
2444
+ .where(({veterinarian}, {eq}) => eq(veterinarian.name, "Herb Peterson"))
2337
2445
  .go()
2338
2446
  ```
2339
2447
 
2340
- **Example 1: Filtering on an element in a `list` attribute**
2341
-
2342
- ```javascript
2343
- animals.update({habitat: "Africa", enclosure: "5b"})
2344
- .where(({handlers}, {eq}) => eq(handlers[0], "jerry"))
2345
- .go()
2346
- ```
2448
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoAWQgoAzvACGKUJNZi4AXjgoCAdzip0WABQIBcOCAjc2ALkQHD1sUVIULTAF4QITbFetwCaDJkfSsvLuntbERGLAoo4AjCGGlB6GkjBcwLwArjAEYhb6XgAWkrwYKXmhhlhgBBYA2kwAgnTkku7MDVCc5G1MAEqSwCgAYtA5MEwAuklecFAEAI4ZwHPcFlwZBNMJW94oZKwQYhlz5TNwVTXMElCDAObx1omhgSBypzMXjtd3D15zi8sCKtzlANjsnl4UJIQJd8h9MNUvmkUPdQhDrNxpLciBAMrlLGdPsxeK52NJfnB0YZgGIAApzW5QtDvLxEpgkiBklCCLxUuAlWAFTH+AnwxFXZGo3k7bjAAgwFnWNm2cY7anZED4pjfFE8x47CA0GhiMA3FGKyoIy5MVg01UVOAYAiai1Kq2OV5gCleU0QaqwOX4uFnQxQmGuwnuiVmqUh7YOrwCmBCyQi4Nx85R7WSvVxvlnFAQbIRsXWnWxvMJykOyhonbhbJmyQ3aSutme71wX3+9A5Eth2FVy3i7Mx3MzfM2apkYByLAl4dlnNV2tnVf60KsSQSIZAttZ8vjvlbndAgBCaYdyuX0s325gSGIcgyKSiKH3I8PdbvEkfz9fogXh+S5jmiVjooMpgAB59qKhgmhwoA+K6YAANYLrQcqsMCTBoZ2XgiOAhxOnUTAvHIkxqpSVFiOhcEhjQWE4bR+HWIRkCRMWcD1AOkw1t+XgEFBBTpBgrqQUJji3JEMRoQAtNJwAxLRckSVBnZoRhjFsDhimyahrGGOxxFcfURQlDAKSUTWNF0emZzadhUkySxVEEQwHEkdxLB7AcRxzD0J4wLu3B8WuAnUQIiSIJZvDsI4LgQAA+q8Mg0GMTCUAAlAA3EI5HyAAdIsRCYFYhVCSJFl6OZpQKu0zRkK02XlWoBREAQOh6A2RCDM2s4oNFCALNlSgAHzePMOg9U2LYoIVA64EwAASRC8HAtLyhEohMFlWXlbcEA6PtAhAA)
2347
2449
 
2348
- **Example 3: Filtering on the a `set` item ("veal"), with a `map` attribute property ("meat"), that is an element of a `list` attribute ("meals")**
2450
+ **Example 1: Filtering on an element in a `list` attribute**
2349
2451
 
2350
2452
  ```javascript
2351
2453
  animals.query
2352
- .farm({habitat: "Africa"})
2353
- .where(({meals}, {exists, between}) => `
2354
- ${exists(meals[0].meat.veal)} AND ${between(meals[0].schedule, '6:00', '7:00')}
2355
- `)
2356
- .go()
2454
+ .exhibit({habitat: "Tundra"})
2455
+ .where(({offspring}, {eq}) => eq(offspring[0].name, "Blitzen"))
2456
+ .go()
2357
2457
  ```
2358
2458
 
2459
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=106&ssc=8&pln=103&pc=1#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoAWQgoAzvACGKUJNZi4AXjgoCAdzip0WABQIBcOCAjc2ALkQHD1sUVIULTAF4QITbFetwCaDJkfSsvLuntbERGLAoo4AjCGGlB6GkjBcwLwArjAEYhb6XgAWkrwYKXmhhlhgBBYA2kwAgnTkku7MACoZKNxQrbhMAEqSwCgAYtA5MEwAuklecFAEAI4ZwIvcFlwZBHMJu94oZKwQYhmL5fNwVTXMElAjAObx1omhgSByF-PXjnePz15Fis1gQNlcoNt9q8vChJCAbvlvphqr80ignqFodZuNIHkQIBlcpZLj9mLxXOxpAC4FjDMAxAAFRYPWFoL5eUlMckQSkoQReWlwEqwAo4-zEpEo25ojEC-bcYAEGDs6yc2xTfZ07IgIlMP7o-kvfYQGg0MRge7olWVZE3JisekaipwDAEHXW1W2xwfMDUrwWiDVWCKomIy6GWHwj0kr3Sy2y8N7Z1eYUwUWScVhxNXWN6mWGxOCy4oCDZaOSu36hOF5M052UTH7cLZS2Se7SD2cn1+uABoPoHLlyMI2s2qV5+MF+ZFmzVMjAORYctjyv52sNy4bo2hViSCSjUGd3NVqeC3f70EAIUzzrVa7lO73MCQxDkGRSURQR-HJ8bj4kL5vh+ojXt+q6TpiVhYiMpgAB6DhKhjmhwoA+B6YAANbLrQiqsGCTCYT2XgiOAJyunUTDvHIMyajStFiFhiHhjQuH4QxRHWCRkCRGWcD1MOMz1n+XgELBBTpBgHowaJjgPJEMSYQAtHJwAxAxinSbBPaYdhLFsPhKkKRhHGGFxZG8fURQlDAKQ0fW9GMVmlx6XhsnyextHEQw3HkXxLCHMcpyLG09pPge3CCZuwl0QIiSIDZvDsI4LgQAA+h8Mg0JMTCUAAlAA3EIVHyAAdCsRCYFYJWieJ1l6FZpTKh0XQ9K0eVVWoBREAQOh6CaZoWo8cUIMseVKAAfN4Sw6P15rxrUAAM0wlcO-SXg6MBOD4TC5blVUPBAOi5UAA)
2460
+
2359
2461
  ### Attributes and Operations
2360
2462
 
2361
2463
  Where functions allow you to write a `FilterExpression` or `ConditionExpression` without having to worry about the complexities of expression attributes. To accomplish this, ElectroDB injects an object `attributes` as the first parameter to all Filter Functions, and an object `operations`, as the second parameter. Pass the properties from the `attributes` object to the methods found on the `operations` object, along with inline values to set filters and conditions.
@@ -2365,34 +2467,56 @@ Where functions allow you to write a `FilterExpression` or `ConditionExpression`
2365
2467
  ```javascript
2366
2468
  // A single filter operation
2367
2469
  animals.update({habitat: "Africa", enclosure: "5b"})
2368
- .set({keeper: "Joe Exotic"})
2369
- .where((attr, op) => op.eq(attr.dangerous, true))
2370
- .go();
2470
+ .set({keeper: "Joe Exotic"})
2471
+ .where((attr, op) => op.eq(attr.dangerous, true))
2472
+ .go();
2371
2473
 
2372
- // A single filter operation
2373
- animals.update({habitat: "Africa", enclosure: "5b"})
2374
- .set({keeper: "Joe Exotic"})
2375
- .where((attr, op) => op.eq(attr.dangerous, true))
2376
- .go();
2474
+ // A single filter operation w/ destructuring
2475
+ animals.update({animal: "tiger", name: "janet"})
2476
+ .set({keeper: "Joe Exotic"})
2477
+ .where(({dangerous}, {eq}) => eq(dangerous, true))
2478
+ .go();
2377
2479
 
2378
2480
  // Multiple conditions - `op`
2379
- animals.update({habitat: "Africa", enclosure: "5b"})
2380
- .set({keeper: "Joe Exotic"})
2381
- .where((attr, op) => `
2382
- ${op.eq(attr.dangerous, true)} AND ${op.contains(attr.diet, "meat")}
2383
- `)
2384
- .go();
2481
+ animals.update({animal: "tiger", name: "janet"})
2482
+ .set({keeper: "Joe Exotic"})
2483
+ .where((attr, op) => `
2484
+ ${op.eq(attr.dangerous, true)} AND ${op.notExists(attr.lastFed)}
2485
+ `)
2486
+ .go();
2385
2487
 
2386
2488
  // Multiple usages of `where` (implicit AND)
2387
- animals.update({habitat: "Africa", enclosure: "5b"})
2388
- .set({keeper: "Joe Exotic"})
2389
- .where((attr, op) => `
2390
- ${op.eq(attr.dangerous, true)} AND ${op.contains(attr.diet, "meat")}
2391
- `)
2392
- .where((attr, op)) => op.betweem(attr.schedule, "05:30", "19:00"))
2393
- .go();
2489
+ animals.update({animal: "tiger", name: "janet"})
2490
+ .set({keeper: "Joe Exotic"})
2491
+ .where((attr, op) => `
2492
+ ${op.eq(attr.dangerous, true)} OR ${op.notExists(attr.lastFed)}
2493
+ `)
2494
+ .where(({birthday}, {between}) => {
2495
+ const today = Date.now();
2496
+ const lastMonth = today - 1000 * 60 * 60 * 24 * 30;
2497
+ return between(birthday, lastMonth, today);
2498
+ })
2499
+ .go();
2500
+
2501
+ // "dynamic" filtering
2502
+ function getAnimals(habitat, keepers) {
2503
+ const query = animals.query.exhibit({habitat});
2504
+ for (const name of keepers) {
2505
+ query.where(({keeper}, {eq}) => eq(keeper, name));
2506
+ }
2507
+ return query.go();
2508
+ }
2509
+
2510
+ const keepers = [
2511
+ "Joe Exotic",
2512
+ "Carol Baskin"
2513
+ ];
2514
+
2515
+ getAnimals("RainForest", keepers);
2394
2516
  ```
2395
2517
 
2518
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoAWQgoAzvAAWAQ14ZpMMXAC8cANpMAgnXLSmuLVE7l9zAErTgKAGLQCEpgF040pSPEwA3AKxgCcAAlZeXhVXwIIGjgZORgFMTUUAFcQXiJHb2FRCRcUUGlWJVUUAgB3OFR0LAAKBAE4OBAIbjYALkR6hq6xIlIKdqYALwgIfU6uuAI0DEwB6TyQArExiYbiIjFgUQGARhW4SmxOhS5gXiSYe3a6iZiQ6-Gu8Pa7uMUj1bgoAgBHJOBvtx2lwkgQPl1Do8pmRWBAxElvg9Ps9mBIoFYAOb7BqQibzfKsJGrFFMNGY7Fdb5-AEEIFwEFgx64rooaQgAhEiYkskoLFM8ENbjzDFECBJMScp6YPwDXgjdjzCnMhrAMQABW+GNZaElDRJcogCpQggmyrgclgkiFsw6yOlHOYyVSRBNEIFcG4wAIMF19PtAx6MApKsuIAlqNOvNdOPdAGsCAQ-FBfdzI3zTe71pd0az0fMU-6Izn027HpEaGIwMWCzLmKxVUH3SGCGHfXrC0xFmBg10qxAk+grrbPiy2Q6biOuR2eSXJ2bPhaYFbpDaJ5P27XSWnoyP56sUBBLm3idPt49PpRzxCr5eM49WK4YNZaTWHVvizuzQ+JM-uAAhVcr1TD9+XvR8kGIAokgULYUFfAMzzvCZvxgCCoJg0QAPgotySZTpmSsFoAA8hzXOBKw4UApl9MBY2PBoaC9Vg6SYWiewmERwDhDAHQ0fFFlYJwmwOYSxDo4dJ0YtgWLE9iuk4yBNiPdQmFZdknBvUCJgIIjJDODBfUInSBgxTYdlogBaUzgB2MSLKMoie1o+jaCYljrPM2M5IaBTuOUjRXgUISb1E8SyM+KTmJMszZOEjiGEUnj2g0aFYXhb5TCYFDfw0i8tJEgRDkQOJeHYAZhggAB9RY8hoewg0oABKTIAHoACo2vqNq4AANWkPN0GyOBRGiCBykwMU4DIeY4HFfwl38AADUpJCIAhFqmh85q6lqhBalq4E0cjMXYVzWGzYakwwlA4AEfilgAOiSMAhUuWp7sJZh0BFKBTDUt8ACt5m9JgmoEABIB7A1qeNEyIAYACkIH8JAiMPEwwYaB6VrW6pqhOKBcH7RqVAAPkuh7fnxmAuAeoVeVFcVcAZRrGs6B6MQgapmr2g6js2XlTsY86iEuohrrgUoDpaNEkk4BFMTuhZHue16CHe5XPqYb6XVwf6BiBkoGrZyHoYQWGk0R5GKjR9AyFBtmsZx748YQemfrFMQioQX4mrJyYfmqd3GbEZmoFBVn2c57nWoOgBZJJzuAMBTvcT1BvEOALLgRb+0WpWCTEJ6XoUdWEA+gYdd+vWxwN4HjYhqHvRhhNLeYJGUdtjHHbgbHVpd6muCJsASeUcn84mAASBB+0pwOCbp4UQ7DiPqE0AA5AAROBp9ng9UKIhsxEHqAHuy2lGtvHOe45rmeYEfa4ATpOU-8cVpBFJRIhz531rgapQAp3IBgQ6W82YfSLqrUuGsCSV2AD9P6tdmCGxBmDU2zdzat3hu3a2qN0b20xr3X+eMCbD1HuPR4u8wBzxPovBm9Amb0nDgQS+cAADyZgd4z2ofvVGR9aHn24JfToi0b7ENqIuZcmBvZpBgKUBMKA-ZjwklNbI8AYDNBXCoOAm9S4PQPKUGOjx3A5BQnHUQS5tEaOtFnOAOwAAMji4DdQAGz2OcXANxHiABMAAWDxABmex3gJjfBgAiG6sj5FTGqJI60uAzEWMkMzTRmAeY4hvtHe+j8mDcEwGpEwZ1syKxoEkFAxgRoihgJoTWx9Ao+kCMEN4uALYbHaDONQjgSYThMfAP4RBMDaIgQ9fpUBMCU10vpGAtR6lNRCbQaA-9elwH+sNKIrSoBiG6Y8UZ4zxGYLhlAb2vtyEB2qBsmu7JWbzKvmEiJcBdm3yMZeLIHg4AbKKOoToTAO423wfsJgABhfqho4B-lcLGKwggMhCCqTUwu1QmAWCsLYb4DgWlYM2c1IAA)
2519
+
2396
2520
  The `attributes` object contains every Attribute defined in the Entity's Model. The `operations` object contains the following methods:
2397
2521
 
2398
2522
  operator | example | result
@@ -2576,13 +2700,7 @@ let schema = {
2576
2700
  composite: ["leaseEndDate"]
2577
2701
  }
2578
2702
  }
2579
- },
2580
- filters: {
2581
- byCategory: ({category}, name) => category.eq(name),
2582
- rentDiscount: (attributes, discount, max, min) => {
2583
- return `${attributes.discount.lte(discount)} AND ${attributes.rent.between(max, min)}`
2584
- }
2585
- }
2703
+ }
2586
2704
  };
2587
2705
  const StoreLocations = new Entity(schema, {table: "StoreDirectory"});
2588
2706
  ```
@@ -3012,6 +3130,99 @@ Update Method | Attribute Types
3012
3130
  [delete](#update-method-delete) | `any` `set` | `object`
3013
3131
  [data](#update-method-data) | `*` | `callback`
3014
3132
 
3133
+ #### Updates to Composite Attributes
3134
+
3135
+ ElectroDB adds some constraints to update calls to prevent the accidental loss of data. If an access pattern is defined with multiple composite attributes, then ElectroDB ensure the attributes cannot be updated individually. If an attribute involved in an index composite is updated, then the index key also must be updated, and if the whole key cannot be formed by the attributes supplied to the update, then it cannot create a composite key without overwriting the old data.
3136
+
3137
+ This example shows why a partial update to a composite key is prevented by ElectroDB:
3138
+
3139
+ ```json
3140
+ {
3141
+ "index": "my-gsi",
3142
+ "pk": {
3143
+ "field": "gsi1pk",
3144
+ "composite": ["attr1"]
3145
+ },
3146
+ "sk": {
3147
+ "field": "gsi1sk",
3148
+ "composite": ["attr2", "attr3"]
3149
+ }
3150
+ }
3151
+ ```
3152
+
3153
+ The above secondary index definition would generate the following index keys:
3154
+
3155
+ ```json
3156
+ {
3157
+ "gsi1pk": "$service#attr1_value1",
3158
+ "gsi1sk": "$entity_version#attr2_value2#attr3_value6"
3159
+ }
3160
+ ```
3161
+
3162
+ If a user attempts to update the attribute `attr2`, then ElectroDB has no way of knowing value of the attribute `attr3` or if forming the composite key without it would overwrite its value. The same problem exists if a user were to update `attr3`, ElectroDB cannot update the key without knowing each composite attribute's value.
3163
+
3164
+ In the event that a secondary index includes composite values from the table's primary index, ElectroDB will draw from the values supplied for the update key to address index gaps in the secondary index. For example:
3165
+
3166
+ For the defined indexes:
3167
+
3168
+ ```json
3169
+ {
3170
+ "accessPattern1": {
3171
+ "pk": {
3172
+ "field": "pk",
3173
+ "composite": ["attr1"]
3174
+ },
3175
+ "sk": {
3176
+ "field": "sk",
3177
+ "composite": ["attr2"]
3178
+ }
3179
+ },
3180
+ "accessPattern2": {
3181
+ "index": "my-gsi",
3182
+ "pk": {
3183
+ "field": "gsi1pk",
3184
+ "composite": ["attr3"]
3185
+ },
3186
+ "sk": {
3187
+ "field": "gsi1sk",
3188
+ "composite": ["attr2", "attr4"]
3189
+ }
3190
+ }
3191
+ }
3192
+ ```
3193
+
3194
+ A user could update `attr4` alone because ElectroDB is able to leverage the value for `attr2` from values supplied to the `update()` method:
3195
+
3196
+ ```typescript
3197
+ entity.update({ attr1: "value1", attr2: "value2" })
3198
+ .set({ attr4: "value4" })
3199
+ .go();
3200
+
3201
+ {
3202
+ "UpdateExpression": "SET #attr4 = :attr4_u0, #gsi1sk = :gsi1sk_u0, #attr1 = :attr1_u0, #attr2 = :attr2_u0",
3203
+ "ExpressionAttributeNames": {
3204
+ "#attr4": "attr4",
3205
+ "#gsi1sk": "gsi1sk",
3206
+ "#attr1": "attr1",
3207
+ "#attr2": "attr2"
3208
+ },
3209
+ "ExpressionAttributeValues": {
3210
+ ":attr4_u0": "value6",
3211
+ // This index was successfully built
3212
+ ":gsi1sk_u0": "$update-edgecases_1#attr2_value2#attr4_value6",
3213
+ ":attr1_u0": "value1",
3214
+ ":attr2_u0": "value2"
3215
+ },
3216
+ "TableName": "test_table",
3217
+ "Key": {
3218
+ "pk": "$service#attr1_value1",
3219
+ "sk": "$entity_version#attr2_value2"
3220
+ }
3221
+ }
3222
+ ```
3223
+
3224
+ > Note: Included in the update are all attributes from the table's primary index. These values are automatically included on all updates in the event an update results in an insert.
3225
+
3015
3226
  #### Update Method: Set
3016
3227
 
3017
3228
  The `set()` method will accept all attributes defined on the model. Provide a value to apply or replace onto the item.
@@ -4049,6 +4260,7 @@ By default, **ElectroDB** enables you to work with records as the names and prop
4049
4260
  unprocessed?: "raw" | "item";
4050
4261
  response?: "default" | "none" | "all_old" | "updated_old" | "all_new" | "updated_new";
4051
4262
  ignoreOwnership?: boolean;
4263
+ limit?: number;
4052
4264
  };
4053
4265
  ```
4054
4266
 
@@ -4063,7 +4275,8 @@ originalErr | `false` | By default, **ElectroDB** alters the st
4063
4275
  concurrent | `1` | When performing batch operations, how many requests (1 batch operation == 1 request) to DynamoDB should ElectroDB make at one time. Be mindful of your DynamoDB throughput configurations
4064
4276
  unprocessed | `"item"` | Used in batch processing to override ElectroDBs default behaviour to break apart DynamoDBs `Unprocessed` records into composite attributes. See more detail about this in the sections for [BatchGet](#batch-get), [BatchDelete](#batch-write-delete-records), and [BatchPut](#batch-write-put-records).
4065
4277
  response | `"default"` | Used as a convenience for applying the DynamoDB parameter `ReturnValues`. The options here are the same as the parameter values for the DocumentClient except lowercase. The `"none"` option will cause the method to return null and will bypass ElectroDB's response formatting -- useful if formatting performance is a concern.
4066
- ignoreOwnership | `false` | By default, **ElectroDB** interrogates items returned from a query for the presence of matching entity "identifiers". This helps to ensure other entities, or other versions of an entity, are filtered from your results. If you are using ElectroDB with an existing table/dataset you can turn off this feature by setting this property to `true`.
4278
+ ignoreOwnership | `false` | By default, **ElectroDB** interrogates items returned from a query for the presence of matching entity "identifiers". This helps to ensure other entities, or other versions of an entity, are filtered from your results. If you are using ElectroDB with an existing table/dataset you can turn off this feature by setting this property to `true`.
4279
+ limit | _none_ | A convenience option for the query parameter `Limit`, used to specify the number of records to retrieve while performing a query.
4067
4280
 
4068
4281
  # Errors:
4069
4282
 
@@ -4986,7 +5199,7 @@ type EntityRecord<E extends Entity<any, any, any, any>> =
4986
5199
 
4987
5200
  _Use:_
4988
5201
  ```typescript
4989
- type MyEntity = EntityRecord<typeof MyService, "mycollection">
5202
+ type EntiySchema = EntityRecord<typeof MyEntity>
4990
5203
  ```
4991
5204
 
4992
5205
  ## EntityItem Type