MongoDB一起使用NOT和AND

时间:2014-06-07 02:12:08

标签: mongodb mongoose

我正在尝试使用MongoDB否定$and子句,并且我收到了MongoError: invalid operator: $and消息。基本上我想要实现的目标如下:

query = { $not: { $and: [{institution_type:'A'}, {type:'C'}] } }

这可以在mongo查询中表达吗?

以下是一个示例集合:

{ "institution_type" : "A", "type" : "C" }
{ "institution_type" : "A", "type" : "D" }
{ "institution_type" : "B", "type" : "C" }
{ "institution_type" : "B", "type" : "D" }

我想要回复的内容如下:

{ "institution_type" : "A", "type" : "D" }
{ "institution_type" : "B", "type" : "C" }
{ "institution_type" : "B", "type" : "D" }

4 个答案:

答案 0 :(得分:18)

您正在寻找NOT (A AND C),相当于NOT A OR NOT C

db.collection.find({
  "$or": [
    {"institution_type": {"$ne": "A"}},
    {"type": {"$ne": "C"}}
  ]
})

MongoDB还有一个$nor逻辑运算符,它“对一个或多个查询表达式的数组执行逻辑NOR运算,并选择使数组中所有查询表达式失败的文档”,因此等效查询将是:

db.collection.find({
  "$nor": [
    {"institution_type": "A"},
    {"type": "C"}
  ]
})

接受的答案建议使用$where运算符,但这里不需要这样做,并且还有税收效果。

答案 1 :(得分:1)

我看不到标准否定,您需要使用JavaScript进行$where运算符样式的查询:

db.collection.find(function(){ 
    return !( this.institution_type == "A" && this.type == "C" ) 
})

不是最好的扫描整个集合,但逻辑上的否定需要这个,因为你需要测试这两个值。

或基本等效的聚合操作:

db.collection.aggregate([
    { "$project": {
        "institution_type": 1,
        "type": 1,
        "notmatched": {
            "$not": {
                "$and": [
                    { "eq": [ "$institution_type", "A" ] },
                    { "eq": [ "$type", "C" ] }
                ]
            }
        }
    }},
    { "$match": { 
        "notmatched": true
    }}
])

只是通过在内部包含否定来实现这也是一种有效的形式:

db.collection.find({
    "$or": [
        { "institution_type": { "$ne": "A" } }, 
        { "type": { "$ne": "C" }},
    ]
})

这基本上否定了" A"和" C"在同一文档中,就像其他逻辑与包装一样#34;不是"条件。


原稿

在MongoDB查询中,$and实际上是隐式的,因为这是查询中术语的默认比较。当您在同一领域寻找多个条件时,您只需要使用$and

但您的查询是一个简单的不等式匹配:

db.collection.find({
    "institution_type": { "$ne": "bank" },
    "type": { "$ne": "account_type" }
})

因此,您使用$ne运算符来否定匹配项中的条款,如前所述,$and是隐式的,因此必须同时适用这两个条件。

所以使用样本数据:

{ "institution_type" : "bank", "type" : "account_type" }
{ "institution_type" : "school", "type" : "account_type" }
{ "institution_type" : "school", "type" : "account" }

查询仅返回不符合这两个条件的行:

{ "institution_type" : "school", "type" : "account" }

你的评论说你想要"或"当您使用" AND"时未在查询中指定,所以也许您期望" OR"是隐含的,与我告诉你的情况相反。

需要明确应用$or条件:

db.collection.find({
    "$or": [
        { "inititution_type": { "$ne": "bank" } },
        { "type": { "$ne": "account_type" } }
    ]
})

这实际上是双重否定并将返回所有结果。

也许你的意思是$nor

db.data.find({
    "$nor": [
        { "inititution_type": "bank" },
        { "type": "account_type"  }
    ]
})

但实际上这与我给你的第一个查询在逻辑上相同。

答案 2 :(得分:0)

我有一个相同的问题,但没有解决。

我的收藏有以下内容(总计17 ):

