Javascript Can';当$$ROOT没有结果时,t组。(MongoDB)
我正在尝试对一些搜索结果进行评分/排名 一般来说,这是有效的: (Javascript Can';当$$ROOT没有结果时,t组。(MongoDB),javascript,mongodb,mongoose,aggregation-framework,Javascript,Mongodb,Mongoose,Aggregation Framework,我正在尝试对一些搜索结果进行评分/排名 一般来说,这是有效的: (userid这里是一组表示我们想要评分/排名的用户的id,SomeModel包含与这些用户相关联的资产,这些用户为我们提供了排序标准。) ……但事实并非如此。如果我现在查看我的结果,我只会得到[] 我已尝试更改$group步骤,以检查以下内容: {$group: { //make these an array so we can merge it.... _id:0,
userid
这里是一组表示我们想要评分/排名的用户的id,SomeModel
包含与这些用户相关联的资产,这些用户为我们提供了排序标准。)
……但事实并非如此。如果我现在查看我的结果,我只会得到[]
我已尝试更改$group
步骤,以检查以下内容:
{$group: { //make these an array so we can merge it....
_id:0,
origin: {
$push :{
$cond:{
if: {$eq:[{$size : '$$ROOT'}, 0]},
then: [null],
else: '$$ROOT'
}
}
}
}},
…但随后出现错误“$size的参数必须是数组,但类型为:object”
正确的方法是什么?为了清楚起见,我想创建一个容器对象,将管道中该点上的结果作为字段origin
中的数组保存。(然后,我可以将它们与我开始使用的完整列表连接起来,并获得一个正确的排序列表)
如果管道当前包含结果,则此操作有效,但如果不包含结果,则组步骤不执行任何操作
所需输入/输出:
我的问题特别是$group
阶段,因此我将重点关注这一点
示例1:
此示例使用上述代码正常工作
输入:
[ {ownerId: <ID A>, score: 234}, {ownerId: <ID B>, score: 265}]
[]
实际输出:匹配
示例2:
此示例无法正确使用上述代码
输入:
[ {ownerId: <ID A>, score: 234}, {ownerId: <ID B>, score: 265}]
[]
$group
期望输出:
[{
_id:0,
origin:[ {ownerId: <ID A>, score: 234}, {ownerId: <ID B>, score: 265}]
}]
[{
_id:0,
origin:[]
}]
实际产量:
[]
聚合管道的概念是,在执行管道时,MongoDB将操作器彼此连接起来。这里的“管道”具有Linux的含义:操作符的输出成为以下操作符的输入。每个操作员的结果是一个新的文档集合。在上面的示例中,Mongo按如下方式执行管道:
collection | $match | $group | $project => result
这意味着如果$match
步骤不匹配管道中具有给定条件的任何文档,Mongo将不会进一步管道化任何内容,因此您将得到一个空结果,因为管道以$match
结束,它不会进一步
但是,您可以做的是在$group
管道中注入条件,但是如果集合较大,则会导致性能下降。这是因为$group
步骤将处理集合中的所有文档,而不是通过使用$match
将符合条件的文档作为第一优先级返回,从而减少进入管道的文档数量
使用此路由,将您的<代码> $组<代码>阶段作为条件的第一个流水线步骤:
[
{ "$group": {
"_id": 0,
"origin": {
"$addToSet": {
"$cond": [
{ "$in": ["$ownerId", userIds] },
"$$ROOT", null
]
}
}
} },
{ "$project": {
"origin": {
"$filter": {
"input": "$origin",
"as": "el",
"cond": { "$ne": ["$$el", null] }
}
}
} }
]
不同场景的确切请求输出是什么?更新以提供示例。我明白了-这很有意义。考虑到这一点,我可以在最后检测这个案例,并在mongo之外构建我自己的结果列表(因为我只是在列表中的每个id中添加'score:0',我想这会比为每个id分组更有效)。最好的选择是继续使用当前管道,但检查结果数组是否为空。您可以将所需的最终文档推送到该空数组,例如
if(result.length==0)result.push({u id:0,origin:[])代码>有没有可能在周围的管道阶段的上下文中显示这一点?我不知道你可以像那样内联操作结果而不终止管道。如果我能看到你在这里说的话,我会接受这一点——听起来好像我遗漏了一些有价值的东西。我的意思是在执行管道之后,当承诺解决时,即在阶段SomeModel.aggregate([…])。然后(results=>{if(result.length==0)result.push({u id:0,origin:[{score:0}]);})代码>