$search aggragation $elemMatches equivalent

In native queries it is possible to query a document based on the contents of an array field. Take a document that has a field like

{
  "_id": ...,
  "otherFields": ...,
  "positions": [
    {
      "x": 1,
      "y": 15
    },
    {
      "x": 3,
      "y": 15
    },
    {
      "x": 3,
      "y": 9
    }
  ]
}

In native queries you could do a $match like the following to retrieve all documents where an entry in positions has x of 3:

{
  $match: {
    positions: {
      $elemMatch: {"x": 3}
    }
  }
}

Is a similar per-array-element query possible with Atlas $search syntax?

If the positions sub-documents were in their own collection I know you could do a $search like

{
  $search: {
    range: {
      path: 'x',
      gte: 3,
      lte: 3
    }
  }
}

but this query doesn’t work on nested fields of an array (and I’m not here to ask about re-structuring the data). Also, due to the nature of $search I can’t first do an $unwind, and doing a $match after the $search would be a major hit to query speed.

So, the best option today is to have a new collection where you can $unwind the array that is used only for the search index.

In the near future, we will release support for elemMatch style queries. If you would like to be notified of the feature’s availability, please vote on the issue here. Even though it is on the way, the best way to model data for most search use cases is to flatten it. What do the coordinates in position represent? Are they ordered? Could the be broken into sub-documents of the top-level document? These are the sorts of questions I ask myself as well.

Hey nice to hear that an elemMatch equivalent is on the way.

The position documents here are just a simplified version of some data I need to access but don’t have control over the shape of. As for reshaping the data, I’m aware of many of the best practices for making this play nicer with queries but it’s unfortunately not something I have control over.

Sounds like for now my best option is to take the hit when necessary and do a $search and then a $match

1 Like

I’ll update this ticket once we release the equivalent of elemMatch

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.