这个问题-在蒙古有可能得到一片切片吗?介绍了如何在蒙古获得一片切片。简而言之,对$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>由于您不允许多个查询,您唯一的选择是映射请求中的数据。这是通过投影算子处理的。
- 虽然这里有一个
$slice
操作符,但它不处理嵌套数组。 -
$
操作符只允许您获取数组中的第一个条目,这也不足以在数组中获得任意位置。 -
$elemMatch
只允许您从数组中获得一个字段-这也不足以满足您的需求。
此外,您不能在查询上链接投影,因此您不能以某种巧妙的方式将多个投影放在一起以多次切片数据。
总之,这行不通。
2)聚合管道
不幸的是,直到v3.1版本才有用于聚合管道的切片操作符。因此,您被限制在$project或可能狡猾地使用其他操作符(根据您链接的文章)。先取投影算子。虽然可以对数组字段进行操作,但目前仅限于获取大小。你可以尝试使用集合逻辑,但那本质上是无序的,所以你无法得到这里的第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,或者您有超过20,000个文档(因为每个文档现在都是聚合的一个键),那么这将不起作用。当数据集变大时,它也很慢。