Mongo 同时从 2 个集合中获取值
Mongo get value from 2 collections same time
我正在尝试从 2 个集合中获取数据,return 一个包含两个集合的合并数据的数组。
对我来说最好的解决方案是:
const bothValues = await ValueA.aggregate([
{ $unionWith: { coll: 'valueB' } },
{ $sort: { rank: -1, _id: -1 } },
{
$match: {
isAvailable: true,
},
},
{ $skip: skip },
{ $limit: 30 },
]);
效果很好。但是.. $unionWith
没有实现我的 MongoDB 版本 (4.0.X) 所以我不能使用它。
const bothValues = await ValueA.aggregate(
[
{ $limit: 1 },
{
$lookup: {
from: 'valueB',
pipeline: [{ $limit: 15 }],
as: 'valueB',
},
},
{
$lookup: {
from: 'ValueA',
pipeline: [{ $limit: 15 }, { $sort: { rank: -1, _id: -1 } }],
as: 'ValueA',
},
},
{
$project:
{
Union: { $concatArrays: ['$valueB', '$ValueA'] },
},
},
{ $unwind: '$Union' },
{ $replaceRoot: { newRoot: '$Union' } },
],
);
但是现在,我遇到了 2 个问题:
- 我不能使用
$skip
,这很重要,在哪里使用它?
- 如何使用 $match ?
谢谢
查询
- 您的查询经过一些更改后可以像第一个查询一样工作
- 在两个管道中匹配,在两个管道中排序,(limit limitN+skipN)
(这样我们确保我们总是有足够的文档,即使所有的文档都取自 valueA 或 valueB)
- 从每个中取出排序的 70 个,所以在所有方面我们将在并集后的最终 sort/skip/limit 中得到所需的 70 个。
- concat,unwind,replace-root 就像在你的查询中一样
- 再次排序(现在对并集排序),跳过,限制
- 无论我们总是有足够的文件可以跳过
- 此示例查询针对
skip=40
和 limit=30
,因此在前 2 个管道中我们 limit=70
db.ValueA.aggregate([
{
"$limit": 1
},
{
"$lookup": {
"from": "valueB",
"pipeline": [
{
"$match": {
"isAvailable": true
}
},
{
"$sort": {
"rank": -1,
"_id": -1
}
},
{
"$limit": 70
}
],
"as": "valueB"
}
},
{
"$lookup": {
"from": "valueA",
"pipeline": [
{
"$match": {
"isAvailable": true
}
},
{
"$sort": {
"rank": -1,
"_id": -1
}
},
{
"$limit": 70
}
],
"as": "valueA"
}
},
{
"$project": {
"union": {
"$concatArrays": [
"$valueA",
"$valueB"
]
}
}
},
{
"$unwind": {
"path": "$union"
}
},
{
"$replaceRoot": {
"newRoot": "$union"
}
},
{
"$sort": {
"rank": -1,
"_id": -1
}
},
{
"$skip": 40
},
{
"$limit": 30
}
])
我正在尝试从 2 个集合中获取数据,return 一个包含两个集合的合并数据的数组。
对我来说最好的解决方案是:
const bothValues = await ValueA.aggregate([
{ $unionWith: { coll: 'valueB' } },
{ $sort: { rank: -1, _id: -1 } },
{
$match: {
isAvailable: true,
},
},
{ $skip: skip },
{ $limit: 30 },
]);
效果很好。但是.. $unionWith
没有实现我的 MongoDB 版本 (4.0.X) 所以我不能使用它。
const bothValues = await ValueA.aggregate(
[
{ $limit: 1 },
{
$lookup: {
from: 'valueB',
pipeline: [{ $limit: 15 }],
as: 'valueB',
},
},
{
$lookup: {
from: 'ValueA',
pipeline: [{ $limit: 15 }, { $sort: { rank: -1, _id: -1 } }],
as: 'ValueA',
},
},
{
$project:
{
Union: { $concatArrays: ['$valueB', '$ValueA'] },
},
},
{ $unwind: '$Union' },
{ $replaceRoot: { newRoot: '$Union' } },
],
);
但是现在,我遇到了 2 个问题:
- 我不能使用
$skip
,这很重要,在哪里使用它? - 如何使用 $match ?
谢谢
查询
- 您的查询经过一些更改后可以像第一个查询一样工作
- 在两个管道中匹配,在两个管道中排序,(limit limitN+skipN) (这样我们确保我们总是有足够的文档,即使所有的文档都取自 valueA 或 valueB)
- 从每个中取出排序的 70 个,所以在所有方面我们将在并集后的最终 sort/skip/limit 中得到所需的 70 个。
- concat,unwind,replace-root 就像在你的查询中一样
- 再次排序(现在对并集排序),跳过,限制
- 无论我们总是有足够的文件可以跳过
- 此示例查询针对
skip=40
和limit=30
,因此在前 2 个管道中我们limit=70
db.ValueA.aggregate([
{
"$limit": 1
},
{
"$lookup": {
"from": "valueB",
"pipeline": [
{
"$match": {
"isAvailable": true
}
},
{
"$sort": {
"rank": -1,
"_id": -1
}
},
{
"$limit": 70
}
],
"as": "valueB"
}
},
{
"$lookup": {
"from": "valueA",
"pipeline": [
{
"$match": {
"isAvailable": true
}
},
{
"$sort": {
"rank": -1,
"_id": -1
}
},
{
"$limit": 70
}
],
"as": "valueA"
}
},
{
"$project": {
"union": {
"$concatArrays": [
"$valueA",
"$valueB"
]
}
}
},
{
"$unwind": {
"path": "$union"
}
},
{
"$replaceRoot": {
"newRoot": "$union"
}
},
{
"$sort": {
"rank": -1,
"_id": -1
}
},
{
"$skip": 40
},
{
"$limit": 30
}
])