Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use MongoDB aggregation for general purpose set operations (union, intersection, difference)

I have come across some special purpose implementation of set operations, but nothing for the general case. What is the general case for performing set operations (specifically intersection, union, symmetric difference). This is easier to figure out using javascript in a $where or map reduce, but I want to know how to do this in aggregation in order to get native performance.

The better way to illustrate this question is with an example. Say I have a record with 2 arrays/sets:

db.colors.insert({
    _id: 1,
    left : ['red', 'green'],
    right : ['green', 'blue']
});

I want to find the union, intersection and difference of the 'left' and 'right' arrays. Even better, pictorially I want to find:

Union --> ['red', 'green', 'blue']

union

Intersection --> ['green']

enter image description here

Symmetric Difference --> ['red', 'blue']

enter image description here

like image 318
Scott Avatar asked Jun 24 '13 05:06

Scott


1 Answers

Version 2.6+ Only:

As of version 2.6 of MongoDB, this has become much much easier. You can now do the following to solve this problem:

Union

db.colors.aggregate([
    {'$project': {  
                    union:{$setUnion:["$left","$right"]}
                 }
    }
]);

Intersection

db.colors.aggregate([
    {'$project': {  
                  int:{$setIntersection:["$left","$right"]}
                 }
    }
]);

Relative Complement

db.colors.aggregate([
    {'$project': {  
                    diff:{$setDifference:["$left","$right"]}
                 }
    }
]);

Symmetric Difference

db.colors.aggregate([
    {'$project': {  
                    diff:{$setUnion:[{$setDifference:["$left","$right"]}, {$setDifference:["$right","$left"]}]}
                 }
    }
]);

Note: There is a ticket requesting symmetric difference be added as a core feature rather than having to do the union of two set differences.

like image 132
Scott Avatar answered Sep 25 '22 02:09

Scott