B2B buyers know what they need to buy and often search using precise product identifiers, such as stock keeping units (SKU).
Or, they search for a product that meets strict specifications, which would match several items in your catalog.
This guide describes how to set up Algolia to make searching and filtering by numbers easier.
Turning off typo tolerance when searching by SKU
Algolia supports searching by SKU and other numbers by default, if you include them as searchable attributes.
By default, typo tolerance is turned on for numbers as well.
That’s helpful when you don’t want to limit the search results to exactly matching numbers, for example, when searching for product variants or physical sizes. When searching by SKU however, it’s better to turn off typo tolerance to allow for more precise searching.
If you add your SKU attribute to disableTypoToleranceOnAttributes
, the search results only include products with exactly matching SKU.
1
2
3
4
5
6
7
| $index->setSettings(
[
'disableTypoToleranceOnAttributes' => [
'serial_number',
... ]
]
);
|
1
| index.set_settings(disableTypoToleranceOnAttributes: ['serial_number', ... ])
|
1
2
3
4
| index.setSettings({'disableTypoToleranceOnAttributes':['serial_number', ... ]})
.then(() => {
// done
});
|
1
| index.set_settings({'disableTypoToleranceOnAttributes': ['serial_number', ... ]})
|
1
2
3
4
5
6
| index.setSettings([
"disableTypoToleranceOnAttributes": [
"serial_number",
...
]
])
|
1
2
3
4
5
6
7
8
| val settings = settings {
disableTypoToleranceOnAttributes {
+"serial_number"
+...
}
}
index.setSettings(settings)
|
1
2
3
4
5
6
7
8
9
10
11
12
| IndexSettings settings = new IndexSettings
{
DisableTypoToleranceOnAttributes = new List<string> {
"serial_number",
...
}
};
index.SetSettings(setting);
// Asynchronous
await index.SetSettingsAsync(settings);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| // Sync version
index.setSettings(
new IndexSettings()
.setDisableTypoToleranceOnAttributes(Arrays.asList(
"serial_number",
...
))
);
// Async version
index.setSettingsAsync(
new IndexSettings()
.setDisableTypoToleranceOnAttributes(Arrays.asList(
"serial_number",
...
))
);
// To add a custom setting for an index,
// extend the class `IndexSettings` and add your getter/setter.
// The new settings will be automatically serialized by jackson.
|
1
2
3
4
5
6
7
| settings := search.Settings{
DisableTypoToleranceOnAttributes: opt.DisableTypoToleranceOnAttributes(
"serial_number",
...
),
}
res, err := index.SetSettings(settings)
|
1
2
3
4
5
6
7
8
| val result: Future[Task] = client.execute {
changeSettings of "myIndex" `with` IndexSettings(
disableTypoToleranceOnAttributes = Some(Seq(
"serial_number",
...
))
)
}
|
Searching in hyphenated attributes
By default, Algolia regards hyphens as separators, so searching for “123-X-456” and “123 X 456” returns the same results. If you also want to allow searching for the number without spaces, for example, “123X456”, it’s important to consider all variations.
Detect searching intent with rules
You can guide buyers effectively by using Rules to detect keywords in a search query.
Let users search by custom aliases for products
B2B buyers often return to buy the same products.
Typing or copying SKUs or other lengthy product identifiers every time can be tedious and error-prone.
Some ecommerce platforms allow buyers to save a custom alias, or reference, for an item.
With Algolia, you can use Rules to support searching by a custom alias to speed up the search.
For example, the buyer can save an alias “my_product” for the product with the ID “123-456-789”.
You can create a rule that detects the alias and replaces it with the product ID.
When the buyer searches for “my_product”, Algolia applies the rule and returns the product matching the SKU.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| const rule = {
objectID: 'user_123_alias_1',
conditions: [
{
pattern: 'my_product',
anchoring: 'contains',
context: 'user_123'
}
],
consequence: {
params: {
query: {
type: 'replace',
delete: 'my_product',
insert: '123-456-789',
}
},
},
}
|
Each buyer defines their own aliases.
To apply the Rule specific to each buyer, you can use ruleContexts
when searching. For example, using an API client:
1
2
3
4
5
6
7
8
9
10
| const index = client.initIndex('catalog');
// get the buyer account information
const buyer = getBuyerAccountId();
index.search('query', {
ruleContext: buyer
}).then(({ hits }) => {
console.log(hits)
});
|
Guide users by increasing search precision
For example, if a buyer searches for “article ref21”, they might look for an item that starts with the number “21”.
If that’s the case, you can create a Rule to increase the precision of the search, by:
- Removing the keyword “article”
- Restricting the searchable attributes to the title and ID
Define a rule using the API clients
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // Turn JSON into an array
$rule = array(
'objectID' => 'article-rule',
'conditions' => array(array(
'pattern' => 'article',
'anchoring' => 'startsWith'
)),
'consequence' => array(
'params' => array(
'query' => array(
'remove' => 'article'
),
'restrictSearchableAttributes' => array(
'title',
'book_id'
)
)
)
);
// Push Rule to index
$index->saveRule($rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # Create the Rule
rule = {
objectID: 'article-rule',
conditions: [{
pattern: 'article',
anchoring: 'startsWith'
}],
consequence: {
params: {
query: {
type: 'remove',
delete: 'article'
},
restrictSearchableAttributes: ['title', 'book_id']
}
}
}
# Save the rule
index.save_rule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // Create the rule
const rule = {
objectID: 'article-rule',
conditions: [{
pattern: 'article',
anchoring: 'startsWith'
}],
consequence: {
params: {
query: {
type: 'remove',
delete: 'article'
},
restrictSearchableAttributes: ['title', 'book_id']
}
}
};
// Save the Rule
index.saveRule(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # Create the Rule
rule = {
'objectID': 'article-rule',
'conditions': [{
'pattern': 'article',
'anchoring': 'startsWith'
}],
'consequence': {
'params': {
'query': {
'type': 'remove',
'delete': 'article'
},
'restrictSearchableAttributes': ['title', 'book_id']
}
}
}
# Save the Rule
response = index.save_rule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // Create the rule
let rule = Rule(objectID: "article-id")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .startsWith)
.set(\.pattern, to: .literal("article"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.query, to: Query()
.set(\.restrictSearchableAttributes, to: [
"title",
"book_id"
])
)
)
// Save the Rule
index.saveRule(rule, forwardToReplicas: true) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| val rules = rules {
rule(
"rule",
listOf(Condition(StartsWith, Literal("article"))),
Consequence(
query = query {
restrictSearchableAttributes {
+"title"
+"book_id"
}
},
edits = edits { +"article" }
)
)
}
index.saveRules(rules)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| var rule = new Rule
{
ObjectID = "article-rule",
Conditions = new List<Condition> { new Condition { Anchoring = "startsWith", Pattern = "article" } },
Consequence = new Consequence
{
Params = new ConsequenceParams
{
SearchableAttributes = new List<string> { "title", "book_id" },
Edits = new List<Edit>
{
new Edit {Type = EditType.Remove, Delete = "article"}
}
}
}
};
index.SaveRule(rule);
// Asynchronous
await index.SaveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| Condition condition = new Condition().setPattern("article").setAnchoring("startsWith");
Consequence consequence = new Consequence();
List<Edit> edits = Collections.singletonList(new Edit().setDelete("article"));
ConsequenceParams params = new ConsequenceParams();
params.setRestrictSearchableAttributes(Arrays.asList("title","book_id"));
params.setConsequenceQuery(new ConsequenceQuery().setEdits(edits));
consequence.setParams(params);
Rule rule =
new Rule()
.setObjectID("article-rule")
.setConditions(Collections.singletonList(condition))
.setConsequence(consequence);
index.saveRule(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| rule := search.Rule{
ObjectID: "article-rule",
Conditions: []search.RuleCondition{{Anchoring: search.StartsWith, Pattern: "article"}},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
Query: search.NewRuleQueryObject(
search.RuleQueryObjectQuery{
Edits: []search.QueryEdit{
search.RemoveEdit("article"),
},
},
),
QueryParams: search.QueryParams{
RestrictSearchableAttributes: opt.RestrictSearchableAttributes(
"title",
"book_id",
),
},
},
},
}
res, err := index.SaveRule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| val rule = Rule(
objectID = "article",
conditions = Some(Seq(Condition(
anchoring = "startsWith",
pattern = "article",
))),
consequence = Consequence(
params = Some(
Map(
"query" -> Map("edits" -> Seq(Edit("delete", "article"))),
"restrictSearchableAttributes" -> Seq("title", "book_id"),
)
)
)
)
client.execute {
save rule rule inIndex "indexName"
}
|
Define a rule using the Algolia Dashboard
- Select the Rules section from the left sidebar menu in the Algolia dashboard.
- Under the heading Rules, select the index you are adding a Rule to.
- Click the New rule button.
- Select Create your first rule or New rule. In the dropdown, click on the Manual Editor option.
- In the Condition(s) section, keep Query toggled on, select Contains in the dropdown, and enter “article” in the input field.
-
In the Consequence(s) section:
- Click the Add consequence button and select Add Query Parameter.
- In the input field that appears, enter the JSON search parameter you want to add. For example,
{ "restrictSearchableAttributes": ["title","id"] }
.
- Click the Add consequence button again and select Remove Word.
- Type or select “article” in the input field.
- Save your changes.