0

I have documents in a MongoDB collection that reference ObjectIds in a different collection. For example, my Orders collection has documents with a CustomerId.

Using MongoDB Atlas search, I've defined an index that allows me to search the CustomerId field with this syntax:

{
  "index": "Orders",
  "equals": {
    "path": "CustomerId"
    "value": new ObjectId("5m5....")
  }
}

(The above snippet is from the $search stage of my aggregation pipeline.)

But now I need to perform an OR search using multiple customer Ids. Unfortunately, I can't just specify an array of ObjectIds when using the equals operator. https://docs.atlas.mongodb.com/atlas-search/equals/

What are my options for searching a MongoDB Atlas Search index with multiple ObjectIds?

dthrasher
  • 40,656
  • 34
  • 113
  • 139

3 Answers3

2

You can use a compound query with a should clause and minimumShouldMatch set to 1 - https://docs.atlas.mongodb.com/atlas-search/compound/.

Petko M
  • 653
  • 2
  • 5
  • 18
  • I had the same idea! Using a `should` clause improves the scores of documents containing my target CustomerIds, but it doesn't prevent other documents from appearing within my results. Ideally, I'd want to do this within the `must` or `filter` clauses. – dthrasher Jan 04 '22 at 21:31
  • Does using "minimumShouldMatch" set to 1 help? (It's mentioned in the same help page) – Petko M Jan 05 '22 at 07:47
  • It does... as long as I never need to add a filter on a different field into the `should` array. It meets my current use case, though. – dthrasher Jan 05 '22 at 15:35
  • 1
    You can nest compound queries within a compound query. So you can have two compounds with shoulds inside a must, both of them with their own minimumShouldOccur. This would allow you to filter separately. – Petko M Jan 05 '22 at 18:28
  • Ah, I didn't know that compound queries could nest like that. In that case, this is definitely the best answer. Thanks! – dthrasher Jan 07 '22 at 20:07
0

One approach is to follow the $search stage with a $match stage. Then you can use the $in operator to search for multiple ObjectIds. Note that this approach has performance implications, as described here:

https://docs.atlas.mongodb.com/atlas-search/performance/#-match-aggregation-stage-usage

dthrasher
  • 40,656
  • 34
  • 113
  • 139
0

Here is the solution that worked for me using @Petko's suggestion

[{
"$search": {
  "index": "Orders",
  "compound": {
    "should": [
      {
        "equals": {
          "path": "CustomerId",
          "value": {"$oid": "62a..."}
        }
      },
      {
        "equals": {
          "path": "CustomerId",
          "value": {"$oid": "62a..."}
        }
      },
      {
        "equals": {
          "path": "CustomerId",
          "value": {"$oid": "62a..."}
        }
      }
    ],
    "minimumShouldMatch": 1
  }
}

} ]

Idan Petel
  • 184
  • 3
  • 7