To check size greater than. $size

Hi,
Normally the $size operator can be equated with, but if I want to check size > “”, how do I do that?

I tried,
db.movieDetails.find({"countries": {$gt: {$size: 2}}}).count()

but the answer always is zero, despite there being records fitting that criteria. So what are the changes I need to make to the above syntax?

Thanks.
Apurva

Ordering :slight_smile:

Are you looking for “greater than size 2”? Or “size, greater than 2”?

EDIT: BRB, testing this myself. Now I’m curious how to do this.

They’re both the same, right?
Meaning “countries” greater than size 2 or “countries with size greater than 2”

btw: I’ve also tried
db.movieDetails.find({“countries”: {$size: {$gt: 2}}}).count()

The official documentation contains an important explanation.

https://docs.mongodb.com/manual/reference/operator/query/size/

$size does not accept ranges of values. To select documents based on fields with different numbers of elements, create a counter field that you increment when you add elements to a field.

So yeah, it can’t be done unless you add extra programming… like using sizeof, or a counter record.

EDIT:
Another useful explanation and hint

-> https://stackoverflow.com/questions/41918605/mongodb-find-array-length-greater-than-specified-size

You can trick things out, by simply asking for item 3 in the array… if it doesn’t exist, then the length is $lte:2 :slight_smile:

1 Like

I suspected that. I had gone through the documentation, but missed that part.
Sorry for the trouble. It seems, options will have to be explored.

Thanks,
Apurva.

2 Likes

No worries! It’s a learning experience for us all :slight_smile:

A google search for this type of query uses the approach suggested above, testing for existence of array index. This is rather unorthodox and unintuitive.

Will mongodb change this approach? Just curious.

Hi @John_30772,

If you refer our documentation on the $size operator, you can find the recommended solution for achieving the same.

The $size operator does not accept ranges of values. To select documents based on fields with different numbers of elements, create a counter field that you increment when you add elements to a field.

Let’s say you already have a collection with array field in its documents. I am going to create a collection named col and insert some documents into it for demonstration purpose.

db.col.insertMany([{"arr":[1,2,3]},{"arr":[3,2,8,9]},{"arr":[1,2,3,4,4,56,9]}])

Now let’s create a field named ArrayLength to store the count of the elements in the arr field of the document.

Here we are using a JavaScript inline function to perform the count operation on each document.

 db.col.find().forEach(function(doc) { db.col.update({_id:doc._id},{$set:{ArrayLength:doc.arr.length}})})

As we can see in the output, the operation has been performed successfully. Let’s see what each of the document looks like.

Now each of the document contains a field called ArrayLength which stores the count of elements in the arr field. We can very easily issue query on this field and we can also create an index on this field.

Now what happens when you add or remove an element from the arr field. In such cases we will have to update the ArrayLength field as well depending on the type of operation (push or pop) and the number of elements that has been added or removed.

Let’s push 999 to the arr field in one document which has ArrayLength of 4.

db.col.updateOne({'ArrayLength':4},{$push:{arr:999},$inc:{ArrayLength:1}})

Let’s visualize the documents.

db.col.find()

If you still have any query feel free to get back to us. Happy Learning :slight_smile:

Thanks,
Shubham Ranjan
Curriculum Support Engineer

1 Like

Hi Shubham Ranjan,

I understand this approach, but again, it is unintuitive and cumbersome. Adding another counter field to maintain and relying on that field for the count introduces more risks to data error. Anyway, I believe the index check is more reliable than having to maintain an extra counter field.

Thank you for the reply and explanation.

Sincerely,
John

Hi @John_30772,

Here is another brilliant approach suggested by @nathan.leniz. In this approach, you don’t have to create any extra counter field.

db.col.find({"$expr":{$gte:[{$size:"$arr"},4]}})

Here, we are using $expr operator to filter out all those documents which has size greater than or equal to 4.

Yes, on the surface index check seems to be a better alternative, but it wouldn’t be practical to use this solution in the real-life applications, where you are issuing a lot of read queries. Since you cannot create indexes using this approach, your read operations will be slower. We use indexes to make our read query faster for performance gain.

As I can see, you are already registered for the next offering of the M201: MongoDB Performance course. In this course you will learn about all these concepts.

If you still have any other query, please feel free to get back to us.

Happy Learning John :slight_smile:

Thanks,
Shubham Ranjan
Curriculum Support Engineer