我什么时候应该在N1ql中使用UNNEST与ANY ... SATISFIES?

时间:2019-04-24 14:57:29

标签: couchbase 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

每种情况都有哪些用例?

2 个答案:

答案 0 :(得分:2)

对于这两个查询,它们执行相似的操作,但是这两种方法都提供了其他功能。

这两个查询的实际结果应该不同。第一个查询将按原样返回数组数据,而UNNEST将平整数组。

UNNEST是文档内联接。 SATISFIES允许您(完成操作)检查数组以查看其是否符合某些条件,但实际上并不会以任何方式转换数组的结果。

更新

不一定是“哪个更好”的问题。这两个查询都做不同的事情。假设您的文档如下所示:

{
  "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]}]

要使用哪个?一般来说,这取决于您的用例。堆栈溢出不是用于提供此类特定于激光器的建议。如果您只是追求速度,我建议对您的真实数据进行测试,以查看哪种效率更高(您的样本文档可能不是您的真实文档)。

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的价格更高。但是您的里程可能会有所不同,所以我建议您同时尝试并做一些基准测试。

答案 1 :(得分:2)

第一个是内部文档谓词,查询结果是来自“存储桶”的文档。第二个查询将“ bucket”中的每个文档与“ myarray”中的值进行联接,并且查询的每个结果都是“ bucket”中的文档副本和“ myarray”中的一个值。

通常来说,期望第二种选择更加昂贵。