我有4个查询,从中获取相交的结果,并在下一行执行嵌套的FOR。有没有一种方法可以优化此查询?
Query string:
LET c0 = (FOR attr IN products_attributes
FILTER attr.key == "nt1" AND attr.value >= 0 AND attr.value <= 5
RETURN attr.productId)
LET c1 = (FOR attr IN products_attributes
FILTER attr.key == "st1" AND attr.value == "test str"
RETURN attr.productId)
LET c2 = (FOR attr IN products_attributes
FILTER attr.key == "mlt1" AND attr.value == "mo1"
RETURN attr.productId)
LET c3 = (FOR attr IN products_attributes
FILTER attr.key == "mlt1" AND attr.value == "mo2"
RETURN attr.productId)
LET collections = INTERSECTION(c0, c1, c2, c3)
FOR pid IN collections
FOR p IN products
FILTER p._key == pid AND "test" IN p.st AND "product" IN p.st
SORT p.date DESC
LIMIT 0, 10
RETURN p
Execution plan:
Id NodeType Est. Comment
1 SingletonNode 1 * ROOT
8 SubqueryNode 1 - LET c0 = ... /* const subquery */
2 SingletonNode 1 * ROOT
40 IndexNode 1 - FOR attr IN products_attributes /* persistent index scan */
6 CalculationNode 1 - LET #21 = attr.`productId` /* attribute expression */ /* collections used: attr : products_attributes */
7 ReturnNode 1 - RETURN #21
15 SubqueryNode 1 - LET c1 = ... /* const subquery */
9 SingletonNode 1 * ROOT
41 IndexNode 0 - FOR attr IN products_attributes /* persistent index scan */
13 CalculationNode 0 - LET #25 = attr.`productId` /* attribute expression */ /* collections used: attr : products_attributes */
14 ReturnNode 0 - RETURN #25
22 SubqueryNode 1 - LET c2 = ... /* const subquery */
16 SingletonNode 1 * ROOT
42 IndexNode 0 - FOR attr IN products_attributes /* persistent index scan */
20 CalculationNode 0 - LET #29 = attr.`productId` /* attribute expression */ /* collections used: attr : products_attributes */
21 ReturnNode 0 - RETURN #29
29 SubqueryNode 1 - LET c3 = ... /* const subquery */
23 SingletonNode 1 * ROOT
43 IndexNode 0 - FOR attr IN products_attributes /* persistent index scan */
27 CalculationNode 0 - LET #33 = attr.`productId` /* attribute expression */ /* collections used: attr : products_attributes */
28 ReturnNode 0 - RETURN #33
30 CalculationNode 1 - LET collections = INTERSECTION(c0, c1, c2, c3) /* simple expression */
39 IndexNode 1 - FOR p IN products /* persistent index scan */
35 CalculationNode 1 - LET #37 = p.`date` /* attribute expression */ /* collections used: p : products */
31 EnumerateListNode 100 - FOR pid IN collections /* list iteration */
44 CalculationNode 100 - LET #35 = (("product" in p.`st`) && (p.`_key` == pid)) /* simple expression */ /* collections used: p : products */
34 FilterNode 100 - FILTER #35
36 SortNode 100 - SORT #37 DESC
37 LimitNode 10 - LIMIT 0, 10
38 ReturnNode 10 - RETURN p
Indexes used:
By Type Collection Unique Sparse Selectivity Fields Ranges
40 persistent products_attributes true false n/a [ `key`, `value` ] ((attr.`key` == "nt1") && (attr.`value` >= 0) && (attr.`value` <= 5))
41 persistent products_attributes true false n/a [ `key`, `value` ] ((attr.`key` == "st1") && (attr.`value` == "test str"))
42 persistent products_attributes true false n/a [ `key`, `value` ] ((attr.`key` == "mlt1") && (attr.`value` == "mo1"))
43 persistent products_attributes true false n/a [ `key`, `value` ] ((attr.`key` == "mlt1") && (attr.`value` == "mo2"))
39 persistent products false false n/a [ `st[*]` ] ("test" in p.`st`)
Optimization rules applied:
Id RuleName
1 move-calculations-up
2 move-filters-up
3 interchange-adjacent-enumerations
4 move-calculations-up-2
5 move-filters-up-2
6 use-indexes
7 remove-filter-covered-by-index
8 remove-unnecessary-calculations-2
如果需要交集,则可以将子查询简单地合并为带有四个FILTER
子句的子查询,它们的作用类似于自然的AND
。
LET collections = (
FOR attr IN products_attributes
FILTER attr.key == "nt1" AND attr.value >= 0 AND attr.value <= 5
FILTER attr.key == "st1" AND attr.value == "test str"
FILTER attr.key == "mlt1" AND attr.value == "mo1"
FILTER attr.key == "mlt1" AND attr.value == "mo2"
RETURN attr.productId
)
您可能必须使用所有这些列来创建索引,但是应该可以。否则,您可以通过限制前一个数据集来减少后续数据集。如果搜索无法穿过集合或无法建立索引,这将特别有用:
LET c0 = (
FOR attr IN products_attributes
FILTER attr.key == "nt1" AND attr.value >= 0 AND attr.value <= 5
RETURN attr.productId
)
LET c1 = (
FOR attr IN products_attributes
FILTER attr.productId in c0
FILTER attr.key == "st1" AND attr.value == "test str"
RETURN attr.productId
)
LET c2 = (
FOR attr IN products_attributes
FILTER attr.productId in c1
FILTER attr.key == "mlt1" AND attr.value == "mo1"
RETURN attr.productId
)
LET c3 = (
FOR attr IN products_attributes
FILTER attr.productId in c3
FILTER attr.key == "mlt1" AND attr.value == "mo2"
RETURN attr.productId
)