Skip to content

Instantly share code, notes, and snippets.

@sindbach
Last active June 19, 2020 23:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sindbach/6c9c1c3db42cfe5eb2b36196e002a0a6 to your computer and use it in GitHub Desktop.
Save sindbach/6c9c1c3db42cfe5eb2b36196e002a0a6 to your computer and use it in GitHub Desktop.
Compare two object documents in MongoDB 4.4 with $function aggregation pipeline
/*
Outputs:
{
"_id": ObjectId("5eec4fd0aee4bf9d2e209e2d"),
"diff": {
"haveMore": {
"foo2": null
},
"types": {
"differentType": NumberLong("55"),
"objectIdDiff": ObjectId("5eec5020aee4bf9d2e209e2e"),
"stringDiff": "different",
"longDiff": NumberLong("99"),
"decimalDiff": NumberDecimal("11"),
"dateDiff": ISODate("2020-06-19T05:44:39.542Z")
},
"arrayDiff": [
"x"
],
"arrayDiffLength": [
undefined,
"b",
"c"
],
"arrayObjects": [
undefined,
{
"xoo": null
}
],
"missingField": null
}
}
*/
db.a.aggregate([
{"$project":{
"diff":{
"$function":{
"body": function(objectA, objectB) {
var diff = function (obj1, obj2) {
let type1 = Object.prototype.toString.call(obj1);
let type2 = Object.prototype.toString.call(obj2);
if (type2 === '[object Undefined]') {
return obj1;
}
if (type1 !== type2) {
return obj1;
}
if (type1 === '[object ObjectId]' || type1 === '[object NumberDecimal]') {
if (obj1.toString() !== obj2.toString()) {
return obj2;
}
}
if (type1 === "[object Date]" || type1 === "[object NumberLong]"){
if (obj1.valueOf() !== obj2.valueOf()) {
return obj2;
}
}
if (type1 === "[object String]") {
if (obj1 !== obj2) {
return obj2;
}
}
if (type1 === '[object BSON]') {
let result = {}
for (let key in obj1) {
if (obj2.hasOwnProperty(key)) {
let tmp = diff(obj1[key], obj2[key]);
if (tmp !== undefined){
result[key] = tmp;
}
} else {
result[key] = null;
}
}
if (Object.keys(result).length > 0){
return result;
} else {
return undefined;
}
}
if (type1 === '[object Array]') {
let result = [];
for (let i = 0; i < obj1.length; i++) {
let tmp = diff(obj1[i], obj2[i]);
if (tmp !== undefined){
result[i] = tmp;
}
}
if(result.length > 0){
return result;
} else {
return undefined;
}
}
return undefined;
};
return diff(objectA, objectB);
},
"args":[ {"$arrayElemAt": ["$docs", 0]}, {"$arrayElemAt":["$docs", 1]}],
"lang":"js"}
}
}}
]).pretty()
{
_id: ObjectId("5eec4fd0aee4bf9d2e209e2d"),
"docs": [
{
"haveMore": {
"foo1": "x1",
"foo2": "x2"
},
"haveLess": {
"bar1": "x1"
},
"types": {
"differentType": NumberLong("55"),
"objectIdEqual": ObjectId("5eec4f0aaee4bf9d2e209e2b"),
"objectIdDiff": ObjectId("5eec4f0aaee4bf9d2e209e2c"),
"stringEqual": "equal",
"stringDiff": "equal",
"longEqual": NumberLong("11"),
"longDiff": NumberLong("11"),
"decimalEqual": NumberDecimal("99"),
"decimalDiff": NumberDecimal("99"),
"dateEqual": ISODate("2020-06-19T05:36:21.995Z"),
"dateDiff": ISODate("2020-06-19T05:36:22.995Z"),
},
"arrayEqual": ["a", "b"],
"arrayDiffLength": ["a", "b", "c"],
"arrayObjects": [
{"foo":{"bar": "baz"}},
{"xoo":{"xar": "xaz"}}
],
"missingField": "x"
},
{
"haveMore": {
"foo1": "x1",
},
"haveLess": {
"bar1": "x1",
"bar2": "x2"
},
"types": {
"differentType": "55",
"objectIdEqual": ObjectId("5eec4f0aaee4bf9d2e209e2b"),
"objectIdDiff": ObjectId("5eec5020aee4bf9d2e209e2e"),
"stringEqual": "equal",
"stringDiff": "different",
"longEqual": NumberLong("11"),
"longDiff": NumberLong("99"),
"decimalEqual": NumberDecimal("99"),
"decimalDiff": NumberDecimal("11"),
"dateEqual": ISODate("2020-06-19T05:36:21.995Z"),
"dateDiff": ISODate("2020-06-19T05:44:39.542Z"),
},
"arrayEqual": ["a", "b"],
"arrayDiffLength": ["a"],
"arrayObjects": [
{"foo":{"bar": "baz"}},
{"yoo":{"yar": "yaz"}}
],
},
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment