I have an order field in my document that contains reference IDs to documents in another collection.
product: {
_id: // product id,
orders: [refId_1415, refId_5414, refId_0210, refId_4320, refId_1543, refId_4326, refId_7845]
}
Since, they are not in ascending/descending order, I can't really run $gt or $lt to retrieve the values. So, I have to get all the refIds after a certain refId given by the user. Suppose, refId_5414 is given by the user. So, starting at index 2 (refId_0210) run a $lookup to return an array with the values populated like so:
order_history: [{
id: refId_0210,
created: // Date
},
{
id: refId_4320,
created: // Date
},
...
{
id: refId_7845,
created: // Date
}];
This is the query that I have come up with and it works, however there's a lot of stages to this and I was wondering if there is a better way to do this:
- Find the product with the id.
{
$match: { _id: product._id },
},
- Find the index of the id preceding the required starting index since that's what we'll receive.
{
$project: {
index: {
$indexOfArray: ["$orders", "refId_5414"],
},
orders: 1,
},
},
- Increase the index from the previous stage by 1 to get the required starting index.
{
$project: {
index: { $add: ["$index", 1] },
orders: 1,
},
},
- Slice the array from the starting index to the given index.
{
$project: {
orders: { $slice: ["$orders", "$index", to] },
_id: 0,
},
},
- Repopulate the array
{
$lookup: {
from: "orders",
let: { orders: "$orders" },
pipeline: [{ $match: { $expr: { $in: ["$_id", "$$orders"] } } }],
as: "order_history",
},
},
This is how it looks (Notice the 3 project stages):
const res = await this.collection.aggregate([
{
$match: { _id: product._id },
},
{
$project: {
...
},
},
{
$project: {
...
},
},
{
$project: {
...
},
},
{
$lookup: {
...
},
},
])
Any advice to make it better would be greatly appreciated. Thank you.