0

My collection coll is

/* 1 */
{
    "_id" : ObjectId("566121aa4b88d840eb7d1c50"),
    "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"),
    "array" : [ 
        {
            "id" : 1
        }, 
        {
            "id" : 2
        }, 
        {
            "id" : 3
        }, 
        {
            "id" : 4
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5661224a4b88d840eb7d1c51"),
    "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"),
    "array" : [ 
        {
            "id" : 1
        }, 
        {
            "id" : 7
        }, 
        {
            "id" : 3
        }, 
        {
            "id" : 5
        }
    ]
}

what i need is to pull objects in array 'array' where batchCourseId = ObjectId("566122ab94b792fbdf81bcf3")

and 2<array.id<=5

expected output is

/* 1 */
    {
        "_id" : ObjectId("566121aa4b88d840eb7d1c50"),
        "array" : [             
            {
                "id" : 3
            }, 
            {
                "id" : 4
            }
        ]
    }

/* 2 */
{
    "_id" : ObjectId("5661224a4b88d840eb7d1c51"),
    "array" : [            
        {
            "id" : 3
        }, 
        {
            "id" : 5
        }
    ]
}

already tried

db.coll.find({"batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3")},
    { array: { $elemMatch: { id: { $gt: 2,$lte: 5} } } })

the output is like

/* 1 */
{
    "_id" : ObjectId("566121aa4b88d840eb7d1c50"),
    "array" : [ 
        {
            "id" : 3
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("5661224a4b88d840eb7d1c51"),
    "array" : [ 
        {
            "id" : 3
        }
    ]
}

close but only the first matching object in array is in result

FYI this only a sample set of data the original data is more complex and big in count

so pls let me know the best practice to do this, performance is also important

thanks in advance

1

2 Answers 2

2

You can use aggregation for achieving the same. A sample is shown below:

db.coll.aggregate(
  {$match: {"batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3")}},
  {$unwind: '$array'},
  {$match: {'array.id': { $gt: 2,$lte: 5}}},
  {$group: {_id: '$_id', array: {$push : '$array'}}}
)

Result:

{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "array" : [ { "id" : 3 }, { "id" : 5 } ] }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "array" : [ { "id" : 3 }, { "id" : 4 } ] }
Sign up to request clarification or add additional context in comments.

3 Comments

already tried aggregate works for this but as i said this is a sample set not working in the original set in that the array.id in int64/NumberLong() does that make any change the result is with all the array when did for the original data
worked for the original set with some small changes thanks Sarath Nair
@ArunRavindranath like what if I want to search for object which is in array with the help of its object id from search textfield? how will that work? Coz I have this issue going on with me. here is my question : stackoverflow.com/questions/69233084/…
2

In MongoDB aggregation $unwind creates Cartesian_product problem so in large data set is good way to avoid $unwind.

Let's check with your example if you use $unwind in aggregation then result looks like this

db.collectionName.aggregate([
    { "$match": { "batchCourseId": ObjectId("566122ab94b792fbdf81bcf3") }}, 
    { "$unwind": "$array" }
])

so result of above query is :

{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 1 } }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 2 } }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 3 } }
{ "_id" : ObjectId("566121aa4b88d840eb7d1c50"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 4 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 1 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 7 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 3 } }
{ "_id" : ObjectId("5661224a4b88d840eb7d1c51"), "batchCourseId" : ObjectId("566122ab94b792fbdf81bcf3"), "array" : { "id" : 5 } }

this create multiple documents and in large documents in collections it slow the performance and increase processing time.

Instead of $unwind use $map in aggregation with aggregation-set operator and the query is as below :

db.collection.aggregate([{
  "$match": {
    "batchCourseId": ObjectId("566122ab94b792fbdf81bcf3")
  }
}, {
  "$project": {
    "array": {
      "$setDifference": [{
          "$map": {
            "input": "$array",
            "as": "el",
            "in": {
              "$cond": {
                "if": {
                  "$and": [{
                    "$gt": ["$$el.id", 2]
                  }, {
                    "$lte": ["$$el.id", 5]
                  }]
                },
                "then": "$$el",
                "else": false
              }
            }
          }
        },
        [false]
      ]
    }
  }
}])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.