skip to Main Content

I have Mongo DB collection which contains items like below:

{ 
    "_id" : ObjectId("123123123123123123"), 
    "title" : "Item-001", 
    "tags" : [
        "red"
    ], 
}
{ 
    "_id" : ObjectId("234234234234234"), 
    "title" : "Item-002", 
    "tags" : [
        "red,yellow"
    ], 
}

Objective:
I want to find items which has red tag. So for this example, I want to get both Item-001 and Item-002.

What I have tried
I have tried with the below query, but it returns just Item-001. My objective is to get Item-002 also as it contains red tag. How can I structure my query so that I can get both the documents?

db.getCollection("items").find({
    "tags": { '$in': [ 'red'] },
})

2

Answers


  1. First solution

    You can do it with find() query and $regex operator:

    db.collection.find({
     "tags": {
       "$regex": "red"
     }
    })
    

    Working example


    Second solution

    You can do it with Aggregation framework:

    • $match with $expr – to filter documents based on custom filter
    • $filter with $regexMatch – to filter tags array in each document and see if it has at least one item that contains "red".
    • $size – to get the size of the above filtered array.
    • $gt – to check if filtered array have at least one element.
    db.collection.aggregate([
      {
        "$match": {
          "$expr": {
            "$gt": [
              {
                "$size": {
                  "$filter": {
                    "input": "$tags",
                    "cond": {
                      "$regexMatch": {
                        "input": "$$this",
                        "regex": "red"
                      }
                    }
                  }
                }
              },
              0
            ]
          }
        }
      }
    ])
    

    Working example

    Login or Signup to reply.
  2. Your tags field is an array, but the items are joined by comma delimiter. This looks like a mistake. You should change it if possible.

    If not possible, here’s a solution by splitting the string to a list and then matching.

    db.collection.aggregate([
      {
        "$addFields": {
          "tagList": {
            $split: [
              {"$arrayElemAt": ["$tags", 0]}, ","
            ]
          }
        }
      },
      {
        $match: {
          "tagList": "red"
        }
      }
    ])
    

    Playground

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search