对多个文档使用$unwind



这个问题-在蒙古有可能得到一片切片吗?介绍了如何在蒙古获得一片切片。简而言之,对$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的数组。同一个title可以有许多不同的vtitle,并且text可以相当大。

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

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

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

;

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

理由

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

这是MapReduce的一个自然用例,但是你已经明确地从允许的答案中排除了它。所以,这里有3个选项,我将依次使用。

<<p> 1)查询/em>

由于您不允许多个查询,您唯一的选择是映射请求中的数据。这是通过投影算子处理的。

  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个文档(因为每个文档现在都是聚合的一个键),那么这将不起作用。当数据集变大时,它也很慢。

相关内容

  • 没有找到相关文章

最新更新