在mongodb中第二级放松后如何才能匹配?

时间:2018-05-15 19:17:58

标签: mongodb

我正在开发一个使用MongoDB作为数据库的软件。我有这样的集合(这只是一个文档)

{
    "_id" : ObjectId("5aef51e0af42ea1b70d0c4dc"),    
    "EndpointId" : "89799bcc-e86f-4c8a-b340-8b5ed53caf83",    
    "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
    "Url" : "test",
    "Tags" : [ 
        {
            "Uid" : "E2:02:00:18:DA:40",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-98")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-65")
                }
            ]
        }, 
        {
            "Uid" : "12:3B:6A:1A:B7:F9",
            "Type" : 1,
            "DateTime" : ISODate("2018-05-06T19:05:04.574Z"),
            "Sensors" : [ 
                {
                    "Type" : 1,
                    "Value" : NumberDecimal("-95")
                }, 
                {
                    "Type" : 2,
                    "Value" : NumberDecimal("-59")
                }, 
                {
                    "Type" : 3,
                    "Value" : NumberDecimal("12.939770381907275")
                }
            ]
        }
    ]
}    

我想对它运行此查询。

db.myCollection.aggregate([{ "$unwind" : "$Tags" },
{"$match" : { "$and" : [{ "Tags.DateTime" : { "$gte" : ISODate("2018-05-06T19:05:02Z"), "$lte" : ISODate("2018-05-06T19:05:09Z") } }, 
                { "Tags.Uid" : { "$in" : ["C1:3D:CA:D4:45:11"] } }] } },
{ "$unwind" : "$Tags.Sensors" }, { "$match" : { "$Tags.Sensors.Type" : { "$in" : [1,2] } } },
{ "$project" : { "_id" : 0, "EndpointId" : "$EndpointId", "TagId" : "$Tags.Uid", "Url" : "$Url", "TagType" : "$Tags.Type", 
    "Date" : "$Tags.DateTime", "SensorType" : "$Tags.Sensors.Type", "Value" : "$Tags.Sensors.Value" } }
])

问题是,第二次匹配(检查$Tags.Sensors.Type)不起作用,并且不会影响查询结果。 我怎么解决这个问题? 如果这不是正确的方法,那么运行这些条件的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

$match阶段接受没有前导$符号的字段名称。您已经在第一个$match阶段正确地完成了这项工作,但在您编写的第二个$Tags.Sensors.Type阶段。只需删除前导$符号即可使查询正常工作。

请注意,整个事情可以稍微简化一些(并且一些美化也不会受到伤害):

  1. 您不需要在示例中使用$and,因为如果您在过滤器中指定了多个条件,则默认情况下会假设{。p>

  2. 用于$in过滤器的Tags.Sensors.Type可以是一种简单的:等式运算符,除非您在可接受值列表中有多个元素。

  3. $project阶段,除了(种类)重复相同的字段名称外,您可以使用<field>: 1语法,除非字段的顺序很重要。

  4. 所以最后的查询会是这样的。

    db.myCollection.aggregate([
    {
        "$unwind" : "$Tags"
    },
    {
        "$match" : {
            "Tags.DateTime" : { "$gte" : ISODate("2018-05-06T19:05:02Z"), "$lte" : ISODate("2018-05-06T19:05:09Z") },
            "Tags.Uid" : { "$in" : ["C1:3D:CA:D4:45:11"] }
        }
    }, {
        "$unwind" : "$Tags.Sensors"
    }, { 
        "$match" : {
            "Tags.Sensors.Type" : { "$in" : [1,2] } 
        }
    },
    {
        "$project" : { 
            "_id" : 0,
            "EndpointId" : 1, 
            "TagId" : "$Tags.Uid",
            "Url" : 1,
            "TagType" : "$Tags.Type", 
            "Date" : "$Tags.DateTime", 
            "SensorType" : "$Tags.Sensors.Type", 
            "Value" : "$Tags.Sensors.Value" 
        }
    }])