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/CHANGELOG.md +28 -4
- package/README.md +351 -138
- package/browser.js +53 -0
- package/bundle.js +9962 -0
- package/index.d.ts +10 -9
- package/notes +935 -29
- package/package.json +1 -1
- package/src/clauses.js +0 -18
- package/src/entity.js +23 -1
- package/src/schema.js +4 -1
- package/index.test-d.ts +0 -3829
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
|
-
|
|
12
|
+
------------
|
|
13
13
|
|
|
14
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
"
|
|
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
|
-
"#
|
|
54
|
-
"#
|
|
55
|
-
"#
|
|
56
|
-
"#
|
|
66
|
+
"#status": "status",
|
|
67
|
+
"#points": "points",
|
|
68
|
+
"#comments": "comments",
|
|
69
|
+
"#updatedAt": "updatedAt",
|
|
70
|
+
"#gsi1sk": "gsi1sk"
|
|
57
71
|
},
|
|
58
72
|
"ExpressionAttributeValues": {
|
|
59
|
-
":
|
|
60
|
-
":
|
|
61
|
-
":
|
|
62
|
-
":
|
|
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
|
-
"
|
|
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
|
+
[](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
|
+
[](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: "
|
|
831
|
-
service: "
|
|
856
|
+
entity: "products",
|
|
857
|
+
service: "estimator",
|
|
832
858
|
version: "1"
|
|
833
859
|
},
|
|
834
860
|
attributes: {
|
|
835
|
-
|
|
861
|
+
product: {
|
|
836
862
|
type: "string"
|
|
837
863
|
},
|
|
838
864
|
price: {
|
|
839
865
|
type: "number",
|
|
840
|
-
|
|
866
|
+
required: true
|
|
841
867
|
},
|
|
842
868
|
fee: {
|
|
843
869
|
type: "number",
|
|
844
|
-
|
|
845
|
-
|
|
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
|
-
|
|
880
|
+
composite: ["product"]
|
|
855
881
|
},
|
|
856
882
|
sk: {
|
|
857
883
|
field: "sk",
|
|
858
|
-
|
|
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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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"
|
|
1395
|
-
}
|
|
1435
|
+
type: "string"
|
|
1436
|
+
},
|
|
1437
|
+
productNumber: {
|
|
1438
|
+
type: "number"
|
|
1439
|
+
}
|
|
1396
1440
|
},
|
|
1397
1441
|
indexes: {
|
|
1398
|
-
|
|
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
|
+
[](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
|
|
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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
+
[](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
|
-
.
|
|
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
|
+
[](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
|
|
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:
|
|
2267
|
-
TableName:
|
|
2268
|
-
ExpressionAttributeNames: {
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
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
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
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
|
-
|
|
2361
|
+
"IndexName": "gsi1pk-gsi1sk-index",
|
|
2362
|
+
"FilterExpression": "#isPregnant = :isPregnant0 OR attribute_exists(#offspring)"
|
|
2282
2363
|
}
|
|
2283
2364
|
```
|
|
2284
2365
|
|
|
2285
|
-
|
|
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
|
+
[](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:
|
|
2301
|
-
ExpressionAttributeNames: {
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
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
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
[](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
|
|
2444
|
+
.where(({veterinarian}, {eq}) => eq(veterinarian.name, "Herb Peterson"))
|
|
2337
2445
|
.go()
|
|
2338
2446
|
```
|
|
2339
2447
|
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
```javascript
|
|
2343
|
-
animals.update({habitat: "Africa", enclosure: "5b"})
|
|
2344
|
-
.where(({handlers}, {eq}) => eq(handlers[0], "jerry"))
|
|
2345
|
-
.go()
|
|
2346
|
-
```
|
|
2448
|
+
[](https://electrodb.fun/?#code/JYWwDg9gTgLgBAbwKIDsbBgTwDRwMoCmUAbsAMYEC+cAZlBCHAEQEA2BZM9AJgEZMAoAWQgoAzvACGKUJNZi4AXjgoCAdzip0WABQIBcOCAjc2ALkQHD1sUVIULTAF4QITbFetwCaDJkfSsvLuntbERGLAoo4AjCGGlB6GkjBcwLwArjAEYhb6XgAWkrwYKXmhhlhgBBYA2kwAgnTkku7MDVCc5G1MAEqSwCgAYtA5MEwAuklecFAEAI4ZwHPcFlwZBNMJW94oZKwQYhlz5TNwVTXMElCDAObx1omhgSBypzMXjtd3D15zi8sCKtzlANjsnl4UJIQJd8h9MNUvmkUPdQhDrNxpLciBAMrlLGdPsxeK52NJfnB0YZgGIAApzW5QtDvLxEpgkiBklCCLxUuAlWAFTH+AnwxFXZGo3k7bjAAgwFnWNm2cY7anZED4pjfFE8x47CA0GhiMA3FGKyoIy5MVg01UVOAYAiai1Kq2OV5gCleU0QaqwOX4uFnQxQmGuwnuiVmqUh7YOrwCmBCyQi4Nx85R7WSvVxvlnFAQbIRsXWnWxvMJykOyhonbhbJmyQ3aSutme71wX3+9A5Eth2FVy3i7Mx3MzfM2apkYByLAl4dlnNV2tnVf60KsSQSIZAttZ8vjvlbndAgBCaYdyuX0s325gSGIcgyKSiKH3I8PdbvEkfz9fogXh+S5jmiVjooMpgAB59qKhgmhwoA+K6YAANYLrQcqsMCTBoZ2XgiOAhxOnUTAvHIkxqpSVFiOhcEhjQWE4bR+HWIRkCRMWcD1AOkw1t+XgEFBBTpBgrqQUJji3JEMRoQAtNJwAxLRckSVBnZoRhjFsDhimyahrGGOxxFcfURQlDAKSUTWNF0emZzadhUkySxVEEQwHEkdxLB7AcRxzD0J4wLu3B8WuAnUQIiSIJZvDsI4LgQAA+q8Mg0GMTCUAAlAA3EI5HyAAdIsRCYFYhVCSJFl6OZpQKu0zRkK02XlWoBREAQOh6A2RCDM2s4oNFCALNlSgAHzePMOg9U2LYoIVA64EwAASRC8HAtLyhEohMFlWXlbcEA6PtAhAA)
|
|
2347
2449
|
|
|
2348
|
-
**Example
|
|
2450
|
+
**Example 1: Filtering on an element in a `list` attribute**
|
|
2349
2451
|
|
|
2350
2452
|
```javascript
|
|
2351
2453
|
animals.query
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
`)
|
|
2356
|
-
.go()
|
|
2454
|
+
.exhibit({habitat: "Tundra"})
|
|
2455
|
+
.where(({offspring}, {eq}) => eq(offspring[0].name, "Blitzen"))
|
|
2456
|
+
.go()
|
|
2357
2457
|
```
|
|
2358
2458
|
|
|
2459
|
+
[](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
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
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({
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
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({
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
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({
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
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
|
+
[](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
|
|
5202
|
+
type EntiySchema = EntityRecord<typeof MyEntity>
|
|
4990
5203
|
```
|
|
4991
5204
|
|
|
4992
5205
|
## EntityItem Type
|