Reputation: 1995
I have an aggregate query that returns an array of objects. I am trying to slice it by adding this stage at the end of the pipeline:
let limit = 5;
let skip = limit * 1;
const page_limit_stage = {
$project: {
profiles: {
$slice: ["$$CURRENT", skip, limit],
},
},
};
But, I keep getting this error:
🚀 ~ file: profile.js ~ line 331 ~ err MongoError: First argument to $slice must be an array, but is of type: object
Any idea how to solve this?
EDIT 2: Here's the query I am using:
const filterProfiles = async function filterProfiles() {
const { users_filter_option, profiles_filter_option } =
prepareProfilesFilterSearchOptions();
const profile_stage = {
$lookup: {
from: "profiles",
let: { profile_id: "$profile" },
pipeline: [profiles_filter_option],
as: "profile",
},
};
const profile_populate_options = [
{
$lookup: {
from: "schema_name_1",
localField: "profile.schema_name_1",
foreignField: "_id",
as: "schema_name_1",
},
},
{
$lookup: {
from: "schema_name_2",
localField: "profile.schema_name_2",
foreignField: "_id",
as: "schema_name_2",
},
},
];
const project_stage = {
$project: {
user_id: "$_id",
name: "$name",
surname: "$surname",
country: "$country",
schema_name_2: { $arrayElemAt: ["$schema_name_2", 0] },
schema_name_1: "$schema_name_1",
},
};
let limit = 5;
let skip = limit * 1;
const page_limit_stage = {
$project: {
profiles: {
$slice: ["$CURRENT", skip, limit],
},
},
};
const pipeline = [
users_filter_option,
profile_stage,
...profile_populate_options,
{ $unwind: "$profile" },
project_stage,
page_limit_stage,
];
const users = await User.aggregate(pipeline);
return users;
};
And this is the result without the page_limit_stage
:
[
{
_id: "aegaeg",
user_id: "aegaef",
name: "user_name",
surname: "user_surname",
country: "country_name",
schema_name_1: "value",
schema_name_2: "value2",
},
// multiple documents like this
];
Upvotes: 1
Views: 1322
Reputation: 36104
The slice will work on array of object property if you have in your document, but in your case you need to do pagination, There are 2 stages for pagination $skip and $limit,
let limit = 5;
let skip = limit * 1;
const skip_stage = { $skip: skip };
const limit_stage = { $limit: limit };
const pipeline = [
users_filter_option,
profile_stage,
...profile_populate_options,
{ $unwind: "$profile" },
project_stage,
skip_stage,
limit_stage
];
Upvotes: 1
Reputation: 8695
"$$CURRENT"
is a system variable, and it has here the same value as $$ROOT
system variable see here
They both have as value the document that enters the pipeline. If collection is like
[{_id : 1 name : "john" addresses [..]} ...]
The $$CURRENT
will be = {_id : 1 name : "john" addresses [..]}
its a document not array, cannot be sliced.(it has the value of the document that come from the pipeline,the above is the first value it will get)
I think you just want the bellow (instead of $addresses
put the name of your array)
{
$project: {
profiles: {
$slice: ["$addresses", skip, limit],
},
},
};
In case you want to slice the $$ROOT
document, you should first do
$ObjectToArray
and after $slice
but i dont think you want this.
Upvotes: 1