当一些子文档数组记录在日期'X'之前时如何查找()文档

时间:2017-03-06 19:11:49

标签: mongodb

我再次遇到mongoDB查询。 它必须简单,但我找不到......

假设我有一个像这样的集合/文档:

{
  _id: ObjectId("588055a656f0dc1c9327eaf9"),
  type: "house",
  timeline: [
    {
      action: "abc",
      date: 2017-01-01,
    },
    {
      action: "xyz",
      date: 2016-12-12,
    }
   ]
}

我只想查询类型为house的文档以及之前的操作xyz - 让我们说 - 2015 ...怎么做?

显然,我知道如何通过type ...

进行查询
db.collection().find({ 'type': 'house' }).toArray()

我也知道如何使用dot.notation

进行查询
db.collection().find({ 'timeline.action': 'xyz' }).toArray()

但是如何构建一个前面有xyz行动的查询 - 让我们说 - 2015? 非常感谢你。

3 个答案:

答案 0 :(得分:1)

您可以使用$elemMatch运算符匹配嵌入字段。 (在评论中错过了那个操作员)

db.collection.find({'timeline': {$elemMatch:{action: 'xyz', 'date':{$lt: "2015-01-01"}}}})

更多https://docs.mongodb.com/manual/reference/operator/query/elemMatch/#array-of-embedded-documents

答案 1 :(得分:1)

使用$ match查找类型条件,使用$ redact获取匹配的'timeline'对象,

      db.collection.aggregate([{$match:{type:"house"}},{
        $redact: {
            "$cond": [{
                $and: [{
                    "$eq": [{
                            "$ifNull": ["$action", "xyz"]
                        },
                        "xyz"
                    ]
                }, {
                    "$lte": [{
                            "$ifNull": ["$date", ISODate("2015-01-01T00:00:02.015Z")]
                        },
                       ISODate("2015-01-01T00:00:02.015Z")
                    ]
                }]
            }, "$$DESCEND", "$$PRUNE"]
        }
    }]).pretty()

答案 2 :(得分:0)

由于mongo保存数据的方式,你必须小心这种匹配。

如果您查询

{
    action: 'xyz',
    date: {$lt: '2015-01-01'}
} 

但您的对象保存为

{
    date: {$lt: '2015-01-01'},
    action: 'xyz'
}

然后由于保存数据的底层结构,mongo将不匹配。

如果你需要匹配多个元素,建议使用$ elemMatch。

{timeline : {
    $elemMatch: {
        action: 'xyz', 
        date: {$lt: '2015-01-01'}
    }
}} 

因为它将匹配每个元素,而不是整个对象。

您的总查询应该类似于

{
    type: 'house'
    timeline : {
        $elemMatch: {
            action: 'xyz', 
            date: {$lt: '2015-01-01'}
        }
    }
}