在mongodb中结合两个时间范围

时间:2015-06-27 03:09:20

标签: mongodb

mongodb中的时间序列数据如下:

{ "_id" : ObjectId("558912b845cea070a982d894"), "code" : "ZL0KOP", "time" : NumberLong("1420128024000"),"direction" : "10", "siteId" : "0000"}
{ "_id" : ObjectId("558912b845cea070a982d895"), "code" : "AQ0ZSQ", "time" : NumberLong("1420128025000"),"direction" : "10", "siteId" : "0000"}
{ "_id" : ObjectId("558912b845cea070a982d896"), "code" : "AQ0ZSQ", "time" : NumberLong("1420128003000"),"direction" : "10", "siteId" : "0000"}
{ "_id" : ObjectId("558912b845cea070a982d897"), "code" : "ZL0KOP", "time" : NumberLong("1420041724000"),"direction" : "10", "siteId" : "0000"}
{ "_id" : ObjectId("558912b845cea070a982d89e"), "code" : "YBUHCW", "time" : NumberLong("1420041732000"),"direction" : "10", "siteId" : "0002"}
{ "_id" : ObjectId("558912b845cea070a982d8a1"), "code" : "U48AIW", "time" : NumberLong("1420041729000"),"direction" : "10", "siteId" : "0002"}
{ "_id" : ObjectId("558912b845cea070a982d8a0"), "code" : "OJ3A06", "time" : NumberLong("1420300927000"),"direction" : "10", "siteId" : "0000"}
{ "_id" : ObjectId("558912b845cea070a982d89d"), "code" : "AQ0ZSQ", "time" : NumberLong("1420300885000"),"direction" : "10", "siteId" : "0003"}
{ "_id" : ObjectId("558912b845cea070a982d8a2"), "code" : "ZLV05H", "time" : NumberLong("1420300922000"),"direction" : "10", "siteId" : "0001"}
{ "_id" : ObjectId("558912b845cea070a982d8a3"), "code" : "AQ0ZSQ", "time" : NumberLong("1420300928000"),"direction" : "10", "siteId" : "0000"}

需要过滤掉符合两个或多个条件的代码。 例如:

condition1: 1420128000000 < time < 1420128030000,siteId == 0000
condition2: 1420300880000 < time < 1420300890000,siteId == 0003

唯一符合上述所有条件的代码应为:

