Reputation: 3423
Is it possible to do this in MongoDB ?
select id, title from posts
union all
select id, name from programs
sort by title asc;
I would like to sort documents from two distinct collections, and treat the result as one collection. Please help.
Added
In fact, I am doing a text search, but I want to search on 2 collections and merge the results:
My express route handler looks like this:
// Post and Program are a Mongoose models
function (req, res) {
const criteria = req.params.criteria
Promise.all([
Post
.find({$text: {$search: criteria}}, { title: 1, score: { $meta: 'textScore' }})
.sort({ score: { $meta: 'textScore' } })
.exec(),
Program
.find({$text: {$search: criteria}}, { title: 1, score: { $meta: 'textScore' }})
.sort({ score: { $meta: 'textScore' } })
.exec()
])
.then(results => reply([...results[0], ...results[1]]))
.catch(err => handle(err))
}
I know I can manipulate the results array like I want with lodash
, but the problem is that I must display the results page by page, so on each request I should fetch the number of document displayed per page.
If I go for lodash
, then I will always fetch all data from the DB, then choose the right page with lodash
. It will be more efficient to fetch just what is needed.
So I am hoping there is a way to do something like this:
Post
.find({$text: {$search: criteria}}, { title: 1, score: { $meta: 'textScore' }})
.unionAll(
Program
.find({$text: {$search: criteria}}, { title: 1, score: { $meta: 'textScore' }})
)
.sort({ score: { $meta: 'textScore' } })
.limit(10)
.exec()
I know I am dreaming, but it can make sense. So is there a way to do get that results from MongoDB, or do I have to manage it with lodash or something like.
Upvotes: 1
Views: 57
Reputation: 46481
You can try with $facet
and $lookup
aggregation
db.collection.aggregate([
{ "$limit": 1 },
{ "$facet": {
"c1": [
{ "$lookup": {
"from": Post.collection.name,
"pipeline": [
{ "$match": { "$text": { "$search": criteria }} },
{ "$project": { "title": 1 }}
],
"as": "collection1"
}}
],
"c2": [
{ "$lookup": {
"from": Program.collection.name,
"pipeline": [
{ "$match": { "$text": { "$search": criteria }} },
{ "$project": { "name": 1 }}
],
"as": "collection2"
}}
]
}},
{ "$project": {
"data": {
"$concatArrays": [ "$c1", "$c2" ]
}
}},
{ "$unwind": "$data" },
{ "$replaceRoot": { "newRoot": "$data" } }
])
Upvotes: 1