Home > database >  Mongo return what inputs don't match for $IN
Mongo return what inputs don't match for $IN

Time:12-21

Is there any way for Mongo to return some indication (flag, field, etc..) for if an input in a $in does not match any docs?

Please see my Mongo Playgrond

That successfully just returns all odd documents.

How can I have some indication that the evens were not found?

I'd like to do this within Mongo itself. I get I can iterate through the results in JS and perform a diff.

Fwiw, I this $in will actually be the first stage of a $match in an aggregate . So maybe I can use something like addFields for the unmatches.

Thanks!

So my desired output could be that each negative match still gets a returning document..but with a new property found:false like the following. So..in my example, evens #s are not founds and it'd be cool to see something like..

 {
    "_id": ObjectId("5a934e000102030405100006"),
    "key": 2,
    "found": false
  },
 {
    "_id": ObjectId("5a934e000102230405000006"),
    "key": 4,
    "found": false
  },
 {
    "_id": ObjectId("5a934e000122030405000006"),
    "key": 6,
    "found": false
  }

Maybe, it'd be cleaner to put found as true for all positive matches as well.

Or...maybe return an subarray of the unmatches (that could be cleaner in post-processing)

CodePudding user response:

There is no straight way to do this in MongoDB, You can try aggregation query to handle custom requirements,

Here I have added an aggregation query to achieve your requirement, but I am not sure what is your exact data,

Input:

[
  { "key": 1 },
  { "key": 2 },
  { "key": 3 },
  { "key": 4 },
  { "key": 50 },
  { "key": 6 },
  { "key": 7 }
]
  • $match your $in condition
  • $facet to separate results and not found numbers
  • result key is to get your final document results
  • notFound is to find the not found keys
  • $group by null and get unique keys from result using $addToSet
  • $setDifference to get the difference of two arrays, first is your input and second available result numbers
  • $project to show required fields
db.collection.aggregate([
  {
    $match: {
      key: {
        $in: [1, 3, 5, 7]
      }
    }
  },
  {
    $facet: {
      result: [],
      notFound: [
        {
          $group: {
            _id: null,
            key: { $addToSet: "$key" }
          }
        },
        {
          $project: {
            key: {
              $setDifference: [[1, 3, 5, 7], "$key"]
            }
          }
        }
      ]
    }
  }
])

Playground

Result:

[
  {
    "notFound": [
      { "key": [5] }
    ],
    "result": [
      { "key": 1 },
      { "key": 3 },
      { "key": 7 }
    ]
  }
]

The second approach, as per your expected result sample,

  • $addFields to add new field found
  • $in to check key has value in the provided array, if yes then return true otherwise false
db.collection.aggregate([
  {
    $addFields: {
      found: {
        $in: ["$key", [1, 3, 5, 7]]
      }
    }
  }
])

Playground

Result:

[
  { "key": 1, "found": true },
  { "key": 2, "found": false },
  { "key": 3, "found": true },
  { "key": 4, "found": false },
  { "key": 50,"found": false },
  { "key": 6, "found": false },
  { "key": 7, "found": true }
]
  • Related