{&#34;代码&#34; :&#34; AQ0ZSQ&#34;}

我使用以下查询:

db.codes.find({$and:[{'time': {'$gt': 1420128000000,'$lt': 1420128030000}, 'siteId': "0000"},{'time': {'$gt': 1420300880000,'$lt': 1420300890000}},{'siteId':'0003'}]})

未找到任何结果,解释显示:

 "parsedQuery" : {
                    "$and" : [
                            {
                                    "time" : {
                                            "$lt" : 1421856012000
                                    }
                            },
                            {
                                    "time" : {
                                            "$lt" : 1420560012000
                                    }
                            },
                            {
                                    "siteId" : {
                                            "$eq" : "0000"
                                    }
                            },
                            {
                                    "siteId" : {
                                            "$eq" : "0000"
                                    }
                            },
                            {
                                    "time" : {
                                            "$gt" : 1421722392000
                                    }
                            },
                            {
                                    "time" : {
                                            "$gt" : 1420426392000
                                    }
                            }
                    ]
            },

这显然不正确。 那么我怎样才能找到正确的结果?

1 个答案:

答案 0 :(得分:0)

你的意思是$or而不是$and。 &#34; AND&#34;是不可能的,因为没有记录同时具有&#34; 0000&#34;和&#34; 0003&#34;对于siteId。所以你的意思是&#34;要么&#34;这意味着&#34; OR&#34;:

db.codes.find({
    "$or": [
        { 
            "time": { "$gt": 1420128000000, "$lt": 1420128030000 },
            "siteId": "0000"
        },
        {
            "time": { "$gt": 1420300880000, "$lt": 1420300890000 },
            "siteId": "0003"
        }
    ]
})

使用您期望的密钥为您提供结果:

{ 
    "_id" : ObjectId("558912b845cea070a982d895"),
    "code" : "AQ0ZSQ",
    "time" : NumberLong("1420128025000"), 
    "direction" : "10", 
    "siteId" : "0000"
},
{ 
    "_id" : ObjectId("558912b845cea070a982d896"), 
    "code" : "AQ0ZSQ", 
    "time" : NumberLong("1420128003000"), 
    "direction" : "10",
    "siteId" : "0000" 
},
{ 
    "_id" : ObjectId("558912b845cea070a982d89d"),
    "code" : "AQ0ZSQ",
    "time" : NumberLong("1420300885000"), 
    "direction" : "10",
    "siteId" : "0003"
 }
简而言之

简化逻辑

由于这里的条款似乎存在误解,我将尽可能简单地解释一下。让我们考虑一下这些基本文件:

{ "a": 1, "b": true },
{ "a": 2, "b": false },
{ "a": 3, "b": true },
{ "a": 4, "b": false },
{ "a": 5, "b": true },
{ "a": 6, "b": true }

现在,当第一次聚焦于单个范围匹配时,以下将产生结果:

db.collection.find({ "a": { "$gt": 1, "$lt": 6 } })

由于这里的六个文件中有四个将包含&#34; a&#34;落在指定范围之间。

现在你也可以使用&#34;两个&#34;此范围在$and条件范围内,如下所示:

db.collection.find({
    "$and": [
        { "a": { "$gt": 1, "$lt": 6 } },
        { "a": { "$gt": 2, "$lt": 5 } }
    ]
})

现在再次使用&#34; a&#34;对于3和4将匹配&#34;两者&#34;当然条件是丢弃2和5的值,因为没有满足第二个条件。

这里的还原点表达式实际上可以简化为只有&#34;更大&#34;的范围。最小值和&#34;较小的&#34;最大值:

db.collection.find({ "a": { "$gt": 2, "$lt": 5 } })

与上述结果相同。

而不是&#34;包含&#34;逻辑同样适用于&#34;十字路口&#34;条件,所以如下:

db.collection.find({
    "$and": [
        { "a": { "$gt": 1, "$lt": 4 } },
        { "a": { "$gt": 2, "$lt": 6 } }
    ]
})

然后通过相同的&#34;最小值&#34;减少到这个基本陈述。和&#34;最大&#34;规则:

db.collection.find({ "a": { "$gt": 2, "$lt": 4 } })

两者都只返回基本缩减所涵盖的文档3。

但是,如果范围中无重叠,则无法匹配:

db.collection.find({
    "$and": [
        { "a": { "$gt": 1, "$lt": 3 } },
        { "a": { "$gt": 2, "$lt": 6 } }
    ]
})

没有文件符合这些条件,因为3,4,5符合第二个声明,但所有3,4,5都被第一个声明排除在外。再次,这只是&#34;减少&#34;到此为止:

db.collection.find({ "a": { "$gt": 2, "$lt": 3 } })

此集合中2到3之间的数字明显不匹配。

现在看第二个&#34; b&#34;只有财产,你可以这样做:

db.collection.find({ "b": true })

仅按预期返回true的结果。但如果你试过这个:

db.collection.find({
   "$and": [
       { "b": true },
       { "b": false } 
   ]
})

然后就是&#34;不匹配&#34;因为没有单个文档同时包含true false用于&#34; b&#34; 同时。只有$or条件才能匹配文档测试&#34;或者#34;这些价值观:

db.collection.find({
   "$or": [
       { "b": true },
       { "b": false } 
   ]
})

当然,样本中的所有文档都没有包含&#34; b&#34;的其他可能值。在条件中没有提到。

较短的运算符是$in运算符,可以测试&#34;或&#34;在没有完全声明它的同一领域,如:

db.collection.find({ "b": { "$in": [true,false] } })

现在,如果你&#34;结合&#34;原则,$and的第二次尝试如何与范围组合不起作用应该是明确的:

db.collection.find({
    "$and": [
        { "a": { "$gt": 1, "$lt": 4 }, "b": true },
        { "a": { "$gt": 2, "$lt": 6 }, "b": false }
    ]
})

所以虽然&#34;范围&#34;为&#34; a&#34;提供满意的文件等于3该文件没有&#34;两者&#34; truefalse值。它只是&#34;只有&#34;值为true,因此没有符合条件且没有文档匹配。

为了使文档与&#34; a&#34;匹配。 3然后逻辑将被写入&#34; redcued&#34;形式如此:

db.collection.find({
    "a": { "$gt": 2, "$lt": 4 },
    "b": { "$in": [true,false] }
})

在那种情况下,然后记录&#34; a&#34;等于3是匹配,因为找到了减少的范围以及&#34; b&#34; beign等于true/false的其中一个值。

当然最后要考虑&#34; b&#34;作为&#34;或&#34;你会做的条件:

db.collection.find({
    "$or": [
        { "a": { "$gt": 2, "$lt": 4 } },
        { "b": { "$in": [true,false] } }
    ]
})

当然匹配&#34;一切&#34;在样本中作为第一个&#34;范围&#34;匹配的文件&#34; a&#34;等于3但所有文件包含&#34; b&#34;的值这是true/false

这就是这一切的结果。如前所述,有一个基本的还原规则可以应用于一个范围,对于一个&#34;奇异的&#34;它只是不可能。值一次具有多个值。

这是基本逻辑,而不是理论物理,所以Schrödinger's cat不适用于此:)