mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-03-06 22:02:34 +08:00
Add a test on filterable attributes rules priority
**Changes:** - Add a new test playing with filterable attributes rules priority - Optimize the faceted field selector avoiding to match false positives
This commit is contained in:
parent
a7a62e5e4c
commit
5fa4b5c50a
@ -623,3 +623,136 @@ async fn search_with_pattern_filter_settings_scenario_1() {
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_filterable_attributes_priority() {
|
||||
// Test that the filterable attributes priority is respected
|
||||
|
||||
// check if doggos.name is filterable
|
||||
test_settings_documents_indexing_swapping_and_search(
|
||||
&NESTED_DOCUMENTS,
|
||||
&json!({"filterableAttributes": [
|
||||
// deactivated filter
|
||||
{"patterns": ["doggos.a*"], "features": {"facetSearch": false, "filter": {"equality": false, "comparison": false}}},
|
||||
// activated filter
|
||||
{"patterns": ["doggos.*"]},
|
||||
]}),
|
||||
&json!({
|
||||
"filter": "doggos.name = bobby"
|
||||
}),
|
||||
|response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 852,
|
||||
"father": "jean",
|
||||
"mother": "michelle",
|
||||
"doggos": [
|
||||
{
|
||||
"name": "bobby",
|
||||
"age": 2
|
||||
},
|
||||
{
|
||||
"name": "buddy",
|
||||
"age": 4
|
||||
}
|
||||
],
|
||||
"cattos": "pésti"
|
||||
}
|
||||
]
|
||||
"###);
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
// check if doggos.name is filterable 2
|
||||
test_settings_documents_indexing_swapping_and_search(
|
||||
&NESTED_DOCUMENTS,
|
||||
&json!({"filterableAttributes": [
|
||||
// deactivated filter
|
||||
{"patterns": ["doggos"], "features": {"facetSearch": false, "filter": {"equality": false, "comparison": false}}},
|
||||
// activated filter
|
||||
{"patterns": ["doggos.*"]},
|
||||
]}),
|
||||
&json!({
|
||||
"filter": "doggos.name = bobby"
|
||||
}),
|
||||
|response, code| {
|
||||
snapshot!(code, @"200 OK");
|
||||
snapshot!(json_string!(response["hits"]), @r###"
|
||||
[
|
||||
{
|
||||
"id": 852,
|
||||
"father": "jean",
|
||||
"mother": "michelle",
|
||||
"doggos": [
|
||||
{
|
||||
"name": "bobby",
|
||||
"age": 2
|
||||
},
|
||||
{
|
||||
"name": "buddy",
|
||||
"age": 4
|
||||
}
|
||||
],
|
||||
"cattos": "pésti"
|
||||
}
|
||||
]
|
||||
"###);
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
// check if doggos.age is not filterable
|
||||
test_settings_documents_indexing_swapping_and_search(
|
||||
&NESTED_DOCUMENTS,
|
||||
&json!({"filterableAttributes": [
|
||||
// deactivated filter
|
||||
{"patterns": ["doggos.a*"], "features": {"facetSearch": false, "filter": {"equality": false, "comparison": false}}},
|
||||
// activated filter
|
||||
{"patterns": ["doggos.*"]},
|
||||
]}),
|
||||
&json!({
|
||||
"filter": "doggos.age > 2"
|
||||
}),
|
||||
|response, code| {
|
||||
snapshot!(code, @"400 Bad Request");
|
||||
snapshot!(json_string!(response), @r###"
|
||||
{
|
||||
"message": "Index `test`: Attribute `doggos.age` is not filterable. Available filterable attributes are: `doggos.age`, `doggos.name`.\n1:11 doggos.age > 2",
|
||||
"code": "invalid_search_filter",
|
||||
"type": "invalid_request",
|
||||
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
|
||||
}
|
||||
"###);
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
// check if doggos is not filterable
|
||||
test_settings_documents_indexing_swapping_and_search(
|
||||
&NESTED_DOCUMENTS,
|
||||
&json!({"filterableAttributes": [
|
||||
// deactivated filter
|
||||
{"patterns": ["doggos"], "features": {"facetSearch": false, "filter": {"equality": false, "comparison": false}}},
|
||||
// activated filter
|
||||
{"patterns": ["doggos.*"]},
|
||||
]}),
|
||||
&json!({
|
||||
"filter": "doggos EXISTS"
|
||||
}),
|
||||
|response, code| {
|
||||
snapshot!(code, @"400 Bad Request");
|
||||
snapshot!(json_string!(response), @r###"
|
||||
{
|
||||
"message": "Index `test`: Attribute `doggos` is not filterable. Available filterable attributes are: `doggos.age`, `doggos.name`.\n1:7 doggos EXISTS",
|
||||
"code": "invalid_search_filter",
|
||||
"type": "invalid_request",
|
||||
"link": "https://docs.meilisearch.com/errors#invalid_search_filter"
|
||||
}
|
||||
"###);
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
@ -342,16 +342,31 @@ fn match_pattern_by_features(
|
||||
filter: &impl Fn(&FilterableAttributesFeatures) -> bool,
|
||||
) -> PatternMatch {
|
||||
let mut selection = PatternMatch::NoMatch;
|
||||
|
||||
// `can_match` becomes false if the field name matches (PatternMatch::Match) any pattern that is not facet searchable or filterable,
|
||||
// this ensures that the field doesn't match a pattern with a lower priority, however it can still match a pattern for a nested field as a parent (PatternMatch::Parent).
|
||||
// See the test `search::filters::test_filterable_attributes_priority` for more details.
|
||||
let mut can_match = true;
|
||||
|
||||
// Check if the field name matches any pattern that is facet searchable or filterable
|
||||
for pattern in filterable_attributes {
|
||||
match pattern.match_str(field_name) {
|
||||
PatternMatch::Match => {
|
||||
let features = pattern.features();
|
||||
if filter(&features) && can_match {
|
||||
return PatternMatch::Match;
|
||||
} else {
|
||||
can_match = false;
|
||||
}
|
||||
}
|
||||
PatternMatch::Parent => {
|
||||
let features = pattern.features();
|
||||
if filter(&features) {
|
||||
match pattern.match_str(field_name) {
|
||||
PatternMatch::Match => return PatternMatch::Match,
|
||||
PatternMatch::Parent => selection = PatternMatch::Parent,
|
||||
PatternMatch::NoMatch => (),
|
||||
selection = PatternMatch::Parent;
|
||||
}
|
||||
}
|
||||
PatternMatch::NoMatch => (),
|
||||
}
|
||||
}
|
||||
|
||||
selection
|
||||
|
Loading…
x
Reference in New Issue
Block a user