I have 2 schemas, schema A and B like the following:
const A = new Schema({
paymentId: Number,
date: Date,
...data
})
const B = new Schema({
paidId: Number,
date: Date,
...data
})
I want to return records from both A and B like it is a single table, where I can get records from both A and B that can be used with .sort()
, .skip()
, and .limit()
functions ideally.
I could just do a .find()
on both tables, concatenate them, and manually sort / skip / limit, but I find that highly inefficient.
EDIT: To clarify. It shouldn't matter if both collections are related or not. All I want is to query from both collections like both are in one collection.
For example, if I have the following documents
// Documents in A
{ date: '2020-01-01', A_id: 1 },
{ date: '2020-01-03', A_id: 2 },
{ date: '2020-01-05', A_id: 3 },
// Documents in B
{ date: '2020-01-02', B_id: 1 },
{ date: '2020-01-04', B_id: 2 },
{ date: '2020-01-06', B_id: 3 },
Doing a query with the options .sort('date').skip(0).limit(5)
should result in the following:
// Documents in A and B
{ date: '2020-01-01', A_id: 1 },
{ date: '2020-01-02', B_id: 1 },
{ date: '2020-01-03', A_id: 2 },
{ date: '2020-01-04', B_id: 2 },
{ date: '2020-01-05', A_id: 3 },
From https://stackoverflow.com/a/55289023/3793648:
Doing unions in MongoDB in a 'SQL UNION' fashion is possible using aggregations along with lookups, in a single query.
Something like this:
db.getCollection("AnyCollectionThatContainsAtLeastOneDocument").aggregate( [ { $limit: 1 }, // Reduce the result set to a single document. { $project: { _id: 1 } }, // Strip all fields except the Id. { $project: { _id: 0 } }, // Strip the id. The document is now empty. // Lookup all collections to union together. { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } }, { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } }, { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }, // Merge the collections together. { $project: { Union: { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] } } }, { $unwind: "$Union" }, // Unwind the union collection into a result set. { $replaceRoot: { newRoot: "$Union" } } // Replace the root to cleanup the resulting documents. ]);
More details are in the post above. Adding $sort
, $skip
, and $limit
is just a matter of adding them to the aggregate pipeline. Many thanks to @sboisse!