-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathmapValues.js
94 lines (83 loc) · 3.65 KB
/
mapValues.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
var singleValueOperators = {$gt:1, $gte:1, $lt:1, $lte:1, $not:1} // note that $not is only this type if it has no 'parts'
var possibleMultiValueOperators = {$eq:1, $ne:1}
var arrayOperators = {$nin:1, $all:1, $in:1}
//var specialSingleValueOperators = {$geoIntersects:1, $geoWithin:1} // treating as noValueOperators
//var noValueIndependentOperators = {$where:1, $comment:1}
//var noValueFieldOperators = {$mod:1, $exists:1, $regex:1, $size:1, $nearSphere:1, $near:1}
var mapValues = module.exports = function(parts, callback, prefix) {
var result = {}
parts.forEach(function(part) {
if(part.field !== undefined) {
if(prefix !== undefined) {
var field = prefix+'.'+part.field
} else {
var field = part.field
}
} else {
var field = prefix
}
if(part.parts.length === 0) {
if(part.operator in singleValueOperators) {
if(part.field !== undefined) { // normal situation
addOperator(result,part.field, part.operator, callback(field, part.operand))
} else { // if its inside an $elemMatch query
result[part.operator] = callback(field, part.operand)
}
} else if(part.operator in possibleMultiValueOperators) {
if(part.operand instanceof Array) {
var value = part.operand.map(function(v) {
return callback(field, v)
})
} else {
var value = callback(field, part.operand)
}
addOperator(result,part.field, part.operator, value)
} else if(part.operator in arrayOperators) {
addOperator(result,part.field, part.operator, part.operand.map(function(v) {
return callback(part.field, v)
}))
} else if(part.operator === '$text') {
result.$text = {$search: callback(field, part.operand.$search)}
if(part.operand.$language !== undefined) {
result.$text.$language = part.operand.$language
}
} else { // independent operators with no value
// don't map anything
if(part.field !== undefined) {
addOperator(result,part.field, part.operator, part.operand)
} else {
result[part.operator] = part.operand
}
}
} else {
if(part.operator === '$elemMatch') {
var mappedValue = mapValues(part.parts, callback, field)
addOperator(result,part.field, part.operator, mappedValue)
} else if(part.operator === '$not') {
result[part.operator] = mapValues(part.parts, callback, field)
} else {
var operands = []
part.parts.forEach(function(innerPart) {
operands.push(mapValues(innerPart.parts, callback))
})
result[part.operator] = operands
}
}
})
return result
}
// builds an object immediate where keys can be expressions
function obj(/*key,value, key,value ...*/) {
var result = {}
for(var n=0; n<arguments.length; n+=2) {
result[arguments[n]] = arguments[n+1]
}
return result
}
// adds an operator to a field, handling the case where there is already another operator there
function addOperator(obj, field, operator, operand) {
if(obj[field] === undefined) {
obj[field] = {}
}
obj[field][operator] = operand
}