例如,我有以下文档:
{
"addr": "address1",
"book": "book1"
},
{
"addr": "address2",
"book": "book1"
},
{
"addr": "address1",
"book": "book5"
},
{
"addr": "address3",
"book": "book9"
},
{
"addr": "address2",
"book": "book5"
},
{
"addr": "address2",
"book": "book1"
},
{
"addr": "address1",
"book": "book1"
},
{
"addr": "address15",
"book": "book1"
},
{
"addr": "address9",
"book": "book99"
},
{
"addr": "address90",
"book": "book33"
},
{
"addr": "address4",
"book": "book3"
},
{
"addr": "address5",
"book": "book1"
},
{
"addr": "address77",
"book": "book11"
},
{
"addr": "address1",
"book": "book1"
}
和/或其他信息。
我如何才能提出一个请求,该请求将描述前N个地址和每个地址的前M本书?
预期结果示例:
地址1|书册_1:5
| 书册_2:10
| 书籍_3:50
| 总数:65
地址2|书册_1:10
| 书册_2:10
|...
| 书本_M:10
| 总计:M*10
...
地址N|书册_1:20
| 书册_2:20
|...
| 书本_M:20
| 总计:M*20
4条答案
按热度按时间rryofs0p1#
TLDR摘要
在现代的MongoDB版本中,您可以使用
$slice
来强制执行此操作,而不是基本的聚合结果。对于“大型”结果,可以对每个分组运行并行查询(答案末尾有一个演示列表),或者等待SERVER-9377解析,这将允许将数组中的项的数量“限制”为$push
。MongoDB 3.6预览版
仍然无法解析SERVER-9377,但在此版本中
$lookup
允许一个新的“非相关”选项,该选项将"pipeline"
表达式作为参数,而不是"localFields"
和"foreignFields"
选项。这允许与另一个管道表达式进行“自连接”,在该管道表达式中,我们可以应用$limit
以返回“top-n”结果。这里的另一个附加功能当然是使用
$match
通过$expr
插入变量以选择“join”中的匹配项,但一般前提是“管道中的管道”,其中内部内容可以通过来自父级的匹配进行过滤。由于它们本身都是“管道”,我们可以分别对每个结果进行$limit
。这将是运行并行查询的次佳选择,实际上,如果允许
$match
并能够在“子管道”处理中使用索引,这将更好。因此,它没有像引用的问题所要求的那样使用“限制为$push
“,它实际上提供了一些应该工作得更好的东西。原始内容
你似乎无意中发现了前N个问题。从某种程度上说,你的问题很容易解决,尽管没有你要求的确切限制:
既然会给予你这样一个结果:
因此,这与您所要求的不同之处在于,虽然我们确实获得了地址值的最佳结果,但基础“books”选择并不限于所需数量的结果。
这是很难做到的,但它可以做到,虽然复杂性只会随着你需要匹配的项目的数量而增加。为了保持简单,我们可以保持最多2个匹配:
因此,这实际上会从前两个“地址”条目中为您提供前两个“书籍”。
但是对于我的钱,停留在第一个形式,然后简单地“切片”返回的数组元素,以采取前“N”个元素。
演示代码
演示代码适用于当前LTS版本的NodeJS(从v8.x到v10.x)。这主要是针对
async/await
语法,但在一般流程中没有任何真正具有此类限制的内容,只需稍加修改即可适应普通的承诺,甚至返回到普通的回调实现。索引.js
图书.json
nkkqxpd92#
使用如下聚合函数:
它将给予如下结果:
我没有完全得到您期望的结果格式,所以请随意修改为您需要的格式。
ivqmmu1c3#
以下查询将提供与所需响应中给出的结果完全相同的结果:
响应如下所示:
tpxzln5u4#
从mongoDB 3.6版本开始,这就很容易做到了,使用
$group
、$slice
、$limit
和$sort
:$group
这些书来数它们$sort
,因此稍后将根据计数推送它们$group
乘以address
,$push
相关书籍,以及$sum
每个地址的总数。$sort
按地址总计$limit
地址结果为topN
1.使用
$slice
将数组中的图书限制为topM
了解它在playground example-v3.4上的工作原理
在mongoDB版本5.2上,有一个
topN
累加器,可以简化更多:了解它在playground example-v5.2上的工作原理