如何在MONGODB中进行SQL INTERSECT操作

时间:2014-07-28 20:57:15

标签: mongodb mongodb-query aggregation-framework

SELECT SOME_COLUMN 
FROM TABLE 
WHERE SOME_COLUMN_NAME = 'VALUE' 

INTERSECT 

SELECT SOME_COLUMN 
FROM TABLE 
WHERE SOME_COLUMN_NAME_VALUE = 'NEW_VALUE'

如何在MongoDB中获取2个查询(在SQL中使用INTERSECT运算符)的公共值或交集值?

INTERSECT是SQL的关键字,它是如何为MongoDB完成的?

2 个答案:

答案 0 :(得分:5)

与SQL中的许多内容一样,MongoDB中没有与SQL INTERSECT完全对应的内容,但根据实际问题,可能会有替代解决方案。

MongoDB没有影响多个集合的操作,因此无法在数据库上完全创建两个集合之间的交集。

当两个查询都来自同一个集合时,您可以使用聚合执行某些操作。你能做什么取决于你真正想做的事情。

答案 1 :(得分:1)

你的问题似乎与陈述" VALUE"和" NEWVALUE"在每个子查询部分中。 INTERSECT的要点是在列上匹配"相同"值。

但是只要您谈论相同的集合,那么您可以使用聚合框架获得这些列的交集:

db.collection.aggregate([

     // Get the "sets" for each field
     { "$group": {
         "_id": null,
         "field1": { "$addToSet": "$field1" },
         "field2": { "$addToSet": "$field2" }
     }},

     // Intersect the "sets"
         "same": { "$setIntersection": [ "$field1", "$field2" ] }
     }},

     // Unwind the result set
     { "$unwind": "$same" },

     // Just project the wanted field
     { "$project": { "_id": 0, "same": 1 } }
])

这确实利用了MongoDB 2.6中引入的$setIntersection运算符来返回" set"与两个"中的共同元素"被比较。 $addToSet操作构造了" unique"中的两个集合。每个领域的价值观。

如果您的可用MongoDB版本在2.6之前,您基本上可以做同样的事情,但只需要做一些工作:

db.collection.aggregate([
    // Group each "set"
    { "$group": {
        "_id": null,
        "field1": { "$addToSet": "$field1" },
        "field2": { "$addToSet": "$field2" }
    }},

    // Unwind each set
    { "$unwind": "$field1" },
    { "$unwind": "$field2" },

    // Group on the compared values
    { "$group": {
        "_id": null,
        "same": {
            "$addToSet": {
                "$cond": [
                    { "$eq": [ "$field1", "$field2" ] },
                    "$field1",
                    false
                ]
            }
        }
    }},

    // Unwind again, should be compacted now
    { "$unwind": "$same" },

    // Filter out the "false" values
    { "$match": { "same": { "$ne": false } } },

    // Just project the wanted field
    { "$project": { "_id": 0, "same": 1 } } 
])

在早期版本中缺少对"set operators"的支持,您只需通过比较两个"集"的值来模拟行为。这很大程度上就像你$unwind数组一样,生成的内容本质上是每个值的新文档。所以"放松"另一个数组会导致文档中的每个元素可以与另一个元素进行比较。

因此,对于单一集合形式,这是一个完全有效的操作,以便获得交叉点#34;与MongoDB中的所有内容一样,一般的配置是一次只使用一个集合。一般的责任在于您的设计以构建数据,以便在单个集合上进行比较。

使用incremental mapReduce进程可以在多个集合中获得类似的结果,但由于您的一般问题似乎是指单个表源,那么这实际上是与您似乎要求的那个问题不同的问题。当然,它不是单一操作,涉及多个处理步骤。

通常建议您仔细查看SQL to aggregation mapping上的手册部分。这提供了许多常见示例,并且随着时间的推移逐渐增加其他用例。