3

Given the following document structure:

{
  _id : Mongo ID,
  data : [someData1, someData2, ..., someDataN]
}

I want to get all documents which data size is between a and b (strict positive integers, consider a < b is always true).
I first thought about using $size, but the Mongo doc states:

$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.

(Emphasis mine)

How to retrieve all the documents with a data array of length between a and b without using a counter?


Related but did not solve:

  • This answer which suggests using a counter
  • This question which asks how to query an internal length and got many answers
  • This answer which suggests to use: { 'data.' + b : { $exists : true } } but I don't know how reliable it is and how it could apply to a range
  • This question about how to find documents with a minimal array length

1 Answer 1

5

You can use the $exists operator approach by including multiple terms in your query and building it up programmatically:

var startKey = 'data.' + (a-1);
var endKey = 'data.' + b;
var query = {};
query[startKey] = {$exists: true};
query[endKey] = {$exists: false};
db.test.find(query);

So for a=1 and b=3, for example, you end up with a query object that looks like:

{
    "data.0" : {
        "$exists" : true
    },
    "data.3" : {
        "$exists" : false
    }
}

The first part ensures there are at least a elements, and the second part ensures there are no more than b elements.

Sign up to request clarification or add additional context in comments.

1 Comment

I was afraid that, when doing something stupid such as data = []; data[0] = {}; data[10] = {}; (you never know) the final variable data could make us end up with different results between doing 'data.n' : { $exists : ... and a $size. After some tests, it occurred that the empty elements are filled by null values, so I can confirm the rightness of your answer and also, its awesomeness. Thanks for the clean solution!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.