Search
Functionality
Simple search adds an ability to search different entities based on their data. You can search by the core fields set or add your own fields to be indexed, and then search by them. We have one index (we call it master index) where the data of the entities is indexed and there is an ability to search using it.
Supported entities
Using search you can find next entities among search results. Only published entities go to the search engine:
- Page
- Blog
- Post
- FAQ question
- Product (Products\Entities\ProductDescription)
Core fields set
There are next fields you can search by:
- entityClass, for example, Pages\Entities\Page, Blogs\Entities\Post
- id -- ID of the entity
- name
- fullPath -- relative URL to the entity in Frontend
- nativeText -- additional text assigned directly to the entity, not from its layout areas. Currently, it is not used.
- layoutId -- ID of the layout entity uses
- componentLayoutIds -- IDs of all layouts that entity components use
- language.code -- 2 chars of the language code
- author.displayName -- the name of the author of the entity
- created -- the date when entity was created in Y-m-d\TH:i:sP format in UTC, e.g. 2019-08-26T21:07:38+00:00
- indexed -- the date when entity is indexed to the search engine. Same format as created has. This value is changed on every reindex operation.
- tags.name, tags.slug, categories.name, categories.slug -- tags/categories names/slugs assigned to the entity
- relatedRecords -- IDs of the related records of the entity. It's filled from record(s) input types of the entity. Structure example is: [Forms\Entities\Form => [1], Common\Entities\Menu => [2, 10], ...]. There could be any entity in this array, not only from the supported ones for the searching.
- fields -- array of additionally indexed fields from the entity areas where the key is the field name. You can search by value using fields.fieldName query.
Layout area fields
Editing a layout, it is possible to index some areas with a specific field. You can provide a field name the value of the area will be indexed under. You can do that for areas that use input types with text categories. Just add a new name or select among existing. For example, you have an area called ageRestriction in the layout. Use the switch to index this area and give it the "age" name. When you fill this area inside the entity, you can use fields.age to search by its values. You can index the area for the component and every entity that uses it will have its value indexed. When you change (add/remove/assign) search field for the layout area, it is automatically reindexed in the search engine. Use the "Reindex all" button if you want to force all data reindexed along with areas index fields immediately
Indexing process
Every time you CRUD the record it is indexed in the search engine. You can also call reindexing all entities whenever you want using the "Reindex all" button.
Views
Everything described above is about indexing data to the search engine. View entity helps to specify how we search indexed data: what we search, how we sort data, how we filter it, etc. You can create a main view that returns all indexed data. At the same time you can create and set up products view that returns only records where entityClass is Products\Entities\ProductDescription.
You can set up the view in different ways: page size, full-text search settings, fields that are used for searching, filter fields, etc. Almost every setting can be set as (un)changeable -- the one you can (not) change creating a search query. When any parameter is unchangeable, the value you specified in the view will always be used.
You need to use q
parameter to search by a specific phrase. Also, below there are other parameters that can be used.
Pagination
The amount of records that are returned on the page in search results can be set up in the view. If it is changeable, use limit
to change it. Use page
to specify a page number you want to access (started from 1).
Full-text search
There are next parameters you can use in your query:
minimumShouldMatch
-- shows how many words should be matched in the phrase when we search for data. Please, see different examples here https://www.elastic.co/guide/en/elasticsearch/reference/7.10/query-dsl-minimum-should-match.html.tieBreaker
-- https://www.elastic.co/guide/en/elasticsearch/reference/7.10/query-dsl-multi-match-query.html#tie-breakerfuzzy
-- if we use fuzziness search. Enable it and searching for "cofe" you will get correct results with a "coffee" word.
All these fields can be (un)changeable.
Search fields
There is an ability to specify which fields are used for searching and what is the weight of them: which field match adds more scope points for the result, which means the result will be higher.
All of them are (un)changeable -- you can forbid them to change all together. If they are changeable, you can specify something like this q=coffee&searchFields=tags.name,categories.name^2
. In this case, the coffee
phrase will be searched only inside tag and categories names, and results found in categories will be higher in the response, because the bigger weight is specified.
You can use array-based syntax: q=coffee&searchFields[tags.name]=&searchFields[categories.name]=2
, which is equal to the mentioned above. When you don't specify a weight, it is set to 1. It should be 0 and higher.
It is possible to use mixed syntax: q=coffee&searchFields[tags.name]=&searchFields[categories.name]=2&searchFields[]=name&searchFields[]=fullPath^2,entityClass^0.5
.
If you don't specify such fields, default behavior is applied. Usually, all fields are searchable and affect the result.
Filter fields
There is an ability to filter results assigning to their fields specific values. You don't need to use a specific parameter to specify them, just specify a filter name as a query parameter.
You can filter by multiple values sending them as an array or just separate by comma in string (or use 2 variants together). Unspecified fields are ignored.
You can make EVERY filter field (un)changeable and make it ignore (or not) empty values. By default, every field is changeable and ignored when empty.
For example, in the query q=coffee&tags.name[]=coffee,roasting&tags.name[tea]=tea&tags.name[]=water&componentLayoutIds=
, the results that contain "coffee" inside their fields will be returned
Moreover, only those which have at least one of the following tags: coffee, roasting, tea, water. componentLayoutIds
is ignored when the "ignore empty" switch is enabled. But when you disable it, only records that do not have components inside themselves will be returned (in this case componentLayoutIds
field is empty).
Sort fields
You can provide fields the result will be sorted by. When you provide nothing, the default sorting is applied. Usually, results are sorted relatively (_score DESC
).
Sort can be (un)changeable. If it is, you can set up sort fields manually. Use orderBy
parameter for that. Unsupportable fields are ignored.
You can separate fields by comma, or use array syntax, or combine them.
Specifying q=coffee&orderBy[name]=&orderBy[]=entityClass,id desc&orderBy[]=_score
you will have results sorted by name ASC
, entity ASC
, id DESC
, _score DESC
. Notice when you don't specify an ordering, it is ASC by default. Only for _score
the DESC is the default value. Note _score
is used for relative sorting.
Highlight
You can select which fields will be returned with highlighted search results. You can use highlightFields
parameter for that. Separate values by comma, pass them as an array or use combined syntax. It can be (un)changeable.
If you have q=coffee&highlightFields[]=name
, and there is a result with "Coffee Roaster" in the name, its highlighted value will be "<em>Coffee</em> Roaster
".
Use q=coffee&highlightFields=tags.name,tags.slug
to have tag names and slugs highlighted. Combined variant is q=coffee&highlightFields[]=tags.name,tags.slug&highlightFields[]=name
, which additionally highlights name as well.
Searching
To search, use different ways to get search results:
/search/{ViewSlug}?q=phrase
in frontend- Same in API
- Use
$_search->search({ViewSlug}, $parameters)
call within the template.
Example usage
Suppose you want to search for a product with the name "Coffee Beans", which has a tag "organic" and is created by the author with the name "John". You can use the following query:
/search/products?q=Coffee Beans&tags.name=organic&author.displayName=John
This will return all products that match the search criteria.
Suppose you want to search for a blog post that contains the phrase "coffee recipe" and was created in the last month. You can use the following query:
/search/blog?q=coffee recipe&created=>now-1M
This will return all blog posts that match the search criteria.
Conclusion
In this markup, we have discussed the functionality of the search engine, the entities it supports, the core fields set that can be searched, layout area fields that can be indexed, the indexing process, views, pagination, full-text search, search fields, filter fields, sort fields, highlight, and searching. By understanding these concepts, you can use the search engine to its full potential and get the search results that you need.