This is the simple educational project prepared to support my presentation during PHPers Summit 2021 conference (more recently on Warszawskie Dni Informatyki 2022 and 4Developers 2022) and to allow participants to play with Elasticsearch scoring. It is not intended to expose any architectural patterns of the code itself, so please don't stick to the directory structure or the overall code architecture too much 😉.
| Docplanner Tech | PHPers Summit 2021 | Warszawskie Dni Informatyki 2022 | 4Developers 2022 | 
|---|---|---|---|
![]()  | 
![]()  | 
![]()  | 
![]()  | 
- PHP 8.2.2
 - Symfony CLI (https://symfony.com/download)
 - Elasticsearch 7.16.0 running on 
localhost:9200 
If you need to change the Elasticsearch host the application uses, it's defined in the ApiClient class as a constant (normally worth passing it from .env params file 😉 )
In order to run the project, it is advisable to install an instance of latest stable version of Elasticsearch (it's 7.16.0 version at the moment of the presentation https://www.elastic.co/guide/en/elasticsearch/reference/7.16/index.html)
- Create 
carsindex in Elasticsearch (Index/CreateHTTP request*) - Populate the index with sample cars data (
Index/BulkHTTP request*) - Go to project's root directory in the terminal
 - Start Symfony server 
symfony server:start --no-tls - Go to http://127.0.0.1:8000/
 
(*) - all HTTP requests can be executed either:
- from within PhpStorm's built-in REST HTTP client (samples in .elasticsearch-http-requests directory)
 - in Insomnia REST HTTP client (import insomnia.json file with all the samples)
 
All Elasticsearch implementation related code is placed in src/Elasticsearch directory.
The core ranking logic is built from specific Factors classes:
RawScoreFactorthat propagates the originally calculated document score to the overall scoring (as it is being overwritten / replaced by all custom functions) in order to weight it along with other custom factors provided by the developerDodgePromoFactorthat promotes all documents that hasproducerfield equal toDodge(you can switch to any other)ColorRelevanceFactorthat ranks higher these documents / cars which has more intensive or exclusive color to the ones that are being filtered out on every app's request
Then the RecommendedSorter that includes all those ranking factors is set up in CarRepository to guarantee it applies to every search request:
<?php
// ...
final class RecommendedSorter implements FactorSorterInterface
{
  // ...
	public function __construct(private ?Factors $factors = null)
	{
		$this->factors ??= new Factors(
			new RawScoreFactor(new Weight(1)),
			new DodgePromoFactor(new Weight(100)),
			new ColorRelevanceFactor(new Weight(50)),
		);
	}
  // ...
}💡 You can comment out any of the factors to see how they contribute to the ranking.
💡 You can add any other factor you want on base of those existing ones.
💡 You can also play with all those factors' weights as well in the RecommendedSorter constructor and see the influence on the overall ranking.
💡 In order to get rid of customly ranked results on the listing you can switch to DefaultSorter that sorts all results ascending by their id.
Apart from the project's LICENSE, all car photo samples used in the project are taken from Google search results and all copyrights applies to their respective authors and shouldn't be used further than private/educational use without their explicit consent.




