* Loads specified relations in batch. * This will execute one query for each relation, that will populate it on all the specified entities.
(
entityName: EntityName<Entity>,
entities: Entity[],
populate: PopulateOptions<Entity>[] | boolean,
options: EntityLoaderOptions<Entity, Fields>,
)
| 96 | * This will execute one query for each relation, that will populate it on all the specified entities. |
| 97 | */ |
| 98 | async populate<Entity extends object, Fields extends string = never>( |
| 99 | entityName: EntityName<Entity>, |
| 100 | entities: Entity[], |
| 101 | populate: PopulateOptions<Entity>[] | boolean, |
| 102 | options: EntityLoaderOptions<Entity, Fields>, |
| 103 | ): Promise<void> { |
| 104 | if (entities.length === 0 || Utils.isEmpty(populate)) { |
| 105 | return this.setSerializationContext(entities, populate, options); |
| 106 | } |
| 107 | |
| 108 | const meta = this.#metadata.find(entityName)!; |
| 109 | |
| 110 | if ((entities as AnyEntity[]).some(e => !e.__helper)) { |
| 111 | const entity = entities.find(e => !Utils.isEntity(e)); |
| 112 | throw ValidationError.notDiscoveredEntity(entity, meta, 'populate'); |
| 113 | } |
| 114 | |
| 115 | const references = entities.filter(e => !helper(e).isInitialized()); |
| 116 | const visited = ((options as Dictionary).visited ??= new Set<AnyEntity>()); |
| 117 | options.where ??= {} as FilterQuery<Entity>; |
| 118 | options.orderBy ??= {}; |
| 119 | options.lookup ??= true; |
| 120 | options.validate ??= true; |
| 121 | options.refresh ??= false; |
| 122 | options.convertCustomTypes ??= true; |
| 123 | |
| 124 | if (references.length > 0) { |
| 125 | await this.populateScalar(meta, references, { ...options, populateWhere: undefined } as any); |
| 126 | } |
| 127 | |
| 128 | populate = this.normalizePopulate<Entity>( |
| 129 | entityName, |
| 130 | populate as true, |
| 131 | options.strategy as LoadStrategy | undefined, |
| 132 | options.lookup, |
| 133 | options.exclude as unknown as string[], |
| 134 | ); |
| 135 | const invalid = populate.find(({ field }) => !this.#em.canPopulate(entityName, field)); |
| 136 | |
| 137 | /* v8 ignore next */ |
| 138 | if (options.validate && invalid) { |
| 139 | throw ValidationError.invalidPropertyName(entityName, invalid.field); |
| 140 | } |
| 141 | |
| 142 | this.setSerializationContext(entities, populate, options); |
| 143 | |
| 144 | const addedToVisited: AnyEntity[] = []; |
| 145 | |
| 146 | for (const entity of entities) { |
| 147 | if (visited.has(entity as AnyEntity)) { |
| 148 | continue; |
| 149 | } |
| 150 | |
| 151 | addedToVisited.push(entity as AnyEntity); |
| 152 | visited.add(entity); |
| 153 | } |
| 154 | |
| 155 | for (const pop of populate) { |
no test coverage detected