Mongodb 在多个文档上使用$unwind

Mongodb 在多个文档上使用$unwind,mongodb,aggregation-framework,Mongodb,Aggregation Framework,这个问题-涵盖了如何在Mongo中获得一个切片。简而言之,使用聚合链来$unwind,$skip,$limit,$unwind,$skip,$limit和$group 我的问题是如何在多个文档的集合上执行此操作。我想修剪每个数组中的嵌套数组。但是,一旦I$unwind,$skip和$limit仅根据第一个数组的编号才有意义 有没有办法在集合中的每个文档上运行这种管道,而不是在整个集合上运行?我希望在聚合管道中做的事情有可能吗?使用Map Reduce显然是可能的,但这样做比单独运行对每个文档的n

这个问题-涵盖了如何在Mongo中获得一个切片。简而言之,使用聚合链来
$unwind
$skip
$limit
$unwind
$skip
$limit
$group

我的问题是如何在多个文档的集合上执行此操作。我想修剪每个数组中的嵌套数组。但是,一旦I
$unwind
$skip
$limit
仅根据第一个数组的编号才有意义

有没有办法在集合中的每个文档上运行这种管道,而不是在整个集合上运行?我希望在聚合管道中做的事情有可能吗?使用Map Reduce显然是可能的,但这样做比单独运行对每个文档的n+1查询要慢


编辑

下面是一个示例记录

{
  title: "Text Title"
  vtitle: "Text Version Title"
  text:  [[["Book1, Chapter 1, Line 1", "Book1, Chapter 1, Line 2"],["Book 1, Chapter 2, Line 1"]],[["Book 2, Chapter 1, Line 1]]]
}
这里的记录是一本大书的文本,存储为深度3数组。同一个
标题
可以有许多不同的
vtitle
,而
文本
可能相当大

我想从许多书的集合中的每本书中选择一小部分包含的文本,由索引标识——返回的每一个文档的一个片段中的一个片段

例如,
[3,3]
的输入参数将返回如下记录:

{ "text" : ["Book 4, Chapter 4, Line 1", "Book 4, Chapter 4, Line 2", ...] }

TL;DR

我认为简单的答案是你还不能真正做你想做的事。当前的选择是等到v3.1版,或者使用
聚合进行破解(但我怀疑这对于您的需要来说太慢了)

理由

虽然不太清楚您想要得到的确切结果,但其目的显然是希望能够在集合中找到一组匹配的文档,并转换(即映射)文档(通过切片嵌套数组生成一个简单的字符串列表)。搜索是不相关的,因为您可以在映射之前或之后进行搜索,并且仍然满足您的约束。因此,我将只讨论映射

这是MapReduce的一个自然用例,但您已明确将其从允许的答案中排除。因此,有3个选项,我将依次选择

1) 询问

因为您不允许多个查询,所以您唯一的选择是在请求中映射数据。这件事是通过法律来处理的。这些都行不通

  • 虽然这里有一个
    $slice
    操作符,但它不处理嵌套数组
  • $
    运算符只允许您获取数组中的第一个条目,这也不足以获取数组中的任意位置
  • $elemMatch
    仅允许从数组中获取一个字段,这也不足以满足您的需要
  • 此外,您不能在一个查询上链接投影,因此您不能以某种巧妙的方式将多个投影放在一起以多次分割数据

    简言之,这是行不通的

    2) 聚合管道

    不幸的是,在之前没有用于聚合管道的切片操作符。因此,您只能使用或可能巧妙地使用其他操作符(根据您链接的文章)

    首先使用投影操作符。虽然您可以,但目前仅限于获取尺寸。您可以尝试使用,但这本身就是无序的,因此无法在此处获取第n个条目

    因此,直接操作显然不起作用。那么我们可以增强你链接的文章吗?此解决方案仅适用于一个文档,因为您不需要区分多个文档。因此,您可以展开一个数组来创建更大的文档列表,然后使用文档级别的作用域操作来有效地进行切片

    遗憾的是,当您需要在最新的展开列表中找到下一个原始文档的开始时,这种情况就会出现。没有允许您枚举展开数组,然后在该枚举和原始文档上选择的组合

  • $unwind
    扩展数组,但不会为您提供后续匹配的索引,$skip无法跳转到具有匹配条件的下一个文档
  • $redact
    仍将您保留在原始文档的范围内,但随后会遇到与
    $project
    相同的问题,即它无法在嵌套数组上操作
  • 简言之,这也是一次失败

    3) 组聚合

    我正要放弃,这时我注意到了。您可以为匹配的文档创建一个过滤器,但随后提供一个带有
    finalize
    的任意JavaScript函数,以便在返回数据之前转换该数据。这意味着您应该能够发出如下命令:

    db.runCommand(
       {
         group:
           {
             ns: 'books',
             key: { title: 1, text: 1 },
             cond: { },
             $reduce: function (curr, result) { },
             initial: { },
             finalize: function(result) {
                 // Insert your code here to slice the array - e.g.
                 result.text = result.text[0][0]
             }
          }
       })
    

    当然,如文档所述,如果您的数据库是分片的,结果大于16MB,或者您有20000多个文档(因为每个文档现在都是聚合的关键),则此操作不起作用。当数据集变大时,速度也会非常慢。

    目前,我发现我必须运行n+1查询-1来获取文档列表,然后是每个文档的聚合管道。您的实际示例是什么?如何编辑您的问题,以显示一些示例文档和您希望实现的实际案例。这样就可以用一个例子来回答问题,而不仅仅是单词或猜测。