嵌套数组上的N1QL独特查询

时间:2017-08-31 18:58:56

标签: couchbase n1ql

(Couchbase 4.5)假设我的couchbase实例中存储了以下对象:

{
  parentArray : [
    {
      childArray: [{value: 'v1'}, {value:'v2'}]
    }, 
    {
      childArray: [{value: 'v1'}, {value: 'v3'}]
    }
  ]
}

现在我想从childArray中选择不同的元素,它们应该返回一个等于['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秒的真实数据) )。当我删除不需要的东西,并简单地查询顶级元素(与parentArray相邻的元素)上的不同元素时,它需要毫秒级。

另一个解决方案是在应用程序代码中处理这个问题,只需迭代返回的值并找到不同的值my-self。这种方法很糟糕,因为它会给应用程序空间带来太多数据。

请帮忙!

谢谢!

更新:看起来没有使用“UNNEST”语句的“WHERE”子句,性能很快。那我在这里需要数组索引吗?

更新:没关系上一次更新,因为where子句中没有索引元素。此外,但我注意到,如果我删除UNNEST或WHERE,那么查询很快。此外,查看解释并为复合索引添加GSI(_class,dataType),我可以在提供的索引上看到“IndexScan”。

1 个答案:

答案 0 :(得分:3)

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;

OR

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;