{ 
    "_id" : ObjectId("5d9d09dff9399554b35f4fc8"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "createdAt" : ISODate("2019-10-08T22:12:47.872+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:12:47.872+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d09dff9399553df5f4fc9"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "createdAt" : ISODate("2019-10-08T22:12:47.883+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:13:10.129+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d0a00f93995da635f4fca"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "vacuo", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "createdAt" : ISODate("2019-10-08T22:13:20.310+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:13:20.310+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d0a44de4e534ba8a1eaf6"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "nao-sugerir", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d833a2a7aebc4af5ba378ca")
    }, 
    "createdAt" : ISODate("2019-10-08T22:14:28.445+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:14:28.445+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d0a48de4e534ba8a1eaf7"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "nao-sugerir", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82c2e07aebc4305da378b1")
    }, 
    "createdAt" : ISODate("2019-10-08T22:14:32.189+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:14:32.189+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d0b28de4e534ba8a1eaf8"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82de827aebc42767a378c6")
    }, 
    "createdAt" : ISODate("2019-10-08T22:18:16.235+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:18:16.235+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d0b28de4e534ba8a1eaf9"), 
    "status" : {
        "codigo" : "2", 
        "msg" : "Solicitação pendente"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82de827aebc42767a378c6")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "createdAt" : ISODate("2019-10-08T22:18:16.268+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:18:16.268+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d10eede4e534ba8a1eb0d"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82755c7aebc49efca378aa")
    }, 
    "createdAt" : ISODate("2019-10-08T22:42:54.790+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:42:54.790+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9d10eede4e534ba8a1eb0e"), 
    "status" : {
        "codigo" : "2", 
        "msg" : "Solicitação pendente"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82755c7aebc49efca378aa")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
    }, 
    "createdAt" : ISODate("2019-10-08T22:42:54.822+0000"), 
    "updatedAt" : ISODate("2019-10-08T22:42:54.822+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dad94f939952d305f4fcc"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82d8fa7aebc42be1a378c2")
    }, 
    "createdAt" : ISODate("2019-10-09T09:51:16.984+0000"), 
    "updatedAt" : ISODate("2019-10-09T09:51:16.984+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dad94f939957a905f4fcd"), 
    "status" : {
        "codigo" : "2", 
        "msg" : "Solicitação pendente"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82d8fa7aebc42be1a378c2")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "createdAt" : ISODate("2019-10-09T09:51:16.998+0000"), 
    "updatedAt" : ISODate("2019-10-09T09:51:16.998+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dad96f939956a345f4fce"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "vacuo", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d82d8fa7aebc42be1a378c2")
    }, 
    "createdAt" : ISODate("2019-10-09T09:51:18.587+0000"), 
    "updatedAt" : ISODate("2019-10-09T09:51:18.587+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dce0cf939958be25f4fcf"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d8354497aebc439a7a378d0")
    }, 
    "createdAt" : ISODate("2019-10-09T12:09:48.619+0000"), 
    "updatedAt" : ISODate("2019-10-09T12:09:48.619+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dce0cf939958c4b5f4fd0"), 
    "status" : {
        "codigo" : "2", 
        "msg" : "Solicitação pendente"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d8354497aebc439a7a378d0")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "createdAt" : ISODate("2019-10-09T12:09:48.635+0000"), 
    "updatedAt" : ISODate("2019-10-09T12:09:48.635+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dce10f9399590a65f4fd1"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d685f790215c983e4fd097e")
    }, 
    "createdAt" : ISODate("2019-10-09T12:09:52.994+0000"), 
    "updatedAt" : ISODate("2019-10-09T12:09:52.994+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9dce11f9399564715f4fd2"), 
    "status" : {
        "codigo" : "2", 
        "msg" : "Solicitação pendente"
    }, 
    "extra" : [

    ], 
    "tipo" : "amizade", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d685f790215c983e4fd097e")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "createdAt" : ISODate("2019-10-09T12:09:53.006+0000"), 
    "updatedAt" : ISODate("2019-10-09T12:09:53.006+0000"), 
    "__v" : NumberInt(0)
}
// ----------------------------------------------
{ 
    "_id" : ObjectId("5d9e4afbde4e534ba8a1eb0f"), 
    "status" : {
        "codigo" : "1", 
        "msg" : "Ativo"
    }, 
    "extra" : [

    ], 
    "tipo" : "nao-sugerir", 
    "vinculo" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d69a8eb0215c92942fd0983")
    }, 
    "vinculado" : {
        "colecao" : "atletas", 
        "objeto" : ObjectId("5d80f31e7aebc412dea3789a")
    }, 
    "createdAt" : ISODate("2019-10-09T21:02:51.026+0000"), 
    "updatedAt" : ISODate("2019-10-09T21:02:51.026+0000"), 
    "__v" : NumberInt(0)
}

在此查询中,返回正确的( 4 itens ):

db.getCollection("vinculos").aggregate(
    [
        { 
            "$match" : {
                "status.codigo" : "1", 
                "tipo" : {
                    "$in" : [
                        "amizade", 
                        "nao-sugerir"
                    ]
                }, 
                "vinculo.objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
            }
        }
    ]
)

但是我需要反过来:

第一次尝试(无结果)

db.getCollection("vinculos").aggregate(
    [
        { 
            "$match" : {
                "$nor" : [
                    {
                        "status.codigo" : "1"
                    }, 
                    {
                        "tipo" : {
                            "$in" : [
                                "amizade", 
                                "nao-sugerir"
                            ]
                        }
                    }, 
                    {
                        "vinculo.objeto" : ObjectId("5d6821c70215c9e5e5fd096b")
                    }
                ]
            }
        }
    ]
)

第二次尝试(无结果)

db.getCollection("vinculos").aggregate(
    [
        { 
            "$match" : {
                "$and" : [
                    {
                        "status.codigo" : {
                            "$ne" : "1"
                        }
                    }, 
                    {
                        "tipo" : {
                            "$nin" : [
                                "amizade", 
                                "nao-sugerir"
                            ]
                        }
                    }, 
                    {
                        "vinculo.objeto" : {
                            "$ne" : ObjectId("5d6821c70215c9e5e5fd096b")
                        }
                    }
                ]
            }
        }
    ]
)

我需要退回另外13个车票,有什么建议吗?

答案 3 :(得分:0)

TLDR;您想要一个与非门...

db.getCollection('test').find({ $or: [ {institution_type:{$ne:'A'}}, {type:{$ne:'C'}} ]})

...然后,谢谢(支持)this answer(不是我)

或NOR门...

db.getCollection('test').find({ $nor: [{institution_type:'A', type:'C'}] })

更长的版本...

我在MongoDB中找不到logical operator来处理$nand逻辑,因此我“构建”了该逻辑(见下文)。

$nand运算符有一个open feature request,但我不会屏住呼吸(创建于2014年)。

如果反转$nor逻辑,

$ne也可以做您想做的事情。

(但是IMO-感觉像我们是在反正行为-仅使用反$not的行为,而无视数组的$and行为...但是它起作用了,所以不是错误)。

db.getCollection('test').insertMany([
    { "institution_type" : "A", "type" : "C" },
    { "institution_type" : "A", "type" : "D" },
    { "institution_type" : "B", "type" : "C" },
    { "institution_type" : "B", "type" : "D" }
])

// "NAND gate": (NOT A) OR (NOT B) -> correct 3x results
db.getCollection('test').find({ $or: [ {institution_type:{$not:{$eq:'A'}}}, {type:{$not:{$eq:'C'}}} ]})

// or simpler...
db.getCollection('test').find({ $or: [ {institution_type:{$ne:'A'}}, {type:{$ne:'C'}} ]})

// or simpler still...

// "NOR gate": (NOT A) AND (NOT B) -> correct 3x results
db.getCollection('test').find({ $nor: [{institution_type:'A', type:'C'}] })