mongodb query documents which have subset of all key value pairs mentioned in the query

Viewed 115

Let's assume we have the following documents in the Mongo db

[
  {
    "Name": "Jack",
    "info": {
      "eyes": "brown",
      "city": "paris",
      "accomodation": "house"
    }
  },
  {
    "Name": "Mathew",
    "info": {
      "eyes": "yellow",
      "city": "rome",
      "accomodation": "apartment"
    }
  },
  {
    "Name": "Peter",
    "info": {
      "eyes": "brown",
      "city": "barcelona",
      "accomodation": "house",
      "hair_color": "black"
    }
  }
]

Let's say the input JSON is

{
    "eyes": "brown",
    "city": "paris",
    "accomodation": "house",
    "hair_color": "black"
}

I would like to construct a query such that all the key-value pairs of the document should be present in the input json document but not necessarily the other way round. For the above example - the output should be

{
    "Name": "Jack",
    "info": {
      "eyes": "brown",
      "city": "paris",
      "accomodation": "house"
    }
  }

Since all the key value pairs of Jack were met by the input json document even though the input JSON document had hair_color which wasn't present in Jack document

Mongo playground with input : https://mongoplayground.net/p/1T0ZL8yGhPW

1 Answers

All you have to do is convert both your input and info field to an array using $objectToArray and check if their if there's any none matches, like so:

db.collection.aggregate([
  {
    $addFields: {
      rawInput: { // better if you do this in code once and drop this stage.
        "$objectToArray": {
          "eyes": "brown",
          "city": "paris",
          "accomodation": "house",
          "hair_color": "black"
        }
      }
    }
  },
  {
    $match: {
      $expr: {
        $eq: [
          {
            $size: {
              $filter: {
                input: {
                  "$objectToArray": "$info"
                },
                as: "elem",
                cond: {
                  $not: {
                    "$in": [
                      "$$elem",
                      "$rawInput"
                    ]
                  }
                }
              }
            }
          },
          0
        ]
      }
    }
  },
  {
    "$project": {
      Name: 1,
      info: 1
    }
  }
])

Mongo Playground

Related