You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					156 lines
				
				4.8 KiB
			
		
		
			
		
	
	
					156 lines
				
				4.8 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const get = require('../get');
							 | 
						||
| 
								 | 
							
								const helperIsObject = require('../isObject');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								 * Gather all indexes defined in the schema, including single nested,
							 | 
						||
| 
								 | 
							
								 * document arrays, and embedded discriminators.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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 {
							 | 
						||
| 
								 | 
							
								          const 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) {
							 | 
						||
| 
								 | 
							
								        if (!('background' in index[1])) {
							 | 
						||
| 
								 | 
							
								          index[1].background = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      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] ..]
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  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]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 |