-
Notifications
You must be signed in to change notification settings - Fork 0
/
fields_sharing_index.mjs
115 lines (97 loc) · 3.65 KB
/
fields_sharing_index.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// This example demonstrates how to take advantage of sorting within the sort
// key of an index to efficiently find and return documents of a specific type
// by equality of one property, sorted by a separate property.
//
// To do this both properties are saved to the same string field in the
// database, with virtual getters and setters defined to allow transparent
// access as separate properties for users of the model:
//
//
import DynamoDM from 'dynamodm';
// get an instance of the API (options can be passed here)
const ddm = DynamoDM();
// get a reference to a table:
const table = ddm.Table('my-dynamodb-table');
// Create User and Comment models with their JSON schemas in this table:
const UserSchema = ddm.Schema('user', { });
const CommentSchema = ddm.Schema('comment', {
properties: {
text: { type: 'string' },
user_and_time: { type: 'string' }
}
}, {
index: {
findByUserAndTime: {
hashKey: 'type',
sortKey: 'user_and_time'
}
}
});
const UploadSchema = ddm.Schema('upload', {
properties: {
url: { type: 'string' },
user_and_time: { type: 'string' }
}
}, {
// ...
});
// define virtual getters and setters for easy access to the
// separate parts of the compound fields
UploadSchema.virtuals.user = CommentSchema.virtuals.user = {
get() {
return this.user_and_time.split('/')[0];
},
set(v) {
this.user_and_time = v.toString() + '/' + (this.user_and_time || '/').split('/')[1];
},
};
UploadSchema.virtuals.time = CommentSchema.virtuals.time = {
get() {
return Date.parse(this.user_and_time.split('/')[1]);
},
set(v) {
this.user_and_time = (this.user_and_time || '/').split('/')[0] + '/' + v.toISOString();
},
};
// define static helper functions to make the details of
// composing the query internal to the models:
UploadSchema.statics.getForUserSince =
CommentSchema.statics.getForUserSince = async function(user, sinceTime) {
return await this.queryMany({
type: this.type,
user_and_time: {
$between: [ `${user}/${sinceTime.toISOString()}`, `${user}/9999` ]
}
});
};
const User = table.model(UserSchema);
const Comment = table.model(CommentSchema);
const Upload = table.model(UploadSchema);
console.log('waiting for the table...');
await table.ready({ waitForIndexes: true });
const u1 = await (new User()).save();
const u2 = await (new User()).save();
const firstCommentTime = Date.now();
for (const user of [u1, u2]) {
console.log(`creating records for ${user.id}...`);
for (let i = 0; i < 10; i ++) {
// The virtual fields can be assigned even during construction:
const comment = new Comment({text: `Text of comment ${i} by user ${user.id}.`, user: user.id, time: new Date(firstCommentTime + i * 10000)});
await comment.save();
const upload = new Upload({url: `https://example.com/example-url-${i}`});
upload.user = user.id;
upload.time = new Date(firstCommentTime + i * 10000);
await upload.save();
}
}
// both these queries will use the findByUser index. Since the hash
// key of the index is `type`, we can be sure that only documents
// of the correct type are returned to each query:
for (const user of [u1, u2]) {
console.log(`querying records for ${user.id}...`);
const sinceTime = new Date(firstCommentTime + 50000);
const comments = await Comment.getForUserSince(user.id, sinceTime);
const uploads = await Upload.getForUserSince(user.id, sinceTime);
console.log(`User ${user.id} comments since ${sinceTime}:`, comments);
console.log(`User ${user.id} uploads since ${sinceTime}:`, uploads);
}