Site search on Core dna is an Elasticsearch index that the platform fills and queries, and a page you build. What reaches the index, search views, the search page, product facets, filtered listings that need no index, and when to go beyond the built-in index.
L2
Unit 04 · Listings without the index
When a listing should become a search view
Listings without the indexPage 16 of 20Updated
A plain listing is always current, needs no index and respects the visitor's permissions; a search view matches words, ranks across record types and counts facets. Where the line between them falls, and what each side costs, so that nothing moves onto the index without a reason.
Who this is for. The developer deciding whether a new filtered page needs a search view, and the reviewer asking why it has one. Afterwards you can name the requirement that forces a view, or show that a listing is the better answer.
The line
A listing filters one module's records on their own fields, in a fixed order or a chosen sort. Move to a search view when the page needs something a listing cannot do:
Free-text matching. A box where the visitor types words and expects every word form, typing errors and the best match first. A listing's contains filter, %25field=, is a plain substring match on one field: no stems, no fuzziness, no ranking, and on a large table it reads every row (Queries, ranking and highlighting).
One result set across types, pages, posts, products and FAQ answers together, in relevance order. A listing is one module's records.
Counts beside each option, for products. A listing can filter by tag or category but does not count what each option would leave; that is the facets index (Facets and the mapping template).
Below that line, a listing is the better answer, and a rule of thumb finds the line quickly: if the visitor picks from a known set of values, filter a listing; if the visitor types words, use a view.
What a listing gives you that a view does not
It is always current. It reads the records directly, so there is no indexing delay and no stale index to explain (Why a new record is not findable yet).
It respects the visitor's permissions. A signed-in member sees the records their groups may read. The index holds only what a signed-out visitor may read, so members-only content can only ever be a listing.
It covers every module. Custom entity records are never in site search; a custom entity's listing route, or a $_query lookup, is the only way to filter them.
Its count is exact, where a search count stops at 10,000.
There is no view to maintain: no mapping, no reindex after a model change, no scope to lock.
A members-only search is the clearest case: it cannot be a view at all. A $_query lookup applies the signed-in member's permissions and the published filter, and is enough for a short list of matching titles:
{% do _response.preventCaching() %}
{% set q = _request.getParameter('q') %}
{% if q is not null and q is not iterable and q|trim != '' %}
{% set found = _query.findBy('Pages\\Entities\\Page', {'%activeRevision.name': q|trim}, {'created': 'DESC'}, 20) %}
<ul class="member-results">
{% for result in found %}
<li><a href="{{ result.getFullPath()|e }}">{{ result.getName()|e }}</a></li>
{% else %}
<li>No page title contains “{{ q|e }}”.</li>
{% endfor %}
</ul>
{% endif %}
It matches titles only, as a substring, which is the trade: no ranking and no stems, but nothing a member may read is left out and nothing they may not read is shown.
What a view costs
Mapping work: layout area text is invisible until each area is mapped to a search field (Search fields).
Delay and staleness: new records arrive in seconds or minutes, and some changes, a global component's text or a renamed tag, leave the index stale until a reindex (What leaves the index stale).
Configuration to guard: a new view lets visitors change its scope from the URL until the filters are locked (What a visitor can change).
Public content only, and a count that stops at 10,000.
Deciding
The page needs
Use
Filtering by tag, category, author or a field, from known values
A listing, through its routes or query parameters
Members-only records, or custom entity records
A listing, or a $_query lookup
Words typed by the visitor, matched forgivingly and ranked