Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用MongoDB聚合将键值对字符串转换为文档_Mongodb_Aggregation Framework - Fatal编程技术网

如何使用MongoDB聚合将键值对字符串转换为文档

如何使用MongoDB聚合将键值对字符串转换为文档,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我正在使用MongoDB聚合管道,试图看看是否可以使用它来解析以下格式的文件 FIELD1:ABC FIELD2:DEF ... FIELD12:YZ RowData:__ __ 01 __ __ RowData:__ 02 01 01 __ RowData:__ __ 03 __ __ 我已经将文件流直接插入mongo文档中名为fileStream的字段中。现在我尝试创建一个管道,将每个字段添加到文档中。我取得了一些成功,但似乎无法将具有重复值的键放入数组中 我遇到的问题是,任何重复的键都会

我正在使用MongoDB聚合管道,试图看看是否可以使用它来解析以下格式的文件

FIELD1:ABC
FIELD2:DEF
...
FIELD12:YZ
RowData:__ __ 01 __ __
RowData:__ 02 01 01 __
RowData:__ __ 03 __ __
我已经将文件流直接插入mongo文档中名为fileStream的字段中。现在我尝试创建一个管道,将每个字段添加到文档中。我取得了一些成功,但似乎无法将具有重复值的键放入数组中

我遇到的问题是,任何重复的键都会被最后一个值覆盖

通过这个管道,我得到了一个数组数组,元素0是键,元素1是值。因此,当我使用$arrayToObject时,只有最后一个字段保留用于重复键

db.maps.aggregate([
  {
    $addFields: {
      'rows':
      {
        $map:
        {
          input: {
            // Sinf Rows
            $filter: {
              input: { $split: ['$fileStream', '\r\n'] },
              as: 'row',
              cond: { $ne: ['$$row', ''] }
            }
          },
          as: 'row',
          in:
            {
              $split: ['$$row', ':']
            }
        }
      }
    }
  }
]).pretty()
此管道已关闭,但RowData元素未包含在数组中

db.maps.aggregate([
  {
    $addFields: {
      'rows':
      {
        $map:
        {
          input: {
            // Sinf Rows
            $filter: {
              input: { $split: ['$fileStream', '\r\n'] },
              as: 'row',
              cond: { $ne: ['$$row', ''] }
            }
          },
          as: 'row',
          in:
            {
              $cond: [{ $eq: [{ $arrayElemAt: [{ $split: ['$$row', ':'] }, 0] }, 'RowData'] }, { $arrayElemAt: [{ $split: ['$$row', ':'] }, 1] }, { $split: ['$$row', ':'] }]
            }
        }
      }
    }
  }
]).pretty()
我想将任何重复的密钥组合到同一个数组中

像这样的

"file": 
{
"FIELD1": "ABC"
...
"RowData": 
[
"__ __ 01 __ __",
"__ 02 01 01 __",
"__ __ 03 __ __"
]
}

我可以使用reduce在js中实现这一点,但如何使用聚合$reduce将数据累积到数组或对象中?

以下查询可以获得预期的输出:

db.maps.aggregate([
    {
        $project:{
            "file":{
                $reduce:{
                    "input":{
                        $split:["$fileStream","\n"]
                    },
                    "initialValue":{
                        "elements":[]
                    },
                    "in":{
                        "elements":{
                            $concatArrays:[
                                "$$value.elements",
                                [
                                    {
                                        $let:{
                                            "vars":{
                                                "splitted":{
                                                    $split:["$$this",":"]
                                                }
                                            },
                                            "in":{
                                                "k":{
                                                    $arrayElemAt:["$$splitted",0]
                                                },
                                                "v":{
                                                    $arrayElemAt:["$$splitted",1]
                                                }
                                            }
                                        }
                                    }
                                ]
                            ]
                        }
                    }
                }
            }
        }
    },
    {
        $unwind:"$file.elements"
    },
    {
        $group:{
            "_id":{
                "_id":"$_id",
                "element":"$file.elements.k"
            },
            "k":{
                $first:"$file.elements.k"
            },
            "v":{
                $push:"$file.elements.v"
            }
        }
    },
    {
        $addFields:{
            "v":{
                $cond:[
                    {
                        $gt:[
                            {
                                $size:"$v"
                            },
                            1
                        ]
                    },
                    "$v",
                    {
                        $arrayElemAt:["$v",0]
                    }
                ]
            }
        }
    },
    {
        $group:{
            "_id":"$_id._id",
            "file":{
                $push:{
                    "k":"$k",
                    "v":"$v"
                }
            }
        }
    },
    {
        $project:{
            "file":{
                $arrayToObject:"$file"
            }
        }
    }
]).pretty()
数据集:

{
    "_id" : ObjectId("5d73c530f04b490307453cfe"),
    "fileStream" : "FIELD1:ABC\nFIELD2:DEF\nRowData:__ __ 01 __ __\nRowData:__ 02 01 01 __\nRowData:__ __ 03 __ __"
}
{
    "_id" : ObjectId("5d73c530f04b490307453cfe"),
    "file" : {
        "RowData" : [
            "__ __ 01 __ __",
            "__ 02 01 01 __",
            "__ __ 03 __ __"
        ],
        "FIELD2" : "DEF",
        "FIELD1" : "ABC"
    }
}
输出:

{
    "_id" : ObjectId("5d73c530f04b490307453cfe"),
    "fileStream" : "FIELD1:ABC\nFIELD2:DEF\nRowData:__ __ 01 __ __\nRowData:__ 02 01 01 __\nRowData:__ __ 03 __ __"
}
{
    "_id" : ObjectId("5d73c530f04b490307453cfe"),
    "file" : {
        "RowData" : [
            "__ __ 01 __ __",
            "__ 02 01 01 __",
            "__ __ 03 __ __"
        ],
        "FIELD2" : "DEF",
        "FIELD1" : "ABC"
    }
}
说明:

{
    "_id" : ObjectId("5d73c530f04b490307453cfe"),
    "fileStream" : "FIELD1:ABC\nFIELD2:DEF\nRowData:__ __ 01 __ __\nRowData:__ 02 01 01 __\nRowData:__ __ 03 __ __"
}
{
    "_id" : ObjectId("5d73c530f04b490307453cfe"),
    "file" : {
        "RowData" : [
            "__ __ 01 __ __",
            "__ 02 01 01 __",
            "__ __ 03 __ __"
        ],
        "FIELD2" : "DEF",
        "FIELD1" : "ABC"
    }
}
  • 将文件流转换为元素数组。每个元素都有一个键值对
  • 对键进行分组,并将键的所有值推送到一个数组中
  • 如果大小仅为1,则将值数组替换为数组的第一个值。之所以这样做,是因为如果值是单个的,则不应将其显示为数组
  • 将所有键值对合并到一个数组中
  • 将键值对数组转换为对象

哇,谢谢!我花了一段时间才完成这项工作,但第一个小组阶段非常重要。我在reduce输入中添加了一个过滤器,以消除文件`$filter:{input:{$split:['$fileStream','\r\n']}中的任何空行,如:'row',cond:{$ne:['$$row',''']}`