Guides / Managing results / Optimize search results / Override engine defaults

Querying in the Middle of a Word

By design, Algolia doesn’t support infix/suffix matching; therefore it won’t find substrings in the middle or the end of a string. Only prefix matching is natively supported. This means that if a user searches for “note”, this would find records with attributes containing “notepad” or “notebook”, but wouldn’t match “keynote”.

However, there are occasional use cases where this behavior can be useful. Let’s say you have prefixed references in your system (e.g., “XXXABCDEF”) but not on printed catalogs. Therefore, if a user searched for “ABCDEF”, it wouldn’t return the product with reference “XXXABCDEF”. In this case, it would make sense to enable search in the middle of the reference.

To do this with Algolia, you need to generate alternatives.

Partial matching can be dangerous for relevance because they create noise. Make sure you do it sparingly and limit the number of alternatives to what makes sense.

Modifying the data: an example

Before

Let’s say you have the following dataset for products:

1
2
3
4
5
6
7
8
9
10
[
  {
    "name": "Apple iPhone XS",
    "product_reference": "002ABCDEF"
  },
  {
    "name": "Apple iPhone XS Max",
    "product_reference": "001GHIJKL"
  }
]

The product_reference attribute has a numeric prefix, which may exist for internal purposes. The problem is, if a user searches for “ABCDEF” or “GHIJKL”, they won’t find anything.

Since Algolia only supports prefix search, what you need to do to is add an attribute that contains all the possible suffixes for product_reference, as an array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$objects = json_decode(file_get_contents('products.json'), true);

$objects = array_map(function ($record) {
  $reference = $record['product_reference'];

  $record['product_reference_suffixes'] = [];

  while (mb_strlen($reference) > 1) {
    $reference = substr($reference, 1);

    $record['product_reference_suffixes'][] = $reference;
  }

  return $record;
}, $objects);


$index->saveObjects($objects, ['autoGenerateObjectIDIfNotExist' => true]);

After

Once processed, the records should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
[
  {
    "name": "Apple iPhone XS",
    "product_reference": "002ABCDEF",
    "product_reference_suffixes": ["02ABCDEF", "2ABCDEF", "ABCDEF", "BCDEF", "CDEF", "DEF", "EF", "F"]
  },
  {
    "name": "Apple iPhone XS Max",
    "product_reference": "001GHIJKL",
    "product_reference_suffixes": ["01GHIJKL", "1GHIJKL", "GHIJKL", "HIJKL", "IJKL", "JKL", "KL", "L"]
  }
]

We’ve created a new attribute called product_reference_suffixes where we’ve stored all suffixes for the product_reference attribute.

Note that you might not need to generate all possible suffixes, and stop when the reference is of a certain length. As said above, partial matching generates noise, so the more short alternatives you have, the more your search may return irrelevant results.

Updating searchableAttributes

You also need to add product_reference_suffixes to the list of searchable attributes, to ensure the suffixes are searchable along with the original product reference.

1
2
3
4
5
6
7
$index->setSettings([
  'searchableAttributes' => [
    'name',
    'product_reference',
    'product_reference_suffixes'
  ]
]);

It’s recommended to set product_reference_suffixes after product_reference to give it a lower priority. This way, a full match would be considered better than a partial one.

Did you find this page helpful?