ElP*_*nte 5 mapreduce mongodb mongodb-query aggregation-framework
我有一组文档,其中"标签"字段从空格分隔的标签列表切换到单个标签的数组.我想将以前的空格分隔字段更新为所有数组,如新的传入数据.
我也遇到了$ type选择器的问题,因为它将类型操作应用于单个数组元素,即字符串.所以按类型过滤只会返回所有内容.
如何将每个看起来像第一个示例的文档转换为第二个示例的格式?
{
"_id" : ObjectId("12345"),
"tags" : "red blue green white"
}
{
"_id" : ObjectId("54321"),
"tags" : [
"red",
"orange",
"black"
]
}
Run Code Online (Sandbox Code Playgroud)
我们不能使用$type运算符来过滤此处的文档,因为数组中元素的类型是“字符串”,如文档中所述:
当应用于数组时,$type 匹配指定 BSON 类型的任何内部元素。例如,当匹配 $type : 'array' 时,如果字段具有嵌套数组,则文档将匹配。当字段本身是数组时,它不会返回结果。
但幸运的是,MongoDB 还提供了$exists可以在此处与数字数组索引一起使用的运算符。
现在我们如何更新这些文档?
好吧,从 MongoDB 版本 <= 3.2 开始,我们唯一的选择是mapReduce()首先看看即将发布的 MongoDB 版本中的其他选择。
从 MongoDB 3.4 开始,我们可以使用$project文档并使用$split运算符将字符串拆分为子字符串数组。
请注意,为了仅拆分那些字符串“标签”,我们需要一个逻辑$cond处理来仅拆分字符串值。这里的条件是当字段的 等于时$eq评估为。顺便说一句,这是 3.4 中的新增内容。true$type"string"$type
最后,我们可以使用管道阶段运算符覆盖旧集合$out。但我们需要明确指定阶段中包含其他字段$project。
db.collection.aggregate(
[
{ "$project": {
"tags": {
"$cond": [
{ "$eq": [
{ "$type": "$tags" },
"string"
]},
{ "$split": [ "$tags", " " ] },
"$tags"
]
}
}},
{ "$out": "collection" }
]
)
Run Code Online (Sandbox Code Playgroud)
对于mapReduce,我们需要使用 来在我们的映射函数Array.prototype.split()中发出子字符串数组。我们还需要使用“查询”选项来过滤文档。从那里,我们需要 使用3.2 中的 new 方法或现在已弃用的方法(如果我们在 2.6 或 3.0 上)使用批量操作来迭代“结果”数组和“标签”的新值,如此处所示。$setbulkWrite()Bulk()
db.collection.mapReduce(
function() { emit(this._id, this.tags.split(" ")); },
function(key, value) {},
{
"out": { "inline": 1 },
"query": {
"tags.0": { "$exists": false },
"tags": { "$type": 2 }
}
}
)['results']
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2560 次 |
| 最近记录: |