-
Notifications
You must be signed in to change notification settings - Fork 10
/
index.js
113 lines (103 loc) · 2.49 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* @method random
* @param {mongoose.Schema} schema
* @param {Object} options
* @param {Function} [options.fn=Math.random]
* @param {String} [options.path='random']
*/
function random(schema, options) {
options = options || {};
var randFn = options.fn || Math.random;
var randCoords = function () { return [randFn(), randFn()] }
var path = options.path || 'random';
var field = {};
field[path] = {
type: { type: String, default: 'Point' },
coordinates: { type: [Number], default: randCoords }
};
var index = {};
index[path] = '2dsphere';
schema.add(field);
schema.index(index);
/**
* @method findRandom
* @param {Object} conditions
* @param {Object} [fields]
* @param {Object} [options]
* @param {Function} [callback]
*/
schema.statics.findRandom = function (conditions, fields, options, callback) {
var self = this;
if (!conditions || typeof conditions === 'function') {
conditions = {};
}
conditions[path] = conditions[path] || {
$near: {
$geometry: { type: 'Point', coordinates: randCoords() }
}
};
var query = self.find.call(self, conditions, fields, options, callback);
query.__random = { path: path, query: conditions[path] };
return query;
};
/**
* @method syncRandom
* @param callback
*/
schema.statics.syncRandom = function (callback) {
var self = this;
var stream = self.find({}).stream({ transform: transform });
var result = {
attempted: 0,
updated: 0
};
var left = 0;
var streamEnd = false;
stream.on('data', function (doc) {
result.attempted += 1;
left += 1;
doc.save(function (err) {
if (err) {
console.error(err.stack);
} else {
result.updated += 1;
}
left -= 1;
if (streamEnd && !left) {
return callback(null, result);
}
});
}).on('error', function (err) {
console.error(err.stack);
}).on('end', function () {
streamEnd = true;
});
return stream;
};
function transform(doc) {
var update = {
type: 'Point',
coordinates: randCoords()
};
doc.set(path, update);
return doc;
}
}
module.exports = random;
/**
* Merges keys from `objects` into `base`, without overwriting.
*
* @method merge
* @param {Object} base
* @param {[Object]} [objects]*
* @returns {Object}
*/
function merge(base) {
var objects = [].slice.call(arguments, 1);
objects.forEach(function (obj) {
Object.keys(obj).forEach(function (key) {
base[key] = base[key] === undefined ? obj[key] : base[key];
});
});
return base;
}