我使用express/nodejs(没有mongoose)和mongodb作为我的数据库。我有一个集合Pages,看起来像这样
{
_id: ..
Urls: [
{
IncomingUrl: "/test/test1",
Status: "active",
},
{
IncomingUrl: "/test/test2",
Status: "active",
}
],
DraftUrls: [
// same structure as Urls
]
//other fields which arent related to the ques
}
现在,在创建页面时,我正在查看此集合,以查找我在请求正文中提供的 urls 数组中是否有任何 url 已存在于任何现有页面文档中。
并且 如果存在重复的网址,则提供重复网址的列表作为响应。
现在我面临的问题是,如果我只需要获取计数,我可以使用像这样的查找过滤器
const filter = { $or: [
{ "Urls.IncomingUrl": { $in: urls } },
{ "DraftUrls.IncomingUrl": { $in: urls } }
] }
然后使用类似的查询
db.collection(PageCollection).find(filter).countDocuments();
它会给出重复网址的数量
但就我而言,我需要获取重复的网址而不是计数,所以如果我使用这样的东西
const duplicateUrlPages = db.collection(PageCollection).find(filter).toArray();
然后对 url 和重复的 UrlPages 运行嵌套的 for 循环,那么成本太高了。
有人可以建议我如何有效地获取任何页面文档中已存在于其 Urls.IncomingUrl 或 DraftUrls.IncomingUrl 下的输入 url 中的 url 列表
示例:
假设我的数据库中有2个这样的文档
Document1: {
// ....
Urls: [
{ IncomingUrl: "test1", status: "active" },
// ...
],
DraftUrls: [
{ IncomingUrl: "test2", status: "inactive" },
// ...
]
}
Document2: {
// ....
Urls: [
{ IncomingUrl: "test4", status: "active" },
// ...
],
DraftUrls: [
{ IncomingUrl: "test10", status: "inactive" },
// ...
]
}
我将主体提供给 POST 请求控制器函数作为
{
// ...
urls: ["test1", "test2", "test3", "test4"]
}
然后我想要一个响应数组,例如:
["test1", "test2", "test4"]
由于 test1、test2 和 test4 已经存在
这个聚合管道对我有用 但我想知道我是否可以优化这个大管道
const pipeline = [
{ $match: matchFilter },
{
$project: {
allUrls: {
$concatArrays: [
{ $ifNull: ['$Urls', []] },
{ $ifNull: ['$DraftUrls', []] }
]
}
}
},
{ $unwind: '$allUrls' },
{
$match: {
'allUrls.IncomingUrl': { $in: urls }
}
},
{
$group: {
_id: '$allUrls.IncomingUrl',
count: { $sum: 1 }
}
},
{
$match: {
count: { $gt: 0 }
}
},
{
$project: {
_id: 0,
IncomingUrl: '$_id'
}
}
];
const duplicateUrls = await collection.aggregate(pipeline).toArray();
return duplicateUrls.map(doc => doc.IncomingUrl);