如何在Mongodb中不存在或存在查询?

时间:2014-03-20 16:27:13

标签: sql mongodb mongodb-query aggregation-framework

我是MongoDb的新手,我正在尝试查看是否可以在Mongodb中执行exists()查询。

我玩的收藏品包含用户(包括公司和计费组等详细信息)和期望公司。

通常在Oracle中,用户和expectedCompanies将在两个表中,我会这样查询:

SELECT *
    FROM tableUsers
    WHERE exists (
        SELECT 1 
        FROM tableExpectedCompanies 
        WHERE 
            tableExpectedCompanies.companyname != tableUsers.companyName and 
            tableExpectedCompanies.billingGroup =  tableUsers.companyName.billingGroup
        )

在MongoDb中,它现在都在一个集合中,大致如下:

    {
          "_id" : "billingGroupX", 
          "expectedCompanies" : ["CompanyA", "company B", "supercompany X"],
          "users" : [{"name":..., "company": ...}, {}, {}]
}

我希望我能做到这样的事情:

db.MasterData.find(
    {'users.company': 
        {$nin: db.MasterData.find(
                {},
                {'expectedCompanies:1'})
        }
    })

但当然失败了,第一个错误是:

error: { "$err" : "$nin needs an array", "code" : 13277 }

MongoDb中是否存在实际存在或不存在的类似物?

修改:对我的问题做出初步的负面反馈。请注意,我很难找到存在/不存在/处于/不处于条件的情况,您可以使用子查询,因为它通常在SQL中完成。

2 个答案:

答案 0 :(得分:5)

好的,这是您需要了解的声明。

  

MongoDB不做联接

即使在此子查询表单中,您也不能在您的语句中包含来自其他集合的其他查询。也就是说,请注意以下几点:

  

错误:{“$ err”:“$ nin需要一个数组”,“代码”:13277}

所以你没有按要求提供数组,但你试图提出一个声明。然后你可以考虑代码:

var results = db.MasterData.find({}, {"expectedCompanies:1"}).toArray();

单独查看它会看到它将从所有结果中返回“expectedCompanies”字段。我在最后添加.toArray()功能,以表明您可能尝试做的事情无法正常工作,因为您将获得光标,不是一个数组。但是这在这里不起作用,因为数组甚至从这个语句引用整个集合,而不仅仅是来自一个文档。

因此,您可能正在“尝试”做的是将“users.company”值与“expectedCompanies”值匹配(或明确地 匹配)。所以在MongoDB中你可以这样做:

db.MasterData.aggregate([

    // Unwind the "users" array
    { "$unwind": "$users" },

    // Unwind the "expectedCompanies" array
    { "$unwind": "$expectedCompanies" },

    // Project a match condition
    { "$project": {
        "users": 1,
        "matching": { "$eq": [
           "$users.company",
           "$expectedCompanies"
        ]}         
    }},

    // Filter the results
    { "$match": { "matching": false }},

    // Group the duplicate entries from the unwind
    { "$group": {
        "_id": {
            "_id": "$_id",
            "users": {
               "name": "$users.name",
               "company": "$users.company"
            }
        }
    }},

    // Project a nicer document
    { "$project": {
        "_id": "$_id._id",
        "users": "$_id.users"
    }}
])

这使用aggregate$unwind数组中的元素,并将它们相互比较。每个阵列需要在不同的阶段“解开”。实际比较在第一个$project阶段完成,使用$eq逻辑运算符来比较这两个值。如果它们相等,则结果为true,而不是false

然后,我们使用$ match阶段将结果“过滤”为我们想要的false值。这就像普通的.find()查询一样。然后通过$group发送结果,将“用户”文档中的密钥汇集在一起​​。这是因为当阵列“未缠绕”时,每个条目被“复制”为另一个“expectedCompanies”数组中的每个元素。可以想象$unwind形式就像“去标准化”数据一样。分组在此处删除重复项。

最后,由于所有内容都在一个键下“分组”,然后再次使用$project将结果重新塑造成更符合您想要的内容。

因此,使用情况与“子查询”形式有点不同,但这就是你如何使用比较两个数组中的值的语句。你的文件。

答案 1 :(得分:-1)

以下是用于Exist()或IN()SQL函数转换的不同方法。 这是一个简单的javascript实用程序,但是为了提高性能,您将需要适当的索引。

var mycursor = db.tableUsers.find( {} ) 

mycursor.forEach( function (x){ 
    var o = db.tableExpectedCompanies.count( { billingGroup : x.billingGroup, companyname  : {$ne: x.companyName}   } )
    if ( o > 0) {
        //print('The _id exists! ' + x._id); //debugging only
        printjson(x) ; 
        }
} )