我什么时候应该在 N1ql 中使用 UNNEST 与 ANY...SATISFIES?
When should I use UNNEST vs ANY...SATISFIES in N1ql?
我想查询(或索引)数组值字段。
举个例子,假设我要检索此文档 { "myarray": [ 1, 2, 3]}
。
我可以用
ANY...SATISFIES
或 UNNEST
。从 documentation 来看,它们在功能上似乎是相同的。
SELECT * FROM `bucket` AND ANY v in myarray SATISFIES v=3 END;
SELECT * FROM `bucket` UNNEST myarray v WHERE v=3
每个的用例是什么?
对于这两个查询,它们做的事情相似,但是这两种方法都提供了其他功能。
这两个查询的实际结果应该不同。第一个查询将按原样 return 数组数据,而 UNNEST 将展平数组。
UNNEST 是文档内连接。 SATISFIES 允许您(正如您所做的那样)检查数组以查看它是否满足某些条件,但它实际上不会以任何方式转换结果中的数组。
更新:
不一定是'which is better'的问题。这两个查询做不同的事情。假设您的文档如下所示:
{
"foo": "bar",
"myarray": [
1,
2,
3
]
}
现在假设您从这两个查询中删除了 WHERE
。
然后,运行 这个查询:
SELECT d.foo, d.myarray, v
FROM `demo` d
UNNEST d.myarray v
您得到 3 个结果,因为正在进行联接。像这样:
[
{"foo":"bar","myarray":[1,2,3],"v":1},
{"foo":"bar","myarray":[1,2,3],"v":2},
{"foo":"bar","myarray":[1,2,3],"v":3}
]
与其他查询:
SELECT d.*
FROM `demo` d
你得到一个结果,因为没有发生连接。它是文档内谓词,但不是文档内连接。
[{"foo":"bar","myarray":[1,2,3]}]
至于用哪一个?一般来说,这取决于您的用例。 Stack Overflow 不是为了提供这种激光特定的建议。如果您只是追求速度,我建议您对您的真实数据进行测试,看看哪个更有效(您的示例文档可能不是您的真实文档)。
Indexing is also a factor。同样,仅基于您的示例文档,对于 SATISFIES 查询,您可能会创建如下索引:
CREATE INDEX adv_DISTINCT_myarray ON `demo`(DISTINCT `myarray`)
对于 UNNEST 查询,您可能会像这样创建一个索引:
CREATE INDEX adv_ALL_myarray ON `demo`(ALL `myarray`)
这些索引假定您所做的只是检查 myarray
中的单个值。如果您的实际查询更复杂,则需要更复杂的索引。
一个补充说明:在幕后,在查询引擎中,我不知道实现差异是什么,所以我不得不接受 Johan 关于 UNNEST 更昂贵的建议。但是您的里程可能会有所不同,所以我建议您尝试两者并做一些基准测试。
第一个是文档内谓词,查询结果是来自"bucket"的文档。第二个将 "bucket" 中的每个文档与 "myarray" 中的值进行连接,查询的每个结果都是 "bucket" 中文档的副本和 [=16] 中的一个值=].
一般来说,预计第二种选择要贵得多。
我想查询(或索引)数组值字段。
举个例子,假设我要检索此文档 { "myarray": [ 1, 2, 3]}
。
我可以用
ANY...SATISFIES
或 UNNEST
。从 documentation 来看,它们在功能上似乎是相同的。
SELECT * FROM `bucket` AND ANY v in myarray SATISFIES v=3 END;
SELECT * FROM `bucket` UNNEST myarray v WHERE v=3
每个的用例是什么?
对于这两个查询,它们做的事情相似,但是这两种方法都提供了其他功能。
这两个查询的实际结果应该不同。第一个查询将按原样 return 数组数据,而 UNNEST 将展平数组。
UNNEST 是文档内连接。 SATISFIES 允许您(正如您所做的那样)检查数组以查看它是否满足某些条件,但它实际上不会以任何方式转换结果中的数组。
更新:
不一定是'which is better'的问题。这两个查询做不同的事情。假设您的文档如下所示:
{
"foo": "bar",
"myarray": [
1,
2,
3
]
}
现在假设您从这两个查询中删除了 WHERE
。
然后,运行 这个查询:
SELECT d.foo, d.myarray, v
FROM `demo` d
UNNEST d.myarray v
您得到 3 个结果,因为正在进行联接。像这样:
[
{"foo":"bar","myarray":[1,2,3],"v":1},
{"foo":"bar","myarray":[1,2,3],"v":2},
{"foo":"bar","myarray":[1,2,3],"v":3}
]
与其他查询:
SELECT d.*
FROM `demo` d
你得到一个结果,因为没有发生连接。它是文档内谓词,但不是文档内连接。
[{"foo":"bar","myarray":[1,2,3]}]
至于用哪一个?一般来说,这取决于您的用例。 Stack Overflow 不是为了提供这种激光特定的建议。如果您只是追求速度,我建议您对您的真实数据进行测试,看看哪个更有效(您的示例文档可能不是您的真实文档)。
Indexing is also a factor。同样,仅基于您的示例文档,对于 SATISFIES 查询,您可能会创建如下索引:
CREATE INDEX adv_DISTINCT_myarray ON `demo`(DISTINCT `myarray`)
对于 UNNEST 查询,您可能会像这样创建一个索引:
CREATE INDEX adv_ALL_myarray ON `demo`(ALL `myarray`)
这些索引假定您所做的只是检查 myarray
中的单个值。如果您的实际查询更复杂,则需要更复杂的索引。
一个补充说明:在幕后,在查询引擎中,我不知道实现差异是什么,所以我不得不接受 Johan 关于 UNNEST 更昂贵的建议。但是您的里程可能会有所不同,所以我建议您尝试两者并做一些基准测试。
第一个是文档内谓词,查询结果是来自"bucket"的文档。第二个将 "bucket" 中的每个文档与 "myarray" 中的值进行连接,查询的每个结果都是 "bucket" 中文档的副本和 [=16] 中的一个值=].
一般来说,预计第二种选择要贵得多。