I need the first part of $or
(or equivalent query) to be resolved first and to make sure that the first query is always part of the result.
Must use query, not aggregation.
[
{ "docId": "x1" },
{ "docId": "x2" },
{ "docId": "x3" },
{ "docId": "x4" },
{ "docId": "x5" },
...
{ "docId": "xn" },
]
Query:
{
'$or': [ { docId: 'x434' },{} ],
}
I need x434
to be part of the query result, regardless of all other results.
Expected result:
[
{ docId: 'x434' },
{ docId: 'x12' },
{ docId: 'x1' },
...
]
Return:
[
{ docId: 'xn' },
{ docId: 'xn' },
{ docId: 'xn' },
...
]
Results by x434
is not always returned
I tried $or
and $and
queries but nothing worked. I tried regex
too
{
'$or': [ { docId: 'x434' },{} ],
}
CodePudding user response:
So the solution can only be an aggregation:
$match: {
'$or': [ { docId: 'x434' },{} ],
},
$addFields: {
order: {
$cond: [
{
$in: [
"$docId",
['x434']
]
},
0,
1
]
}
},
$sort: {
order: 1
},
$limit: 20
Result:
{ docId: 'x434' },
{ docId: 'x12' },
{ docId: 'x1' },
...
]```
CodePudding user response:
A straightforward solution can use $facet
:
db.collection.aggregate([
{$facet: {
allOther: [{$match: {docId: {$ne: "x434"}}}, {$limit: 19}],
wanted: [{$match: {docId: "x434"}}]
}},
{$project: {data: {$concatArrays: ["$wanted", "$allOther"]}}},
{$unwind: "$data"},
{$replaceRoot: {newRoot: "$data"}}
])
See how it works on the playground example
CodePudding user response:
You can use $unionWith
. It's behaviour is similar to UNION ALL
in SQL so you can persist x434 at the start. Remember to exclude x434 in the $unionWith
pipeline to avoid duplicate if needed
db.collection.aggregate([
{
$match: {
"docId": "x434"
}
},
{
"$unionWith": {
"coll": "collection",
"pipeline": [
// exclude x434 to avoid duplicate
{
$match: {
"docId": {
$ne: "x434"
}
}
}// put your other queries here
]
}
}
])