Skip to content

Commit

Permalink
Attempt to make term <> collection query more performant (#345)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanmitchell committed Aug 28, 2024
1 parent 4d41965 commit 38371ab
Showing 1 changed file with 23 additions and 36 deletions.
59 changes: 23 additions & 36 deletions src/Taxonomies/TermQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Statamic\Eloquent\Taxonomies;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Statamic\Contracts\Taxonomies\Term as TermContract;
use Statamic\Facades\Blink;
Expand Down Expand Up @@ -215,46 +214,34 @@ private function applyCollectionAndTaxonomyWheres()
? Taxonomy::handles()->all()
: $this->taxonomies;

// get entries in each collection that have a value for the taxonomies we are querying
// or the ones associated with the collection
// what we ultimately want is a subquery for terms in the form:
// where('taxonomy', $taxonomy)->whereIn('slug', $slugArray)
$collectionTaxonomyHash = md5(collect($this->collections)->merge(collect($taxonomies))->sort()->join('-'));

Blink::once("eloquent-taxonomy-hash-{$collectionTaxonomyHash}", function () use ($taxonomies) {
return Entry::query()
->whereIn('collection', $this->collections)
->select($taxonomies)
->get();
})
->flatMap(function ($entry) use ($taxonomies) {
$slugs = [];
foreach ($entry->collection()->taxonomies()->map->handle() as $taxonomy) {
if (in_array($taxonomy, $taxonomies)) {
foreach (Arr::wrap($entry->get($taxonomy, [])) as $term) {
$slugs[] = $taxonomy.'::'.$term;
}
}
collect($taxonomies)->each(function ($taxonomy) use ($query) {
$collectionTaxonomyHash = md5(collect($this->collections)->merge([$taxonomy])->sort()->join('-'));

$terms = Blink::once("eloquent-taxonomy-hash-{$collectionTaxonomyHash}", function () use ($taxonomy) {
if (! $taxonomy = Taxonomy::find($taxonomy)) {
return [];
}

return $slugs;
})
->unique()
->map(function ($term) {
return [
'taxonomy' => Str::before($term, '::'),
'term' => Str::after($term, '::'),
];
})
->mapToGroups(function ($item) {
return [$item['taxonomy'] => $item['term']];
})
->each(function ($terms, $taxonomy) use ($query) {
return TermModel::where('taxonomy', $taxonomy)
->select('slug')
->get()
->map(function ($term) use ($taxonomy) {
return Entry::query()
->whereIn('collection', $this->collections)
->whereJsonContains('data->'.$taxonomy, [$term->slug])
->count() > 0 ? $term->slug : null;
})
->filter()
->values();
});

if ($terms->isNotEmpty()) {
$query->orWhere(function ($query) use ($terms, $taxonomy) {
$query->where('taxonomy', $taxonomy)
->whereIn('slug', $terms);
->whereIn('slug', $terms->all());
});
});
}
});
});
}

Expand Down

0 comments on commit 38371ab

Please sign in to comment.