MongoDB query - Return sliced arrays MongoDB query - Return sliced arrays mongoose mongoose

MongoDB query - Return sliced arrays


The problem you are going to have with $slice here or any kind of projection with arrays is the fact that you are nesting arrays in the schema you have defined. I also notice the use of the positional $ operator sneaking in there for a peek, so it's probably best to explain in the context of the documentation from there.

So on that page there is this:

  • The $ projection operator limits the content of the field to the first element that matches the query document.
  • The field must appear in the query document

So for starters, you are not asking in the query to match a particular field in any element of any array. By that alone there will be no projection that can be done for a matched element. In any case only the first matching array element could possibly be matched even if you did so.

In your structure, the only thing you could match is the top position in the array "components". And right at the top.

The problem with $slice in this context is that you actually don't know "which" array element out of the nesting to operate on. So the style you have presented will not work because the elements could be and any possible index. The correct form, if it were supported, and which it is not would be something like:

{ "components.0.output_samples.0.values": { "$slice": 5 } }

As you would need to specify the index path down to the elements you are actually talking about.

So this does bring to question, "do you actually mean to have arrays"? Only saying this because as the information is presented, then it seems the only parts that are actually arrays are the "values" fields.

Nested lists are going to be a problem for various things and are notoriously bad for updating. Where possible you should consider alternatives. In this case if you want to limit your output, then the only practical way is to retrieve the whole document, then process the arrays in code to limit the returned results.

Even the following "very involved" incantation will only work ("somewhat") in it's present form considering that all the "other" array nesting only has one one element. So it makes this possible but impractical:

db.components.aggregate([   { "$unwind": "$components" },   { "$unwind": "$components.output_samples"},   { "$unwind": "$components.control_ports"},   { "$unwind": "$components.output_samples.values"},   { "$limit": 5 },   { "$group": {        "_id": {            "_id": "$_id",            "components": {               "uid": "$components.uid",               "type": "$components.type",               "_id": "$components._id",               "execution_times": "$components.execution_times",               "output_samples": {                   "name": "$components.output_samples.name",                   "_id": "$components.output_samples._id"               },               "input_samples": "$components.input_samples",               "control_ports": "$components.control_ports"           }       },        "output_samples_values": {"$push": "$components.output_samples.values" }   }},   { "$project": {        "_id": {            "_id": "$_id._id",            "components": {               "uid": "$_id.components.uid",               "type": "$_id.components.type",               "_id": "$_id.components._id",               "execution_times": "$_id.components.execution_times",               "output_samples": {                   "name": "$_id.components.output_samples.name",                   "_id": "$_id.components.output_samples._id",                   "values": "$output_samples_values"               },               "input_samples": "$_id.components.input_samples",               "control_ports": {                   "name": "$_id.components.control_ports.name",                   "_id": "$_id.components.control_ports._id"               }           }       },        "control_ports_values": "$_id.components.control_ports.values"   }},   { "$unwind": "$control_ports_values" },   { "$limit": 5 },   { "$group": {        "_id": {            "_id": "$_id._id",            "components": {               "uid": "$_id.components.uid",               "type": "$_id.components.type",               "_id": "$_id.components._id",               "execution_times": "$_id.components.execution_times",               "output_samples": {                   "name": "$_id.components.output_samples.name",                   "_id": "$_id.components.output_samples._id",                   "values": "$_id.components.output_samples.values"               },               "input_samples": "$_id.components.input_samples",               "control_ports": {                   "name": "$_id.components.control_ports.name",                   "_id": "$_id.components.control_ports._id"               }           }       },        "control_ports_values": {"$push": "$control_ports_values" }   }}])

And all of that just to slice two arrays by the first 5 values.

So if you need the nested arrays, then do the "slicing" in code when you retrieve the result. Otherwise change the schema to something that is going be more practically suit your purpose.