results = $results; $this->callback = $callback; } /** * Retrieve an external iterator. * * @link https://php.net/manual/en/iteratoraggregate.getiterator.php * * @return Traversable An instance of an object implementing Iterator or * Traversable * * @since 5.0.0 */ public function getIterator(): Traversable { $hits = collect(); if ($this->results['hits']['total']) { $raw = collect($this->results['hits']['hits']); $models = $this->collectModels($raw); $eloquentHits = $this->getEloquentHits($raw, $models); $hits = $this->mergeHighlightsIntoModels($eloquentHits, $raw); // $hits2 = $this->mergeCustomFieldsIntoModels($eloquentHits, $raw); } return new \ArrayIterator($hits); } private function collectModels($rawHits) { return collect($rawHits)->groupBy('_source.__class_name') ->map(function ($results, $class) { $model = new $class(); $builder = new Builder($model, ''); if (! empty($this->callback)) { $builder->query($this->callback); } /* @var Searchable $model */ return $models = $model->getScoutModelsByIds( $builder, $results->pluck('_id')->all() ); }) ->flatten()->keyBy(function ($model) { return get_class($model).'::'.$model->getScoutKey(); }); } private function getEloquentHits($hits, $models) { return collect($hits)->map(function ($hit) use ($models) { $key = $hit['_source']['__class_name'].'::'.$hit['_id']; return isset($models[$key]) ? $models[$key] : null; })->filter()->all(); } private function mergeHighlightsIntoModels($eloquentHits, $raw) { return collect($eloquentHits)->map(function (Model $eloquentHit) use ($raw) { $raw = collect($raw) ->where('_source.__class_name', get_class($eloquentHit)) ->where('_source.id', $eloquentHit->id) ->first(); foreach($raw['highlight'] ?? [] as $key => $highlight) { $eloquentHit->setAttribute($key, $highlight[0]); } return $eloquentHit; })->all(); } // private function mergeCustomFieldsIntoModels($eloquentHits, $raw){ // return collect($eloquentHits)->map(function(Model $eloquentHit) use($raw){ // $raw = collect($raw) // ->where('_source.__class_name', get_class($eloquentHit)) // ->where('_source.id', $eloquentHit->id) // ->first()['_source']; // $source = collect($raw); // $eloquentHit->setAttribute('published_from', $source->get('published_from')); // $eloquentHit->setAttribute('published_to', $source->get('published_to')); // return $eloquentHit; // })->all(); // } }