Switch rankings based on exact match

I have a dataset of products that have { name, brand } properties.

I want to be able to search on brand, but only when the query is an exact match and never a partial prefix

Example dataset:

{ id: 1, name: 'Apple', brand: null },
{ id: 2, name: 'Apple', brand: 'Applegate' },
{ id: 3, name: 'Orange', brand: 'Sour Grapes' },
{ id: 4, name: 'Yellow Grapes', brand: 'Applegate' },
{ id: 5, name: 'Potatoes', brand: 'Sour Grapes' },
{ id: 6, name: 'Really Sour Grapes', brand: null },

I was a search for:

  • “Apple” to return [ 1, 2 ] only
  • “Grapes” to return [ 4 ] only
  • “Sour Grapes” to return [ 3, 5, 6 ] only (exact brand match, name match should be last)
  • and ideally “Sour Grapes Oranges” to return [ 3, 5 ] (full match on the brand attribute + name, followed by generic brand)

I need partial matching in names, but never in the brand attribute

I’ve tried setting the exact ranking first and name and brand afterwards, but it’s always preferring a name match if it exists

Hi,

I just want to make clear that if apple matches #3 is because the last word of the query is considered as a prefix. So for example, searching for “Apple sour” will not match #4

I’d recommend to read this guide to better understand prefix search:
https://www.algolia.com/doc/guides/textual-relevance/prefix-search

Algolia allows you to desable the prefix search per attributes with the setting disablePrefixOnAttributes. I believe that’s why you’re looking for.

Thanks! That does look promising!

I’m trying to use it and I’m not sure, the index seems to be updated but it does not seem to work:

Using a simple index with the above data and the following setup script:

const algoliasearch = require('algoliasearch');

const client = algoliasearch('<REDACTED>', '<REDACTED>');
const index = client.initIndex('test');

const init = async () => {
    console.log(
        'Disabling prefix on brand:',
        await index.setSettings({
            disablePrefixOnAttributes: [ 'brand' ],
        })
    );

    console.log('');

    await search('grapes');
    await search('apple');
    await search('sour');

    console.log('done');
}

const search = async term =>
    console.log(
        `Search "${term}":\n`,
        ...(await index.search(term))
            .hits
            .map(({ id, name, brand }) => `  id: ${id} | name: ${name} | brand: ${brand}\n`)
    );

init();

The output is bellow. It seems to successfully update the index, but both queries for “Grapes” and “Apple” return brand matches, and even “sour” also prefix matches the brand

Disabling prefix on brand: { updatedAt: '2018-07-03T22:26:37.743Z', taskID: 1420091 }

Search "grapes":
   id: 4 | name: Yellow Grapes | brand: Applegate
   id: 6 | name: Really Sour Grapes | brand: null
   id: 5 | name: Potatoes | brand: Sour Grapes
   id: 3 | name: Orange | brand: Sour Grapes

Search "apple":
   id: 2 | name: Apple | brand: Applegate
   id: 1 | name: Apple | brand: null

Search "sour":
   id: 6 | name: Really Sour Grapes | brand: null
   id: 5 | name: Potatoes | brand: Sour Grapes
   id: 3 | name: Orange | brand: Sour Grapes

done