You can use Rules to add filters dynamically depending on what the user types.
Filter by color
Consider the query “red t-shirt”. A customer wants Algolia to recognize “red” as a color and therefore restrict the search only to records containing “red” in their color attribute whenever the keyword “red” is typed in.
Rule
If query contains ‘red’ then filter by color=red
Option 1 - Using filters
Using the API
One approach is to use the filters
parameter. With this approach, you will need to have 1 Rule per filter value. So if you have 10 color options, you will need to create 10 Rules, 1 for each color.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| $rule = array(
'objectID' => 'red-color',
'conditions' => array(array(
'pattern' => 'red',
'anchoring' => 'contains'
)),
'consequence' => array(
'params' => array(
'query' => array(
'remove' => 'red'
),
'filters' => 'color:red'
)
)
);
// Push Rule to index
$index->saveRule($rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| index.save_rule('red-color', {
objectID: 'red-color',
conditions: [{
pattern: 'red',
anchoring: 'contains'
}],
consequence: {
params: {
query: {
remove: ['red']
},
filters: 'color:red'
}
}
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| index.saveRule({
objectID: 'red-color',
condition: {
pattern: 'red',
anchoring: 'contains',
},
consequence: {
params: {
query: {
remove: 'red',
},
filters: 'color:red',
},
},
});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| rule = {
"objectID": "red-color",
"condition": {
"anchoring": "contains",
"pattern": "red",
},
"consequence": {
"params": {
"query": {
"remove": ["red"],
},
"filters": "color:red",
}
}
}
response = index.save_rule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| let rule = Rule(objectID: "red-color")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .contains)
.set(\.pattern, to: .literal("red"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.queryTextAlteration, to: .edits([.remove("read")]))
.set(\.query, to: Query().set(\.filters, to: "color:red"))
)
index.saveRule(rule) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
| val rule = Rule(
objectID = ObjectID("red-color"),
conditions = listOf(
Condition(anchoring = Anchoring.Contains, pattern = Pattern.Literal("red"))
),
consequence = Consequence(
query = Query(filters = "color:red"),
edits = listOf(Edit(delete = "read"))
)
)
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
24
25
| var rule = new Rule
{
ObjectID = "red-color",
Conditions = new List<Condition> {
new Condition { Anchoring = "contains", Pattern = "red" }
},
Consequence = new Consequence
{
Params = new ConsequenceParams {
Filters = "color:red",
Query = new ConsequenceQuery {
Edits = new List<Edit> {
new Edit {
Delete = "red"
}
}
}
}
}
};
index.SaveRule(rule);
// Asynchronous
await index.SaveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| Condition condition = new Condition()
.setAnchoring("contains")
.setPattern("red");
ConsequenceParams params =
new ConsequenceParams()
.setFilters("color:red")
.setConsequenceQuery(
new ConsequenceQuery()
.setEdits(Collections.singletonList(Edit.createDelete("read"))));
Consequence consequence = new Consequence()
.setParams(params);
Rule rule = new Rule()
.setObjectID("red-color")
.setConditions(Collections.singletonList(condition))
.setConsequence(consequence);
index.saveRule(rule);
// Asynchronous
index.saveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| rule := search.Rule{
ObjectID: "red-color",
Condition: search.RuleCondition{Anchoring: search.Contains, Pattern: "red"},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
Query: search.NewRuleQueryObject(
search.RuleQueryObjectQuery{
Edits: []search.QueryEdit{
search.RemoveEdit("red"),
},
},
),
QueryParams: search.QueryParams{
Filters: opt.Filters("color:red"),
},
},
},
}
res, err := index.SaveRule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| val rule = Rule(
objectID = "red-color",
condition = Some(
Condition(
pattern = "red",
anchoring = "contains"
)
),
consequence = Consequence(
params = Some(
Map(
"query" -> Map("remove" -> "red"),
"filters" -> "color:red"
)
)
)
)
client.execute {
save rule rule inIndex "indexName"
}
|
Using the dashboard
- Select the Search product icon on your dashboard and then select your index.
- 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.
- 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 “red” 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, add the JSON parameters you want to apply when the user’s query matches the Rule:
{"filters":"color:red"}
- Click the Add consequence button and select Remove Word.
- Type or select “red” in the input field.
- Don’t forget to save your changes.
Option 2: Using facets
This alternative method is only available through our Premium plans.
Using the API
This approach uses facets. With facets, instead of creating 1 Rule for each color, you create 1 Rule per facet. So if you have the facet ‘color’, then 1 Rule will handle every color value. For example, if the query includes red, and if red matches a value in the color facet, the Rule will be triggered.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // Turn JSON into an array
$rule = array(
'objectID' => 'color-facets',
'conditions' => array(array(
'pattern' => '{facet:color}'
)),
'consequence' => array(
'params' => array(
'automaticFacetFilters' => ['color']
)
)
);
// Push Rule to index
$index->saveRule($rule['objectID'], $rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
| index.save_rule('color-facets', {
objectID: 'color-facets',
conditions: [{
pattern: '{facet:color}',
anchoring: 'contains'
}],
consequence: {
params: {
automaticFacetFilters: ['color']
}
}
})
|
1
2
3
4
5
6
7
8
9
10
11
| index.saveRule({
objectID: 'color-facets',
condition: {
pattern: '{facet:color}',
},
consequence: {
params: {
automaticFacetFilters: ['color'],
},
},
});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| rule = {
"objectID": "color-facets",
"condition": {
"anchoring": "contains",
"pattern": "{facet:color}",
},
"consequence": {
"params": {
"automaticFacetFilters": ["color"],
},
},
}
response = index.save_rule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| let rule = Rule(objectID: "color-facets")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .contains)
.set(\.pattern, to: .literal("{facet:color}"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.automaticFacetFilters, to: [.init(attribute: "color")])
)
index.saveRule(rule) { 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
| val rule = Rule(
objectID = ObjectID("color-facets"),
conditions = listOf(
Condition(
anchoring = Anchoring.Contains,
pattern = Pattern.Literal("{facet:color}")
)
),
consequence = Consequence(
automaticFacetFilters = listOf(
AutomaticFacetFilters(attribute = Attribute("color"))
)
)
)
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
| var rule = new Rule
{
ObjectID = "color-facets",
Conditions = new List<Condition> {
new Condition { Anchoring = "contains", Pattern = "facet:color" }
},
Consequence = new Consequence
{
Params = new ConsequenceParams {
AutomaticFacetFilters = new List<AutomaticFacetFilter> {
new AutomaticFacetFilter {
Facet = "color"
}
}
}
}
};
index.SaveRule(rule);
// Asynchronous
await index.SaveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| Condition condition = new Condition()
.setAnchoring("contains")
.setPattern("{facet:color}");
ConsequenceParams params = new ConsequenceParams()
.setAutomaticFacetFilters(Collections.singletonList(new AutomaticFacetFilter("color")));
Consequence consequence = new Consequence()
.setParams(params);
Rule rule =
new Rule()
.setObjectID("color-facets")
.setConditions(Collections.singletonList(condition))
.setConsequence(consequence);
index.saveRule(rule);
// Asynchronous
index.saveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
| rule := search.Rule{
ObjectID: "color-facets",
Condition: search.RuleCondition{Anchoring: search.Contains, Pattern: "{facet:color}"},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
AutomaticFacetFilters: []search.AutomaticFacetFilter{{Facet: "color"}},
},
},
}
res, err := index.SaveRule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| val rule = Rule(
objectID = "color-facets",
condition = Some(
Condition(
pattern = "{facet:color}",
anchoring = "contains"
)
),
consequence = Consequence(
params = Some(
Map(
"automaticFacetFilters" -> Seq("color")
)
)
)
)
client.execute {
save rule rule inIndex "indexName"
}
|
You can replace automaticFacetFilters
with automaticOptionalFacetFilters
, they share the same syntax. This includes non-red t-shirts below the red ones. Learn more about optionalFilters
.
Using the dashboard (facets)
This alternative method is only available through our Premium plans.
- Select the Search product icon on your dashboard and then select your index.
- 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.
- Select Create your first rule or New rule. In the dropdown, click on the Manual Editor option.
- In the Condition(s) sections, keep Query contains and select the option Add Facet “color” from the input dropdown.
{facet:color}
should then be displayed in the input.
- In the Consequence(s) section:
- Don’t forget to save your changes.
Filter by type
Show only “shirts” whenever the engine detected a kind of shirt like “t-shirt”.
Rule
If query contains ‘t-shirt’ then filter by type=shirt
Using the API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| // Turn JSON into an array
$rule = array(
'objectID' => 't-shirt',
'conditions' => array(array(
'pattern' => 't-shirt',
'anchoring' => 'contains'
)),
'consequence' => array(
'params' => array(
'query' => array(
'remove' => 't-shirt'
),
'filters' => 'clothing_type:shirt'
)
)
);
// Push Rule to index
$index->saveRule($rule['objectID'], $rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| index.save_rule('t-shirt', {
objectID: 't-shirt',
conditions: [{
pattern: 't-shirt',
anchoring: 'contains'
}],
consequence: {
params: {
query: {
remove: ['t-shirt']
},
filters: 'clothing_type:shirt'
}
}
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| index.saveRule({
objectID: 't-shirt',
condition: {
pattern: 't-shirt',
anchoring: 'contains',
},
consequence: {
params: {
query: {
remove: 't-shirt',
},
filters: 'clothing_type:shirt',
},
},
});
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| rule = {
"objectID": "t-shirt",
"condition": {
"anchoring": "contains",
"pattern": "t-shirt",
},
"consequence": {
"params": {
"query": {
"remove": ["t-shirt"],
},
"filters": "clothing_type:shirt",
},
},
}
response = index.save_rule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| let rule = Rule(objectID: "t-shirt")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .contains)
.set(\.pattern, to: .literal("t-shirt"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.queryTextAlteration, to: .edits([.remove("t-shirt")]))
.set(\.query, to: Query().set(\.filters, to: "clothing_type:shirt"))
)
index.saveRule(rule) { 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
| val rule = Rule(
objectID = ObjectID("t-shirt"),
conditions = listOf(
Condition(
anchoring = Anchoring.Contains,
pattern = Pattern.Literal("t-shirt")
)
),
consequence = Consequence(
edits = listOf(Edit(delete = "t-shirt")),
query = Query(filters = "clothing_type:shirt")
)
)
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
24
25
26
| var rule = new Rule
{
ObjectID = "t-shirt",
Conditions = new List<Condition> {
new Condition { Anchoring = "contains", Pattern = "t-shirt" }
},
Consequence = new Consequence
{
Params = new ConsequenceParams {
Filters = "clothing_type:shirt",
Query = new ConsequenceQuery {
Edits = new List<Edit> {
new Edit {
Delete = "t-shirt"
}
}
}
}
}
};
index.SaveRule(rule);
// Asynchronous
await index.SaveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| Condition condition = new Condition()
.setAnchoring("contains")
.setPattern("t-shirt");
ConsequenceParams params =
new ConsequenceParams()
.setFilters("clothing_type:shirt")
.setConsequenceQuery(
new ConsequenceQuery()
.setEdits(Collections.singletonList(Edit.createDelete("t-shirt"))));
Consequence consequence = new Consequence()
.setParams(params);
Rule rule =
new Rule()
.setObjectID("t-shirt")
.setConditions(Collections.singletonList(condition))
.setConsequence(consequence);
index.saveRule(rule);
// Asynchronous
index.saveRuleAsync(rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| rule := search.Rule{
ObjectID: "t-shirt",
Condition: search.RuleCondition{Anchoring: search.Contains, Pattern: "t-shirt"},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
Query: search.NewRuleQueryObject(
search.RuleQueryObjectQuery{
Edits: []search.QueryEdit{
search.RemoveEdit("t-shirt"),
},
},
),
QueryParams: search.QueryParams{
Filters: opt.Filters("clothing_type:shirt"),
},
},
},
}
res, err := index.SaveRule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| val rule = Rule(
objectID = "t-shirt",
condition = Some(
Condition(
pattern = "t-shirt",
anchoring = "contains"
)
),
consequence = Consequence(
params = Some(
Map(
"query" -> Map("remove" -> Seq("t-shirt")),
"filters" -> "clothing_type:shirt"
)
)
)
)
client.execute {
save rule rule inIndex "indexName"
}
|
Using the dashboard
- Select the Search product icon on your dashboard and then select your index.
- 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.
- 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 “t-shirt” 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, add the JSON parameters you want to apply when the user’s query matches the Rule:
{"filters":"clothing_type:shirt"}
- Click the Add consequence button and select Remove Word.
- Type or select “t-shirt” in the input field.
- Don’t forget to save your changes.
Numerical filtering
Imagine the query “cheap toaster 800w”. Rules can be used to filter the results by “toaster” and “prices between 0 and 25”, so that the only textual search is the remaining term, “800w”, which could further be used to limit the results with that wattage.
Rule
If query = “cheap toaster” then price < 10 and type=toaster
Note: This requires 2 Rules.
Using the API
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
| // Turn JSON into an array
$rules = array(
array(
'objectID' => 'toaster',
'conditions' => array(array(
'pattern' => 'toaster',
'anchoring' => 'contains'
)),
'consequence' => array(
'params' => array(
'query' => array(
'remove' => 'toaster'
),
'filters' => 'product_type:toaster'
)
)
),
array(
'objectID' => 'cheap',
'condition' => array(
'pattern' => 'cheap',
'anchoring' => 'contains'
),
'consequence' => array(
'params' => array(
'query' => array(
'remove' => 'cheap'
),
'filters' => 'price < 10'
)
)
)
);
// Push Rule to index
$index->saveRules($rules);
|
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
| index.batch_rules([
{
objectID: 'toaster',
conditions: [{
pattern: 'toaster',
anchoring: 'contains'
}],
consequence: {
params: {
query: {
remove: ['toaster']
},
filters: 'product_type:toaster'
}
}
},
{
objectID: 'cheap',
conditions: [{
pattern: 'cheap',
anchoring: 'contains'
}],
consequence: {
params: {
query: {
remove: ['cheap']
},
filters: 'price < 10'
}
}
}
])
|
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
| index.saveRules([
{
objectID: 'toaster',
condition: {
pattern: 'toaster',
anchoring: 'contains',
},
consequence: {
params: {
query: {
remove: 'toaster',
},
filters: 'product_type:toaster',
},
},
},
{
objectID: 'cheap',
condition: {
pattern: 'cheap',
anchoring: 'contains',
},
consequence: {
params: {
query: {
remove: 'cheap',
},
filters: 'price < 10',
},
},
},
]);
|
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
| rules = [
{
"objectID": "toaster",
"condition": {
"anchoring": "contains",
"pattern": "toaster",
},
"consequence": {
"params": {
"query": {
"remove": ["toaster"],
},
"filters": "product_type:toaster",
},
},
},
{
"objectID": "cheap",
"condition": {
"anchoring": "contains",
"pattern": "cheap",
},
"consequence": {
"params": {
"query": {
"remove": ["cheap"],
},
"filters": "price < 10",
},
},
},
]
response = index.save_rules(rules)
|
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
| let toasterRule = Rule(objectID: "toaster")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .contains)
.set(\.pattern, to: .literal("toaster"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.queryTextAlteration, to: .edits([.remove("toaster")]))
.set(\.query, to: Query().set(\.filters, to: "product_type:toaster"))
)
let cheapRule = Rule(objectID: "cheap")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .contains)
.set(\.pattern, to: .literal("cheap"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.queryTextAlteration, to: .edits([.remove("cheap")]))
.set(\.query, to: Query().set(\.filters, to: "price < 10"))
)
index.saveRules([toasterRule, cheapRule]) { 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
18
19
20
21
22
23
| val toasterRule = Rule(
objectID = ObjectID("toaster"),
conditions = listOf(
Condition(anchoring = Anchoring.Contains, pattern = Pattern.Literal("toaster"))
),
consequence = Consequence(
query = Query(filters = "product_type:toaster"),
edits = listOf(Edit(delete = "toaster"))
)
)
val cheapRule = Rule(
objectID = ObjectID("cheap"),
conditions = listOf(
Condition(anchoring = Anchoring.Contains, pattern = Pattern.Literal("cheap"))
),
consequence = Consequence(
query = Query(filters = "price < 10"),
edits = listOf(Edit(delete = "cheap"))
)
)
index.saveRules(listOf(toasterRule, cheapRule))
|
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
| var rules = new List<Rule> {
new Rule
{
ObjectID = "toaster",
Conditions = new List<Condition> {
new Condition { Anchoring = "contains", Pattern = "toaster" }
},
Consequence = new Consequence
{
Params = new ConsequenceParams {
Filters = "product_type:toaster",
Query = new ConsequenceQuery {
Edits = new List<Edit> {
new Edit {
Delete = "toaster"
}
}
}
}
}
},
new Rule
{
ObjectID = "cheap",
Conditions = new List<Condition> {
new Condition { Anchoring = "contains", Pattern = "cheap" }
},
Consequence = new Consequence
{
Params = new ConsequenceParams {
Filters = "price < 10",
Query = new ConsequenceQuery {
Edits = new List<Edit> {
new Edit {
Delete = "cheap"
}
}
}
}
}
},
};
index.SaveRules(rules);
// Asynchronous
await index.SaveRulesAsync(rules);
|
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
| Condition toasterCondition = new Condition()
.setAnchoring("contains")
.setPattern("toaster");
Consequence toasterConsequence = new Consequence()
.setParams(new ConsequenceParams()
.setFilters("product_type:toaster")
.setConsequenceQuery(
new ConsequenceQuery()
.setEdits(Collections.singletonList(Edit.createDelete("toaster")))));
Rule toasterRule =
new Rule()
.setObjectID("toaster")
.setConditions(Collections.singletonList(toasterCondition))
.setConsequence(toasterConsequence);
Condition cheapCondition = new Condition()
.setAnchoring("contains")
.setPattern("cheap");
Consequence cheapConsequence = new Consequence()
.setParams(new ConsequenceParams()
.setFilters("price < 10")
.setConsequenceQuery(
new ConsequenceQuery()
.setEdits(Collections.singletonList(Edit.createDelete("cheap")))));
Rule cheapRule =
new Rule()
.setObjectID("cheap")
.setConditions(Collections.singletonList(cheapCondition))
.setConsequence(cheapConsequence);
List<Rule> rules = Arrays.asList(toasterRule, cheapRule);
index.saveRules(rules);
// Asynchronous
index.saveRulesAsync(rules);
|
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
| toasterRule := search.Rule{
ObjectID: "toaster",
Condition: search.RuleCondition{Anchoring: search.Contains, Pattern: "toaster"},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
Query: search.NewRuleQueryObject(
search.RuleQueryObjectQuery{
Edits: []search.QueryEdit{
search.RemoveEdit("toaster"),
},
},
),
QueryParams: search.QueryParams{
Filters: opt.Filters("product_type:toaster"),
},
},
},
}
cheapRule := search.Rule{
ObjectID: "cheap",
Condition: search.RuleCondition{Anchoring: search.Contains, Pattern: "cheap"},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
Query: search.NewRuleQueryObject(
search.RuleQueryObjectQuery{
Edits: []search.QueryEdit{
search.RemoveEdit("toaster"),
},
},
),
QueryParams: search.QueryParams{
Filters: opt.Filters("product_type:toaster"),
},
},
},
}
rules := []search.Rule{toasterRule, cheapRule}
res, err := index.SaveRules(rules)
|
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
| client.execute {
save rules Seq(
Rule(
objectID = "toaster",
condition = Some(
Condition(
pattern = "toaster",
anchoring = "contains"
)
),
consequence = Consequence(
params = Some(
Map(
"query" -> Map("remove" -> Seq("toaster")),
"filters" -> "product_type:toaster"
)
)
)
)
Rule(
objectID = "cheap",
condition = Some(
Condition(
pattern = "cheap",
anchoring = "contains"
)
),
consequence = Consequence(
params = Some(
Map(
"query" -> Map("remove" -> Seq("cheap")),
"filters" -> "price < 10"
)
)
)
)
) inIndex "myIndex"
|
Using the dashboard
Create the first rule:
- Select the Search product icon on your dashboard and then select your index.
- 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.
- 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 “toaster” 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, add the JSON parameters you want to apply when the user’s query matches the Rule:
{"filters":"product_type:toaster"}
- Click the Add consequence button and select Remove Word.
- Type or select “toaster” in the input field.
- Don’t forget to save your changes.
Then the second rule:
- Select Create your first rule or New rule. In the dropdown, click on the Manual Editor option.
- In the Condition(s) section, keep Query contains and enter “cheap” 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, add the JSON parameters you want to apply when the user’s query matches the Rule:
{"filters":"price < 10"}
- Click the Add consequence button and select Remove Word.
- Type or select “cheap” in the input field.
- Don’t forget to save your changes.
Tagged filters
One interesting pattern you can leverage with Rules is tagged filters. Instead of automatically filtering when a search term matches a facet value, tagged filters let users apply filters with prefixes. For example, you could imagine a query like “headphones brand:apple”, which would search for results that match the term “headphones”, but only where the brand
attribute matches “apple”.
You can find this behavior on applications such as GitHub or Slack. They provide great alternative to refinement lists for users who prefer to type rather than click.
Rule
If query contains “brand:apple” then filter on brand=Apple
This feature is only available to Premium plans.
Using the API
This approach uses facets. With facets, instead of creating a Rule for each facet value, you create one Rule per facet. For example, we can create a Rule for the facet brand
, which handles all our facet values for the brand
facet. This way, our Rule will activate if our query contains “Apple”, if you have at least one record with “Apple” in the brand
attribute.
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
| $rule = array (
'conditions' => array(
array (
'pattern' => 'brand\\: {facet:brand}',
'anchoring' => 'contains',
'alternatives' => false,
)),
'consequences' =>
array (
array (
'params' =>
array (
'automaticFacetFilters' =>
array (
'brand',
),
'query' =>
array (
'remove' =>
array (
'brand\\:',
'{facet:brand}',
),
),
),
),
),
'description' => 'filter on brand: {brand}',
'objectID' => 'tagged-brand-rule',
);
$response = $index->saveRule($rule['objectID'], $rule);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| rule = {
conditions: [{
pattern: 'brand\\: {facet:brand}',
anchoring: 'contains',
alternatives: false
}],
consequences: [
{
params: {
automaticFacetFilters: ['brand'],
query: {
remove: ['brand\\:', '{facet:brand}']
}
}
}
],
description: 'filter on brand: {brand}',
objectID: 'tagged-brand-rule'
}
index.save_rule(rule['objectID'], rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| const rule = {
condition: {
pattern: 'brand\\: {facet:brand}',
anchoring: 'contains',
alternatives: false,
},
consequences: [
{
params: {
automaticFacetFilters: ['brand'],
query: {
remove: ['brand\\:', '{facet:brand}'],
},
},
},
],
description: 'filter on brand: {brand}',
objectID: 'tagged-brand-rule',
};
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
24
| rule = {
"description": "filter on brand: {brand}",
"objectID": "tagged-brand-rule",
"conditions": [{
"pattern": "brand\\: {facet:brand}",
"anchoring": "contains",
"alternatives": False,
}],
"consequence": {
"params": {
"query": {
"edits": [
{"type": "remove", "delete": "brand\\:"},
{"type": "remove", "delete": "{facet:brand}"}
]
},
"automaticFacetFilters": [
{"facet": "brand"},
]
}
}
}
response = index.save_rule(rule)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| let rule = Rule(objectID: "tagged-brand-rule")
.set(\.conditions, to: [
Rule.Condition()
.set(\.anchoring, to: .contains)
.set(\.pattern, to: .literal("brand\\: {facet:brand"))
])
.set(\.consequence, to: Rule.Consequence()
.set(\.automaticFacetFilters, to: [.init(attribute: "brand")])
.set(\.queryTextAlteration, to: .edits([
.remove("brand\\:"),
.remove("{facet:brand}")
]))
)
index.saveRule(rule) { 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
| val rule = Rule(
objectID = ObjectID("tagged-brand-rule"),
conditions = listOf(
Condition(
anchoring = Anchoring.Contains,
pattern = Pattern.Literal("brand\\: {facet:brand}"),
alternative = Alternatives.False
)
),
consequence = Consequence(
automaticFacetFilters = listOf(AutomaticFacetFilters(attribute = Attribute("brand"))),
edits = listOf(Edit(delete = "brand\\:"), Edit(delete = "{facet:brand}"))
)
)
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
24
25
26
27
28
| var rule = new Rule
{
Condition = new Condition { Anchoring = "contains", Pattern = "brand\\: {facet:brand}", Alternatives = Alternatives.Of(false) },
Consequence = new Consequence
{
Params = new ConsequenceParams
{
AutomaticFacetFilters = new List<AutomaticFacetFilter> {
new AutomaticFacetFilter { Facet = "brand"}
},
Query = new ConsequenceQuery
{
Edits = new List<Edit> {
new Edit { Type = EditType.Remove, Delete = "brand\\:" },
new Edit { Type = EditType.Remove, Delete = "{facet:brand}" }
}
}
}
},
Description = "filter on brand: {brand}",
ObjectID = "tagged-brand-rule"
};
index.SaveRule(rule);
// Asynchronous
await index.SaveRuleAsync(rule);
|
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
| Condition condition =
new Condition()
.setAnchoring("contains")
.setPattern("brand\\: {facet:brand}")
.setAlternatives(Alternatives.of(false));
ConsequenceParams params =
new ConsequenceParams()
.setAutomaticFacetFilters(
Collections.singletonList(new AutomaticFacetFilter("brand")))
.setConsequenceQuery(
new ConsequenceQuery()
.setEdits(
Arrays.asList(
Edit.createDelete("brand\\:"),
Edit.createDelete("{facet:brand}"))));
Consequence consequence = new Consequence().setParams(params);
Rule rule =
new Rule()
.setObjectID("tagged-brand-rule")
.setConditions(Collections.singletonList(condition))
.setConsequence(consequence);
index.saveRule(rule);
// Asynchronous
index.saveRuleAsync(rule);
|
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
| rule := search.Rule{
ObjectID: "tagged-brand-rule",
Description: "filter on brand: {brand}",
Conditions: []search.RuleCondition{
{
Pattern: "brand\\: {facet:brand}",
Anchoring: search.Contains,
Alternatives: search.AlternativesDisabled(),
},
},
Consequence: search.RuleConsequence{
Params: &search.RuleParams{
AutomaticFacetFilters: []search.AutomaticFacetFilter{
{Facet: "brand"},
},
Query: search.NewRuleQueryObject(
search.RuleQueryObjectQuery{
Edits: []search.QueryEdit{
search.RemoveEdit("brand\\:"),
search.RemoveEdit("{facet:brand}"),
},
},
),
},
},
}
res, err := 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
24
25
26
27
28
| val rule = Rule(
objectID = "tagged-brand-rule",
description = Some("filter on brand: {brand}"),
condition = Some(
Condition(
pattern = "brand\\: {facet:brand}",
anchoring = "contains",
alternatives = Some(Alternatives.`false`)
)
),
consequence = Consequence(
params = Some(
Map(
"query" -> Map(
"edits" -> Seq(
Map("type" -> "remove", "delete" -> "brand\\:"),
Map("type" -> "remove", "delete" -> "{facet:brand}")
)
),
"automaticFacetFilters" -> Map("facet" -> "brand")
)
)
)
)
client.execute {
save rule rule inIndex "index_name"
}
|
You can replace automaticFacetFilters
with automaticOptionalFacetFilters
, they share the same syntax. This includes non-Apple items below the Apple ones. Learn more about optionalFilters
.
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.
- 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 select the option Add Facet “brand” from the input dropdown.
{facet:brand}
should then be displayed in the input.
- Uncheck the Apply to plurals, synonyms and typos checkbox.
- In the Consequence(s) section:
- Click the Add consequence button and select Filter / Boost Matching Attributes.
- In the Filter input that appears, select the option Add Facet “brand” in the dropdown.
- You can use the Optional toggle to switch between
automaticFacetFilters
and automaticOptionalFacetFilters
.
- Select whether you want the filter to be disjunctive or conjunctive.
- Click the Add consequence button and select Remove word.
- In the input that appears, select Remove “{facet:brand}”.
- Don’t forget to save your changes.