-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathquery-builder.js
82 lines (69 loc) · 2.5 KB
/
query-builder.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
var mongooseMethodValidations = require('./Moonridge-client/lib/moonridge-method-validations')
var maxQueryLength = 70 // hardcoded max query length
var qMethodsEnum = []
for (var method in mongooseMethodValidations) {
qMethodsEnum.push(method)
}
var callJustOnce = [
'findOne',
'select',
'count',
'sort',
'limit',
'skip'
]
/**
* @param {Mongoose.Model} model
* @param {Array<Object>} clientQuery received JSON deserialized
* @param {Boolean} isLive true for liveQueries
* @returns {MRQuery|Error}
*/
module.exports = function MRQuery (model, clientQuery, isLive) {
var query = model.find()
// query option object,where we index by method, not by invocation order, useful later when we reexecute the query
var opts = {populate: []}
if (!Array.isArray(clientQuery)) {
throw new TypeError('Query must be an array')
}
if (clientQuery.length > maxQueryLength) {
throw new Error('Maximum query length of the query is bigger than allowed')
}
var ind = 0
while (clientQuery[ind]) {
var methodName = clientQuery[ind].mN // short for methodName
if (qMethodsEnum.indexOf(methodName) !== -1) {
var args = clientQuery[ind].args
if (Array.isArray(args)) { // if it is one of SAA, then we won't call it with apply
var validationResult = mongooseMethodValidations[methodName](args)
if (validationResult instanceof Error) {
throw validationResult
}
if (callJustOnce.indexOf(methodName) !== -1) {
if (methodName === 'sort' && opts.count) {
// doesn't really makes sense to make both at once
throw new Error('Mongoose does not support sort and count in one query')
}
if (opts[methodName]) {
throw new Error(methodName + ' method can be called just once per query')
} else {
opts[methodName] = args // we shall add it to the options, this object will be used when reiterating on LQ
}
} else if (methodName === 'populate') {
opts.populate.push(args)
}
if (methodName === 'count' && isLive) {
opts.count = true
break
}
query = query[methodName].apply(query, args)
} else {
throw new TypeError('Method arguments for "' + methodName + '" must be array, query builder cannot parse this')
}
} else {
throw new Error('Method "' + methodName + '" is not a valid query method.')
}
ind += 1
}
query.lean(true)
return {opts: opts, mQuery: query}
}