Multiple filter clauses on same index field + sort on other field causes wrong index selection
Author: matchoCreated Aug 4, 2026Updated Sep 15, 2026
Hello,
Query 1 uses index on computed.image_tags[*].name, computed.image_tags[*].value as expected, and is very fast.
Query 2 (multiple filter clauses) switches to index on date_created.
This is inconsistent, and doesn't seem relevant as 2 filter clauses on the same field are more restrictive than 1.
edit: version3.12.8 enterprise
Thank you, Best regards,
Mathias
indexes in the collection (among many others) :
| name | type | fields | unique | selectivity |
|---|---|---|---|---|
| idx_1700732696947326976 | Persistent | date_created, geoloc.lat | false | 62.96% |
| idx_1825111849464496128 | Persistent | computed.image_tags[].name, computed.image_tags[].value | false | 1.15% |
query 1
FOR o IN z_obs
FILTER 'report_ai' IN o.computed.image_tags[*].name
SORT o.date_created DESC
LIMIT 0, 100
RETURN o._keyexplain query 1
Query String (127 chars, results cachable: true):
FOR o IN z_obs
FILTER 'report_ai' IN o.computed.image_tags[*].name
SORT o.date_created DESC
LIMIT 0, 100
RETURN o._key
Execution plan:
Id NodeType Par Est. Comment
1 SingletonNode 1 * ROOT
10 IndexNode 162447 - FOR o IN z_obs /* persistent index scan, scan only */ /* with late materialization */
11 MaterializeNode 162447 - MATERIALIZE o INTO #7 /* (projections: `_key`, `date_created`) */ LET #8 = #7.`_key`, #9 = #7.`date_created`
6 SortNode 162447 - SORT #9 DESC /* sorting strategy: constrained heap */
7 LimitNode 100 - LIMIT 0, 100
9 ReturnNode 100 - RETURN #8
Indexes used:
By Name Type Collection Unique Sparse Cache Selectivity Fields Stored values Ranges
10 idx_1825111849464496128 persistent z_obs false false false 1.15 % [ `computed.image_tags[*].name`, `computed.image_tags[*].value` ] [ ] ("report_ai" IN o.`computed`.`image_tags`[*].`name`)
Optimization rules applied:
Id Rule Name Id Rule Name Id Rule Name
1 move-calculations-up 6 remove-filter-covered-by-index 11 push-down-late-materialization
2 move-filters-up 7 remove-unnecessary-calculations-2 12 materialize-into-separate-variable
3 move-calculations-up-2 8 sort-limit 13 optimize-projections
4 move-filters-up-2 9 reduce-extraction-to-projection 14 remove-unnecessary-calculations-4
5 use-indexes 10 batch-materialize-documents
59 rule(s) executed, 1 plan(s) created, peak mem [b]: 0, exec time [s]: 0.00120query 2
FOR o IN z_obs
FILTER 'report_ai' IN o.computed.image_tags[*].name
FILTER 'report_screen' IN o.computed.image_tags[*].name
SORT o.date_created DESC
LIMIT 0, 100
RETURN o._keyexplain query 2
Query String (185 chars, results cachable: true):
FOR o IN z_obs
FILTER 'report_ai' IN o.computed.image_tags[*].name
FILTER 'report_screen' IN o.computed.image_tags[*].name
SORT o.date_created DESC
LIMIT 0, 100
RETURN o._key
Execution plan:
Id NodeType Par Est. Comment
1 SingletonNode 1 * ROOT
12 IndexNode 3248955 - FOR o IN z_obs /* reverse persistent index scan, index scan + document lookup (filter projections: `computed`.`image_tags`) (projections: `_key`) */ LET #9 = o.`_key` FILTER (("report_ai" IN o.`computed`.`image_tags`[*].`name`) && ("report_screen" IN o.`computed`.`image_tags`[*].`name`)) /* early pruning */
9 LimitNode 100 - LIMIT 0, 100
11 ReturnNode 100 - RETURN #9
Indexes used:
By Name Type Collection Unique Sparse Cache Selectivity Fields Stored values Ranges
12 idx_1700732696947326976 persistent z_obs false false false 62.96 % [ `date_created`, `geoloc.lat` ] [ ] *
Optimization rules applied:
Id Rule Name Id Rule Name Id Rule Name
1 move-calculations-up 5 use-indexes 9 move-filters-into-enumerate
2 move-filters-up 6 use-index-for-sort 10 reduce-extraction-to-projection
3 move-calculations-up-2 7 remove-unnecessary-calculations-2 11 optimize-projections
4 move-filters-up-2 8 fuse-filters 12 remove-unnecessary-calculations-4
Optimization rules with highest execution times:
RuleName Duration [s]
use-indexes 0.00022
59 rule(s) executed, 1 plan(s) created, peak mem [b]: 0, exec time [s]: 0.00124Source: arangodb/arangodb