2

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"}
  },
]
NeNaD
  • 18,172
  • 8
  • 47
  • 89
nimrod serok
  • 14,151
  • 2
  • 11
  • 33

2 Answers2

2

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

NeNaD
  • 18,172
  • 8
  • 47
  • 89
1

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

ray
  • 11,310
  • 7
  • 18
  • 42