Home > OS >  How to compare two objects in MongoDB (ignoring order of keys)?
How to compare two objects in MongoDB (ignoring order of keys)?

Time:12-31

What is the best way to find all the documents where objA is the same as objB (order of keys is not important)?

Inspired by another question by @Digvijay, I was looking for a way to compare two objects on MongoDB query and could not find a relevant solution on SO.

Sample data:

[
  {
    objA: {a: 1, b: 2},
    objB: {a: 1, b: 2}
  },
  {
    objA: {m: "g", c: 5},
    objB: {c: 5, m: "g"}
  },
  {
    objA: {m: "g", c: 7},
    objB: {c: 5, m: "g"}
  },
  {
    objA: {m: "g", c: 7},
    objB: {b: "g", c: 7}
  }
]

Expected results:

[
  {
    objA: {a: 1, b: 2},
    objB: {a: 1, b: 2}
  },
  {
    objA: {m: "g", c: 5},
    objB: {c: 5, m: "g"}
  },
]

CodePudding user response:

You can do it like this:

  • $objectToArray - to transform objA and objB to arrays.
  • $setEquals - to compare if above arrays have the same distinct elements.
db.collection.aggregate([
  {
    $match: {
      $expr: {
        $setEquals: [
          { $objectToArray: "$objA" },
          { $objectToArray: "$objB" }
        ]
      }
    }
  }
])

Working example

CodePudding user response:

Maybe use the old-school trick of converting them into an array by $objectToArray. Use $sortArray to sort by key. Compare by the sorted array to get the matches.

db.collection.aggregate([
  {
    $addFields: {
      "sortedA": {
        $sortArray: {
          input: {
            "$objectToArray": "$objA"
          },
          sortBy: {
            k: 1
          }
        }
      },
      "sortedB": {
        $sortArray: {
          input: {
            "$objectToArray": "$objB"
          },
          sortBy: {
            k: 1
          }
        }
      }
    }
  },
  {
    "$match": {
      $expr: {
        $eq: [
          "$sortedA",
          "$sortedB"
        ]
      }
    }
  },
  {
    "$unset": [
      "sortedA",
      "sortedB"
    ]
  }
])

Mongo Playground

  • Related