在多个文档上使用$ unwind

莱泽

这个问题-在Mongo中可以切成薄片吗?讲述了如何在Mongo中获得一小片。总之,使用聚合链$unwind$skip$limit$unwind$skip$limit,和$group

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

有没有一种方法可以在集合中的每个文档上而不是整个集合上运行这种管道?我希望在聚合管道中完成所有工作吗?使用Map-Reduce显然是可能的,但是这样做比分别对$unwind每个文档运行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相同的可能有很多不同title,并且text可能很大。

我想从许多书籍的集合中的每本书中选择一小部分包含文本的内容,这些内容由索引标识-返回的每个文档的一部分。

例如,输入参数[3,3]会返回类似以下的记录:

{ "text" : ["Book 4, Chapter 4, Line 1", "Book 4, Chapter 4, Line 2", ...] }
彼得·布里顿

TL; 博士

我认为简短的答案是您还不能真正做到自己想要的。当前的选择是等到v3.1或通过group聚合对其进行破解(但是我怀疑这对于您的需求而言太慢了)。

理由

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

这是MapReduce的自然用例,但是您已明确将其排除在允许的答案之外。因此,我将依次介绍3个选项。

1)查询

由于您不允许多个查询,因此唯一的选择是在请求中映射数据。这是通过投影运算符处理这些将不起作用。

  1. 虽然这里有一个$slice运算符,但它不处理嵌套数组。
  2. $运营商只允许你参加一个数组,这也不足以阵列中获得一个任意位置的第一个条目。
  3. $elemMatch只允许你从数组中获得一个领域-这也不足以满足您的需求。

另外,您不能在查询上链接投影,因此不能以某种狡猾的方式将多个投影放在一起以多次切片数据。

简而言之,这是行不通的。

2)聚合管道

不幸的是,直到v3.1才存在用于聚合管道的分片运算符因此,您仅限于$ project或其他运算符的狡猾用法(根据您链接的文章)。

首先使用投影算子。虽然您可以对数组字段进行操作,但现在只能获取大小。您可以尝试使用集合逻辑,但是本质上是无序的,因此您无法在此处获得第N个条目。

因此,直接操作显然不起作用。那么,我们可以改善您链接的文章吗?该解决方法仅适用于一个文档,因为您无需区分多个文档。因此,您有能力展开数组以创建更大的文档列表,然后使用文档级范围操作有效地进行切片。

可悲的是,当您需要在最新的展开清单中查找下一个原始文档的开头时,此方法会下降。没有运算符的组合,您无法枚举展开的数组,然后选择该枚举和原始文档。

  1. $unwind 扩展数组,但没有给您索引以供您随后进行匹配,并且$ skip无法提供跳至具有匹配条件的下一个文档的方法。
  2. $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或您有超过20,000个文档(因为每个文档现在是聚合的关键),那么这将不起作用。当数据集变大时,它也非常慢。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用$ unwind保持文档聚合

在我创建的列表上使用UNWIND返回多个值(密码)

在嵌套数组上使用$ unwind的后果?

非理想嵌套文档的 mongodb $unwind

没有$ unwind的$ lookup多个级别?

mongo查询中的多个$ unwind和$ group

方向更改后在Unwind Segue上崩溃

在mongodb中的多个嵌套数组中使用unwind

选择不使用$ unwind(猫鼬聚合)

如何在Golang中使用$ unwind?

MongoDB:使用$ unwind进入$ lookup管道

使用 unwind segue 返回上一页

我试图在 $unwind 之后返回嵌套文档的完整列表

在$ unwind之前检查子文档是否为空

$unwind 嵌入文档中存在的多个数组,并将每个数组显示为单个文档作为 mongoDB 中的输出

Cypher UNWIND'ing并将多个标签应用于节点

C#MongoDB:在$ unwind之后查询数组上的$ match

mongo $ sum在执行$ unwind然后在多个字段上执行$ group时会复合

如何在 Swift 3 中使用 unwind(for: UIStoryboardSegue,comingViewController: UIViewController)?

如何在使用cypher与UNWIND进行迭代时删除关系

将-fno-unwind-tables与-fno-exceptions结合使用

在Golang和MongoDB中使用$ lookup和$ unwind的请求很慢

什么是Unwind segues,您如何使用它们?

与UISearchController一起使用unwind segue时出错

使用 $unwind 获取空数组作为聚合结果

如何在密码查询中使用 UNWIND 后的条件

在聚合框架mongodb中使用$ unwind和$ text

MongoDB 使用 group 和 unwind 计数出现次数

当节点已存在时,使用NEO4J中的UNWIND创建多个节点