-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
97 lines (77 loc) · 2.73 KB
/
index.js
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
const mongoose = require('mongoose')
const modelMap = {}
const subscriberMap = {}
const defineSummarySource = (originalSchema) => {
originalSchema.statics.listenForUpdates = function () {
const model = this
modelMap[model.modelName] = model
}
// Fires on save and create events
originalSchema.post('save', updateSummaries)
// Fires on any findAndUpdate calls
originalSchema.post('findOneAndUpdate', updateSummaries)
// Fires on update query
originalSchema.post('update', function() {
const query = this.getQuery()
const model = this.model // This is using an undocumented property from Query :(
model.find(query).exec((err, results) => {
if (err) return
results.forEach(updateSummaries)
})
})
}
const updateSummaries = (sourceDoc) => {
const sourceModel = sourceDoc.constructor
const subscribers = subscriberMap[sourceModel.modelName]
if (!subscribers) {
return
}
subscribers.forEach(subscriber => {
const conditions = { [subscriber.path + '._id']: sourceDoc._id }
const doc = {}
doc[subscriber.path] = sourceDoc
doc[subscriber.path]._id = sourceDoc._id
subscriber.model.update(conditions, doc, { multi: true }, function(err) {
if (err) return
})
})
}
const summarize = function (subscriberSchema, options) {
const summarySchema = subscriberSchema.obj[options.path]
// Enforce having a required _id path in the summary schema
if (!summarySchema.path('_id') || summarySchema.path('_id').options.required !== true) {
throw new Error('The schema requires an `_id` path in the summary schema in the `' +
options.path + '` path.')
}
// Ensure _id is indexed for quick querying
// TODO: Document this, so developer is not surprised
summarySchema.index({ _id: 1 })
// Set summary doc
subscriberSchema.pre('validate', function (next) {
const originalDoc = this
const docId = originalDoc[options.path]._id
const refModel = modelMap[options.ref]
refModel.findById(docId, (err, refDoc) => {
if (err) {
return next(err)
}
if (!refDoc) {
return next(new Error('No document found in the ' + refModel.modelName + ' reference with _id ' + docId))
}
originalDoc[options.path] = refDoc
next()
})
})
subscriberSchema.statics.listenForSourceChanges = function () {
const model = this
const subscribers = subscriberMap[options.ref] || []
subscribers.push({
model: model,
path: options.path
})
subscriberMap[options.ref] = subscribers
return model
}
}
module.exports = exports = summarize
exports.defineSummarySource = defineSummarySource