0

I have a collection of books with documents laid out like

{
   "title": "The book",
   "author": "Joe Bob",
   "tags": ["dogs", "funny", "race"],
   "categories": ["fiction", "adventure"]
}

I would like to use one search bar to find a book by any of these criteria. I've got this down for the most part, but I don't understand now if it is a search or aggregation I should be using. I also wish I could have everything be case insensitive but I cannot figure out how to do something similar to $options: 'i' with an $in operator.

$or : [
    {'title': {$regex: search, $options: 'i'}},
    {'author': {$regex: search, $options: 'i'}},
    {'tags': {$in: [search]}},
    {'categories': {$in: [search]}},
]

Is this the best way for me to search through 100s of documents like this? Or should I prefer aggregate.

prasad_
  • 12,755
  • 2
  • 24
  • 36

1 Answers1

2

As you point out, you have this thing thing pretty much figured out, save for the case insensitivily for those arrays, which I will get to in a moment.

First off, I suggest that you follow this approach to searching all fields. However, if you want to stick to your method, which is also perfectly valid, here is how I would alter your query.

Since arrays are matched the same way strings are, you don't really need the $in operator there at all. So making those categories and tags searches case-insensitive is a trivial matter. Let's say we're looking for "Mark", so anything with "marketing" in the categories should get picked up. Here is how:

db.collection.find({
  $or: [
    {
      "title": {
        $regex: "Mark",
        $options: "i"
      }
    },
    {
      "author": {
        $regex: "Mark",
        $options: "i"
      }
    },
    {
      "tags": {
        $regex: "Mark",
        $options: "i"
      }
    },
    {
      "categories": {
        $regex: "Mark",
        $options: "i"
      }
    },
    
  ]
})

And here is a Playground example for you to test it.

codemonkey
  • 7,325
  • 5
  • 22
  • 36