N1QL 对嵌套数组的不同查询
N1QL Distinct Query on Nested Arrays
(Couchbase 4.5) 假设我的 couchbase 实例中存储了以下对象:
{
parentArray : [
{
childArray: [{value: 'v1'}, {value:'v2'}]
},
{
childArray: [{value: 'v1'}, {value: 'v3'}]
}
]
}
现在我想 select 来自 childArray
的不同元素,它应该 return 一个等于 ['v1'、'v2'、'v3']。
对此我有几个解决方案。我的第一个想法是继续使用 UNNEST
操作:
SELECT DISTINCT ca.value FROM `my-bucket` AS b UNNEST b.parentArray AS pa UNNEST pa.childArray AS ca WHERE _class="someclass" AND dataType="someDataType";
通过这种方法,我得到了扫描元素数量的多项式爆炸(由于两个数组的未嵌套),并且查询需要一些时间才能完成(对于我的真实数据而言,顺序为24 秒)。当我删除 unnest 并简单地查询顶级元素(那些与 parentArray 相邻的元素)上的不同元素时,它需要毫秒的数量级。
另一种解决方案是在应用程序代码中处理此问题,方法是简单地遍历 returned 值并自行查找不同的值。这种方法不好,因为它给应用程序带来了太多数据 space.
请帮忙!
谢谢!
更新:看起来没有 "WHERE" 子句使用 "UNNEST" 语句性能很快。那么我这里需要数组索引吗?
UPDATE:不用管之前的更新,因为where 子句中没有索引元素。此外,但我确实注意到,如果我删除 UNNEST 或 WHERE,那么查询会很快。此外,查看解释并为复合索引 (_class, dataType) 添加 GSI 我可以在提供的索引上看到 "IndexScan"。
INSERT INTO default values("3",{ "parentArray" : [ { "childArray": [{"value": 'v1'}, {"value":'v2'}] }, { "childArray": [{"value": 'v1'}, {"value": 'v3'}] } ] });
SELECT ARRAY_DISTINCT(ARRAY v.`value` FOR v WITHIN parentArray END) FROM default;
或
SELECT ARRAY_DISTINCT(ARRAY_FLATTEN(
ARRAY ARRAY v.`value` FOR v IN ca.childArray END FOR ca IN parentArray END,
2)) FROM default;
您可以添加 where 子句。如果这需要跨文档使用以下内容。
INSERT INTO default values("4",{ "parentArray" : [ { "childArray": [{"value": 'v5'}, {"value":'v2'}] }, { "childArray": [{"value": 'v1'}, {"value": 'v3'}] } ] });
SELECT ARRAY_DISTINCT(ARRAY_FLATTEN(ARRAY_AGG(ARRAY v.`value` FOR v WITHIN parentArray END),2)) FROM default;
SELECT ARRAY_DISTINCT(ARRAY_FLATTEN(ARRAY_AGG(ARRAY_FLATTEN(ARRAY ARRAY v.`value` FOR v IN ca.childArray END FOR ca IN parentArray END,2)),2)) FROM default;
(Couchbase 4.5) 假设我的 couchbase 实例中存储了以下对象:
{
parentArray : [
{
childArray: [{value: 'v1'}, {value:'v2'}]
},
{
childArray: [{value: 'v1'}, {value: 'v3'}]
}
]
}
现在我想 select 来自 childArray
的不同元素,它应该 return 一个等于 ['v1'、'v2'、'v3']。
对此我有几个解决方案。我的第一个想法是继续使用 UNNEST
操作:
SELECT DISTINCT ca.value FROM `my-bucket` AS b UNNEST b.parentArray AS pa UNNEST pa.childArray AS ca WHERE _class="someclass" AND dataType="someDataType";
通过这种方法,我得到了扫描元素数量的多项式爆炸(由于两个数组的未嵌套),并且查询需要一些时间才能完成(对于我的真实数据而言,顺序为24 秒)。当我删除 unnest 并简单地查询顶级元素(那些与 parentArray 相邻的元素)上的不同元素时,它需要毫秒的数量级。
另一种解决方案是在应用程序代码中处理此问题,方法是简单地遍历 returned 值并自行查找不同的值。这种方法不好,因为它给应用程序带来了太多数据 space.
请帮忙!
谢谢!
更新:看起来没有 "WHERE" 子句使用 "UNNEST" 语句性能很快。那么我这里需要数组索引吗?
UPDATE:不用管之前的更新,因为where 子句中没有索引元素。此外,但我确实注意到,如果我删除 UNNEST 或 WHERE,那么查询会很快。此外,查看解释并为复合索引 (_class, dataType) 添加 GSI 我可以在提供的索引上看到 "IndexScan"。
INSERT INTO default values("3",{ "parentArray" : [ { "childArray": [{"value": 'v1'}, {"value":'v2'}] }, { "childArray": [{"value": 'v1'}, {"value": 'v3'}] } ] });
SELECT ARRAY_DISTINCT(ARRAY v.`value` FOR v WITHIN parentArray END) FROM default;
或
SELECT ARRAY_DISTINCT(ARRAY_FLATTEN(
ARRAY ARRAY v.`value` FOR v IN ca.childArray END FOR ca IN parentArray END,
2)) FROM default;
您可以添加 where 子句。如果这需要跨文档使用以下内容。
INSERT INTO default values("4",{ "parentArray" : [ { "childArray": [{"value": 'v5'}, {"value":'v2'}] }, { "childArray": [{"value": 'v1'}, {"value": 'v3'}] } ] });
SELECT ARRAY_DISTINCT(ARRAY_FLATTEN(ARRAY_AGG(ARRAY v.`value` FOR v WITHIN parentArray END),2)) FROM default;
SELECT ARRAY_DISTINCT(ARRAY_FLATTEN(ARRAY_AGG(ARRAY_FLATTEN(ARRAY ARRAY v.`value` FOR v IN ca.childArray END FOR ca IN parentArray END,2)),2)) FROM default;