-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathcacheCount.js
More file actions
71 lines (61 loc) · 2.08 KB
/
cacheCount.js
File metadata and controls
71 lines (61 loc) · 2.08 KB
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
import _ from 'lodash';
import { addMigration } from './migrations.js';
import { check, Match } from 'meteor/check';
Mongo.Collection.prototype.cacheCount = function (options) {
check(options, {
collection: Mongo.Collection,
cacheField: String,
referenceField: String,
selector: Match.Optional(Object),
bypassSchema: Match.Optional(Boolean),
});
let parentCollection =
options.bypassSchema && Package['aldeed:collection2']
? this._collection
: this;
let childCollection = options.collection;
let selector = options.selector || {};
let cacheField = options.cacheField;
let referenceField = options.referenceField;
let watchedFields = _.union([referenceField], Object.keys(selector));
const topFields = _.uniq(watchedFields.map(field => field.split('.')[0]));
if (referenceField.split(/[.:]/)[0] == cacheField.split(/[.:]/)[0]) {
throw new Error(
'referenceField and cacheField must not share the same top field',
);
}
async function update(child) {
let ref = _.get(child, referenceField);
if (ref) {
let select = _.merge(selector, { [referenceField]: ref });
await parentCollection.updateAsync(
{ _id: ref },
{
$set: {
[cacheField]: await childCollection.find(select).countAsync(),
},
},
);
}
}
async function insert(userId, parent) {
let select = _.merge(selector, { [referenceField]: parent._id });
await parentCollection.updateAsync(parent._id, {
$set: { [cacheField]: await childCollection.find(select).countAsync() },
});
}
addMigration(parentCollection, insert, options);
parentCollection.after.insert(insert);
childCollection.after.insert(async (userId, child) => {
await update(child);
});
childCollection.after.update(async function (userId, child, changedFields) {
if (_.intersection(changedFields, topFields).length) {
await update(child);
await update(this.previous);
}
}, { fetchPrevious: true });
childCollection.after.remove(async (userId, child) => {
await update(child);
});
};