如何使用MongoDB聚合将键值对字符串转换为文档
我正在使用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的字段中。现在我尝试创建一个管道,将每个字段添加到文档中。我取得了一些成功,但似乎无法将具有重复值的键放入数组中 我遇到的问题是,任何重复的键都会
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,则将值数组替换为数组的第一个值。之所以这样做,是因为如果值是单个的,则不应将其显示为数组
- 将所有键值对合并到一个数组中
- 将键值对数组转换为对象