Mongodb$nin查询子文档

Mongodb $nin querying sub-document

这是我的示例文档 MongoDB:

user: {
         _id:1,
         name:'xyz',
         age:12,
         mobile:21321312,
         transaction:[
                         {
                             trans_id:1,
                             prod:'a',
                             purchasedAt:ISODate("2015-02-01"),
                         },
                         {
                             trans_id:2,
                             prod:'b',
                             purchasedAt:ISODate("2015-02-01")
                         },
                         {
                             trans_id:3,
                             prod:'c',
                             purchasedAt:ISODate("2014-11-24")
                         }
                     ]
     }

我想获取在日期“2015-02-01”购买了产品 'a' 但在同一天未购买产品 'b' 或 'c' 的用户。所以我尝试查询:

db.user.find({transaction:{$elemMatch:{prod:'a',purchasedAt:ISODate("2015-02-01")}}, transaction:{$elemMatch:{prod:{$nin:['b', 'c']}, purchasedAt:ISODate("2015-02-01")}}})

但是查询好像return错误的结果。它包含一些在同一天购买了产品 'c' 的用户。所以我尝试了:

db.user.find({transaction:{$elemMatch:{prod:{$in:['a'], $nin:['b','c']}, purchasedAt:ISODate("2015-02-01")}}})

db.user.find({$and:[{transaction:{$elemMatch:{prod:'a',purchasedAt:ISODate("2015-02-01")}}}, {transaction:{$elemMatch:{prod:{$nin:['b', 'c']}, purchasedAt:ISODate("2015-02-01")}}}]})

但 none 似乎有效。我总是得到具有相同购买日期的产品,即 $nin 部分。我也尝试过其他查询,但这些查询与上面的查询类型相同(例如使用点“.”运算符进行查询)并且在这里提及是微不足道的。有什么办法可以得到我想要的结果吗?

您可以通过以下两种方式找出结果

1> 使用 mongo 聚合

db.collectionName.aggregate({
    "$unwind": "$user.transaction"
}, {
    "$match": {
    "$and": [{
        "user.transaction.prod": "a"
    }, {
        "user.transaction.prod": {
            "$nin": ["b", "c"]
        }
    }, {
        "user.transaction.purchasedAt": ISODate("2015-02-01T00:00:00Z")
    }]
    }
}).pretty()

2> 将查找与投影结合使用

    db.collectionName.find({
    "user.transaction.prod": "a",
    "user.transaction.purchasedAt": ISODate("2015-02-01T00:00:00Z")
    },
    {
    "user.transaction.$": 1
    }).pretty()

试试这个:

db.test.find({
    "$and" : [
        { "transaction" : {
            "$elemMatch" : { "prod" : "a", "purchasedAt" : ISODate("2015-02-01") }
        } },
        { "transaction" : { "$not" : {
            "$elemMatch" : { "prod" : "b", "purchasedAt" : ISODate("2015-02-01") }
        } } },
        { "transaction" : { "$not" : {
            "$elemMatch" : { "prod" : "c", "purchasedAt" : ISODate("2015-02-01") }
        } } }
    ]
})