2

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
Community
  • 1
  • 1
Kyll
  • 7,036
  • 7
  • 41
  • 64

1 Answers1

4

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.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • 2
    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! – Kyll May 08 '15 at 15:39