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.
		
		
		
		
		
			
		
			
				
					
					
						
							103 lines
						
					
					
						
							2.9 KiB
						
					
					
				
			
		
		
	
	
							103 lines
						
					
					
						
							2.9 KiB
						
					
					
				| 'use strict';
 | |
| 
 | |
| const leanPopulateMap = require('./leanPopulateMap');
 | |
| const modelSymbol = require('../symbols').modelSymbol;
 | |
| const utils = require('../../utils');
 | |
| 
 | |
| module.exports = assignRawDocsToIdStructure;
 | |
| 
 | |
| /*!
 | |
|  * Assign `vals` returned by mongo query to the `rawIds`
 | |
|  * structure returned from utils.getVals() honoring
 | |
|  * query sort order if specified by user.
 | |
|  *
 | |
|  * This can be optimized.
 | |
|  *
 | |
|  * Rules:
 | |
|  *
 | |
|  *   if the value of the path is not an array, use findOne rules, else find.
 | |
|  *   for findOne the results are assigned directly to doc path (including null results).
 | |
|  *   for find, if user specified sort order, results are assigned directly
 | |
|  *   else documents are put back in original order of array if found in results
 | |
|  *
 | |
|  * @param {Array} rawIds
 | |
|  * @param {Array} vals
 | |
|  * @param {Boolean} sort
 | |
|  * @api private
 | |
|  */
 | |
| 
 | |
| function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, recursed) {
 | |
|   // honor user specified sort order
 | |
|   const newOrder = [];
 | |
|   const sorting = options.sort && rawIds.length > 1;
 | |
|   const nullIfNotFound = options.$nullIfNotFound;
 | |
|   let doc;
 | |
|   let sid;
 | |
|   let id;
 | |
| 
 | |
|   for (let i = 0; i < rawIds.length; ++i) {
 | |
|     id = rawIds[i];
 | |
| 
 | |
|     if (Array.isArray(id)) {
 | |
|       // handle [ [id0, id2], [id3] ]
 | |
|       assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true);
 | |
|       newOrder.push(id);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (id === null && !sorting) {
 | |
|       // keep nulls for findOne unless sorting, which always
 | |
|       // removes them (backward compat)
 | |
|       newOrder.push(id);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     sid = String(id);
 | |
| 
 | |
|     doc = resultDocs[sid];
 | |
|     // If user wants separate copies of same doc, use this option
 | |
|     if (options.clone && doc != null) {
 | |
|       if (options.lean) {
 | |
|         const _model = leanPopulateMap.get(doc);
 | |
|         doc = utils.clone(doc);
 | |
|         leanPopulateMap.set(doc, _model);
 | |
|       } else {
 | |
|         doc = doc.constructor.hydrate(doc._doc);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (recursed) {
 | |
|       if (doc) {
 | |
|         if (sorting) {
 | |
|           const _resultOrder = resultOrder[sid];
 | |
|           if (Array.isArray(_resultOrder) && Array.isArray(doc) && _resultOrder.length === doc.length) {
 | |
|             newOrder.push(doc);
 | |
|           } else {
 | |
|             newOrder[_resultOrder] = doc;
 | |
|           }
 | |
|         } else {
 | |
|           newOrder.push(doc);
 | |
|         }
 | |
|       } else if (id != null && id[modelSymbol] != null) {
 | |
|         newOrder.push(id);
 | |
|       } else {
 | |
|         newOrder.push(options.retainNullValues || nullIfNotFound ? null : id);
 | |
|       }
 | |
|     } else {
 | |
|       // apply findOne behavior - if document in results, assign, else assign null
 | |
|       newOrder[i] = doc || null;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   rawIds.length = 0;
 | |
|   if (newOrder.length) {
 | |
|     // reassign the documents based on corrected order
 | |
| 
 | |
|     // forEach skips over sparse entries in arrays so we
 | |
|     // can safely use this to our advantage dealing with sorted
 | |
|     // result sets too.
 | |
|     newOrder.forEach(function(doc, i) {
 | |
|       rawIds[i] = doc;
 | |
|     });
 | |
|   }
 | |
| } |