使用SQL筛选CosmoDB内部集合的JSON集合中的datetime值

时间:2019-02-19 01:40:12

标签: sql azure nosql azure-cosmosdb

使用Microsoft CosmoDBs SQL之类的语法。我有一个遵循这样的模式的条目集合(本文简化了)

{"id":"123456",
 "activities": {
       "activityA": {
                "loginType": "siteA",
                "lastLogin": "2018-02-06T19:42:22.205Z"
            },
       "activityB": {
                "loginType": "siteB",
                "lastLogin": "2018-03-07T11:39:50.346Z"
            },
       "activityC": {
                "loginType": "siteC",
                "lastLogin": "2018-04-08T15:21:15.312Z"
            }
        }
}

在不知道进入活动条目活动列表/子集合的确切索引的情况下,如何查询以取回Cosmo db集合中所有具有与日期范围匹配的“ lastLogin”的项目?

如果我只想搜索活动列表中的第一项,则可以使用索引0进行类似的操作。

SELECT * FROM c where (c.activities[0].lastLogin > '2018-01-01T00:00:00') and (c.activities[0].lastLogin <= '2019-02-15T00:00:00')

但是我想搜索列表中的所有条目。如果有这样的话会很好:

SELECT * FROM c where (c.activities[?].lastLogin > '2018-01-01T00:00:00') and (c.activities[?].lastLogin <= '2019-02-15T00:00:00')

但是那不存在。

1 个答案:

答案 0 :(得分:0)

答案是您不能遍历非列表集合。收集项目的结构是否如此

{"id":"123456",
 "activities": [
            {   "label": "activityA",
                "loginType": "siteA",
                "lastLogin": "2018-02-06T19:42:22.205Z"
            },
            {
                "label": "activtyB",
                "loginType": "siteB",
                "lastLogin": "2018-03-07T11:39:50.346Z"
            }, 
etc... 

创建这样的UDF来进行迭代很容易

UDF:filterActivityList

function(activityList,  targetDateTimeStart, targetDateTimeEnd) {
    var s, _i, _len;
    for (_i = 0, _len = activityList.length; _i < _len; _i++) {

        s = activityList[_i];

        if ((s.lastLogin >= targetDateTimeStart) && (s.lastLogin < targetDateTimeEnd)) 
        {

            return true;
       }

    }
    return false;
}

然后查询:

从c WHERE udf.filterActivityList(c.activities,'2018-01-01T00:00:00','2018-02-01T00:00:00')中选择*;

如果我将结构保留为JSON层次结构而不是将其转换为JSON列表,那么我将不得不编写另一个udf来接受层次结构的顶级节点作为输入参数,并将其转换为将其添加到列表中,然后将udf.filterActivityList UDF应用于结果。根据我的经验,这种方法会占用大量资源,并且Cosmo需要花费很长时间进行处理。