Spaces:
Runtime error
Runtime error
File size: 5,477 Bytes
9756872 | 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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | 'use strict';
const get = require('../get');
const helperIsObject = require('../isObject');
const decorateDiscriminatorIndexOptions = require('../indexes/decorateDiscriminatorIndexOptions');
/**
* Gather all indexes defined in the schema, including single nested,
* document arrays, and embedded discriminators.
* @param {Schema} schema
* @api private
*/
module.exports = function getIndexes(schema) {
let indexes = [];
const schemaStack = new WeakMap();
const indexTypes = schema.constructor.indexTypes;
const indexByName = new Map();
collectIndexes(schema);
return indexes;
function collectIndexes(schema, prefix, baseSchema) {
// Ignore infinitely nested schemas, if we've already seen this schema
// along this path there must be a cycle
if (schemaStack.has(schema)) {
return;
}
schemaStack.set(schema, true);
prefix = prefix || '';
const keys = Object.keys(schema.paths);
for (const key of keys) {
const path = schema.paths[key];
if (baseSchema != null && baseSchema.paths[key]) {
// If looking at an embedded discriminator schema, don't look at paths
// that the
continue;
}
if (path.$isMongooseDocumentArray || path.$isSingleNested) {
if (get(path, 'options.excludeIndexes') !== true &&
get(path, 'schemaOptions.excludeIndexes') !== true &&
get(path, 'schema.options.excludeIndexes') !== true) {
collectIndexes(path.schema, prefix + key + '.');
}
if (path.schema.discriminators != null) {
const discriminators = path.schema.discriminators;
const discriminatorKeys = Object.keys(discriminators);
for (const discriminatorKey of discriminatorKeys) {
collectIndexes(discriminators[discriminatorKey],
prefix + key + '.', path.schema);
}
}
// Retained to minimize risk of backwards breaking changes due to
// gh-6113
if (path.$isMongooseDocumentArray) {
continue;
}
}
const index = path._index || (path.caster && path.caster._index);
if (index !== false && index !== null && index !== undefined) {
const field = {};
const isObject = helperIsObject(index);
const options = isObject ? index : {};
const type = typeof index === 'string' ? index :
isObject ? index.type :
false;
if (type && indexTypes.indexOf(type) !== -1) {
field[prefix + key] = type;
} else if (options.text) {
field[prefix + key] = 'text';
delete options.text;
} else {
let isDescendingIndex = false;
if (index === 'descending' || index === 'desc') {
isDescendingIndex = true;
} else if (index === 'ascending' || index === 'asc') {
isDescendingIndex = false;
} else {
isDescendingIndex = Number(index) === -1;
}
field[prefix + key] = isDescendingIndex ? -1 : 1;
}
delete options.type;
if (!('background' in options)) {
options.background = true;
}
if (schema.options.autoIndex != null) {
options._autoIndex = schema.options.autoIndex;
}
const indexName = options && options.name;
if (typeof indexName === 'string') {
if (indexByName.has(indexName)) {
Object.assign(indexByName.get(indexName), field);
} else {
indexes.push([field, options]);
indexByName.set(indexName, field);
}
} else {
indexes.push([field, options]);
indexByName.set(indexName, field);
}
}
}
schemaStack.delete(schema);
if (prefix) {
fixSubIndexPaths(schema, prefix);
} else {
schema._indexes.forEach(function(index) {
const options = index[1];
if (!('background' in options)) {
options.background = true;
}
decorateDiscriminatorIndexOptions(schema, options);
});
indexes = indexes.concat(schema._indexes);
}
}
/**
* Checks for indexes added to subdocs using Schema.index().
* These indexes need their paths prefixed properly.
*
* schema._indexes = [ [indexObj, options], [indexObj, options] ..]
* @param {Schema} schema
* @param {String} prefix
* @api private
*/
function fixSubIndexPaths(schema, prefix) {
const subindexes = schema._indexes;
const len = subindexes.length;
for (let i = 0; i < len; ++i) {
const indexObj = subindexes[i][0];
const indexOptions = subindexes[i][1];
const keys = Object.keys(indexObj);
const klen = keys.length;
const newindex = {};
// use forward iteration, order matters
for (let j = 0; j < klen; ++j) {
const key = keys[j];
newindex[prefix + key] = indexObj[key];
}
const newIndexOptions = Object.assign({}, indexOptions);
if (indexOptions != null && indexOptions.partialFilterExpression != null) {
newIndexOptions.partialFilterExpression = {};
const partialFilterExpression = indexOptions.partialFilterExpression;
for (const key of Object.keys(partialFilterExpression)) {
newIndexOptions.partialFilterExpression[prefix + key] =
partialFilterExpression[key];
}
}
indexes.push([newindex, newIndexOptions]);
}
}
};
|