Guides / Managing results / Rules / Detecting intent

Adding search parameters dynamically

Rules are a powerful tool that let you take decisions for users and improve their experience based on what they search for. When combined with query time settings, you can use rules to make your search smarter.

Imagine you’re developing an app to search for airports. Algolia geolocation feature ranks results based how far or distant an item is from a given point. The problem with this approach is that, depending on your search, the closest airport might not be the most relevant result. For example, for a user in Paris, with a geo-located search experience, the first result they may get is Le Bourget, a small airport near the center of the city that services private jets and air shows. This is an unlikely choice for a top result. Most users will be looking for Roissy CDG or Orly.

Distance-based ranking is convenient when you’re looking for airports based on your location. Yet, as soon as you start looking for specific cities or countries, distance-based ranking doesn’t necessarily work anymore. What yoou want is to keep geo-located results, but turn it off as soon as users search for a specific city or country. In that case, you need to fall back on some other metric, like the number of liaisons. Because many Algolia settings, like aroundLatLngViaIP, are available at query time, you can use rules to detect a search for a specific city or country and change search parameters on the fly.

Dataset example

Back to the airports example, using the following dataset:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[
  {
    "name": "Orly",
    "city": "Paris",
    "country": "France",
    "_geoloc": { "lat": 48.725278, "lng": 2.359444 },
    "nb_airline_liaisons": 404
  },
  {
    "name": "Charles De Gaulle",
    "city": "Paris",
    "country": "France",
    "_geoloc": { "lat": 49.012779, "lng": 2.55 },
    "nb_airline_liaisons": 1041
  },
  {
    "name": "Le Bourget",
    "city": "Paris",
    "country": "France",
    "_geoloc": { "lat": 48.961487, "lng": 2.436966 },
    "nb_airline_liaisons": 0
  },
  {
    "name": "Ben Gurion",
    "city": "Tel-Aviv",
    "country": "Israel",
    "_geoloc": { "lat": 32.011389, "lng": 34.886667 },
    "nb_airline_liaisons": 271
  },
  {
    "name": "Haifa",
    "city": "Haifa",
    "country": "Israel",
    "_geoloc": { "lat": 32.809444, "lng": 35.043056 },
    "nb_airline_liaisons": 4
  },
  {
    "name": "Pudong",
    "city": "Shanghai",
    "country": "China",
    "_geoloc": { "lat": 31.143378, "lng": 121.805214 },
    "nb_airline_liaisons": 825
  },
  {
    "name": "Hongqiao Intl",
    "city": "Shanghai",
    "country": "China",
    "_geoloc": { "lat": 31.197875, "lng": 121.336319 },
    "nb_airline_liaisons": 411
  }
]

The first thing you could do is use nb_airline_liaisons for custom ranking to prioritize airports with many liaisons. Yet, as soon as aroundLatLngViaIP is set to true in your search code, this custom ranking would be overridden in favor of geographical proximity, which is part of ranking formula.

In other words, you would still have the Paris problem because Le Bourget, even if it has the lowest number of liaisons, has the closest geographical proximity to the user.

Other examples: if a user is in Paris and searches for “israel”, they would first get Haifa airport, because this is the Israeli airport that’s the closest to Paris. Yet, it wouldn’t make sense, as Haifa airport is relatively small. “Ben Gurion” is a better choice. Same goes if they were looking for “shanghai”. Hongqiao airport is geographically closer to Paris, but not as big as Pudong airport, which is only 30 km away from Hongqiao.

Fix this by creating a rule that detects searches for a specific city or country and turns off aroundLatLngViaIP as a consequence. Whenever a user specifically looks for a city or country name, like “paris”, “israel”, or “shanghai”, the distance-based search would be turned off, falling back on custom ranking by number of liaisons.

Using the API

To achieve this, you first need to use nb_airline_liaisons for custom ranking. You also need to set city and country as attributes for faceting, so you can detect whenever a query matches any of them.

1
2
3
4
5
6
7
$index->setSettings([
  'customRanking' => [
    'desc(nb_airline_liaisons)'
  ],
  'attributesForFaceting' => [
    'city', 'country'
]);

Then, you can set a Rule that detects matches in facets city and country, and changes the search parameters accordingly. For this, you need to use the batchRules method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$index->saveRules([
  [
    'objectID' => 'country',
    'conditions' => array(array(
      'pattern' => '{facet:country}',
      'anchoring' => 'contains'
    )),
    'consequence' => [
      'params' => [
        'aroundLatLngViaIP' => false
      ]
    ]
  ],
  [
    'objectID' => 'city',
    'conditions' => array(array(
      'pattern' => '{facet:city}',
      'anchoring' => 'contains'
    )),
    'consequence' => [
      'params' => [
        'aroundLatLngViaIP' => false
      ]
    ]
  ]
]);

Using the dashboard

You can also add your Rules in your Algolia dashboard.

Custom ranking

  1. Select the Search product icon on your dashboard and then select your index.
  2. Click on the Configuration tab.
  3. In the Ranking and Sorting section, click the “Add a Custom Ranking” button and select the nb_airline_liaisons attribute from the drop-down menu.
  4. In the Facets subsection of Filtering and Faceting, click the “Add an attribute” button and select the country and city attributes from the drop-down menu.
  5. Save your changes.

Rules

  1. Select the Rules section from the left sidebar menu in the Algolia dashboard.
  2. Under the heading Rules, select the index you are adding a Rule to.
  3. Select Create your first rule or New rule. In the drop-down menu, click the Manual Editor option.
  4. In the Condition(s) section, keep Query toggled on, select Contains in the drop-down menu, and select the option Add Facet “country” from the input drop-down menu. {facet:country} should then be displayed in the input.
  5. In the Consequence(s) section:
    • Click the Add consequence button and select Add Query Parameter.
    • In the input field that appears, add the JSON parameters you want to apply when a user query matches the rule: { "aroundLatLngViaIP": false }
  6. Save your changes.
  7. Click the New Rule button again and then Manual Editor.
  8. In the Condition(s) section, keep Query toggled on, select Contains in the drop-down menu, and select the option Add Facet “city” from the input drop-down menu. {facet:city} should then be displayed in the input.
  9. In the Consequence(s) section:
    • Click the Add consequence button again and select Add Query Parameter.
    • In the input field that appears, add the JSON parameters you want to apply when a user query matches the rule: { "aroundLatLngViaIP": false }
  10. Save your changes.

Query time

Once your Rule is ready, you can search for airports, cities, and countries. When the query exactly matches a city or a country from your dataset, the Rule sets aroundLatLngViaIP to false regardless of the parameters you set in the query.

Therefore, when a user searches for “paris” or “china”, matching airports are ranked by nb_airline_liaisons. When not searching for either a city or a country, airports are ranked by distance to a user’s current location.

1
2
3
$results = $index->search('query', [
  'aroundLatLngViaIP' => true
]);
Did you find this page helpful?