N1QL:从数组中查找最新状态

N1QL : Find latest status from an array

我有一个 'User' 类型的文档,如-

{
"id":"User-1",
"Name": "Kevin",
"Gender":"M",
"Statuses":[
   {
     "Status":"ONLINE",
     "StatusChangedDate":"2017-11-01T17:12:00Z"
   },
   {
     "Status":"OFFLINE",
     "StatusChangedDate":"2017-11-02T13:24:00Z"
   },
   {
     "Status":"ONLINE",
     "StatusChangedDate":"2017-11-02T14:35:00Z"
   },
   {
     "Status":"OFFLINE",
     "StatusChangedDate":"2017-11-02T15:47:00Z"
   }.....
],

"type":"User"
}

我需要用户的信息以及基于特定日期(或日期范围)的最新状态详细信息。 我可以使用子查询和 Unnest 子句来实现这一点。

Select U.Name, U.Gender, S.Status, S.StatusChangedDate
From (Select U1.id, max(U1.StatusChangedDate) as StatusChangedDate
      From UserInformation U1
      Unnest Statuses S1
      Where U1.type = 'User'
      And U1.StatusChangedDate between '2017-11-02T08:00:00Z' And '2017-11-02T11:00:00Z'
      And U1.Status = 'ONLINE'
      Group by U1.id 
      ) A
Join UserInformation U On Keys A.id
Unnest U.Statuses S
Where U.StatusChangedDate = A.StatusChangedDate;

但是有没有其他方法可以实现这一点(比如使用集合运算符和数组函数)?? 如果是,请向我提供查询或指导我完成它。 谢谢。

MAX, MIN 参数允许数组。数组的第 0 个元素可以是字段需要聚合,第 1 个元素是你想要携带的。 使用此技术,您可以为 MIN/MAX 投影非聚合字段,如下所示。

SELECT U.Name, U.Gender, S.Status, S.StatusChangedDate
FROM UserInformation U1
UNNEST Statuses S1
WHERE U1.type = 'User'
AND S1.StatusChangedDate BETWEEN '2017-11-02T08:00:00Z' AND '2017-11-02T11:00:00Z'
AND S1.Status = 'ONLINE'
GROUP BY U1.id
LETTING S = MAX([S1.StatusChangedDate,S1])[1];

在 4.6.3+ 中,您也可以在不使用 UNNEST Using subquery expressions https://developer.couchbase.com/documentation/server/current/n1ql/n1ql-language-reference/subqueries.html 的情况下尝试此操作。数组索引查询会更快

CREATE INDEX ix1 ON UserInformation(ARRAY v FOR v IN Statuses WHEN v.Status = 'ONLINE' END) WHERE type = "User";
SELECT U.Name, U.Gender, S.Status, S.StatusChangedDate
FROM UserInformation U1
LET S = (SELECT RAW MAX([S1.StatusChangedDate,S1])[1]
         FROM U1.Statuses AS S1
         WHERE S1.StatusChangedDate BETWEEN '2017-11-02T08:00:00Z' AND '2017-11-02T11:00:00Z' AND S1.Status = 'ONLINE')[0]
WHERE U1.type = 'User'
AND ANY v IN U1.Statuses SATISFIES
        v.StatusChangedDate BETWEEN '2017-11-02T08:00:00Z' AND '2017-11-02T11:00:00Z' AND v.Status = 'ONLINE' END;