Mongodb 如何专注于艰难的mongo系列
我可以做一个类似于下面结构的轴心,但我不能管理Mongo 假设我们有这样一个集合:Mongodb 如何专注于艰难的mongo系列,mongodb,pivot,Mongodb,Pivot,我可以做一个类似于下面结构的轴心,但我不能管理Mongo 假设我们有这样一个集合: { "_id" : ObjectId("***"), "date" : ISODate("2018-04-02T00:00:00Z"), "parameters" : [ { "name" : "value_1", "value" : 50 }, { "name" : "value_2", "value" : 25 }, { "name" : "value_3", "value" : 2
{
"_id" : ObjectId("***"),
"date" : ISODate("2018-04-02T00:00:00Z"),
"parameters" : [
{ "name" : "value_1", "value" : 50 },
{ "name" : "value_2", "value" : 25 },
{ "name" : "value_3", "value" : 20 },
{ "name" : "value_4", "value" : 15 }
]},
{
"_id" : ObjectId("***"),
"date" : ISODate("2018-04-15T00:00:00Z"),
"parameters" : [
{ "name" : "value_5", "value" : 10 },
{ "name" : "value_3", "value" : 20 },
{ "name" : "value_1", "value" : 10 },
{ "name" : "value_6", "value" : 25 }
]}
{result :[
{
"name" : 'value1',
"2018-04-02" : {
"date" : ISODate("2018-04-02T00:00:00Z"),
"value" : 50
}
"2018-04-15" : {
"date" : ISODate("2018-04-15T00:00:00Z"),
"value" : 10
}
},....
]}
现在,我的目的是将行透视到列,以获得如下内容:
{
"_id" : ObjectId("***"),
"date" : ISODate("2018-04-02T00:00:00Z"),
"parameters" : [
{ "name" : "value_1", "value" : 50 },
{ "name" : "value_2", "value" : 25 },
{ "name" : "value_3", "value" : 20 },
{ "name" : "value_4", "value" : 15 }
]},
{
"_id" : ObjectId("***"),
"date" : ISODate("2018-04-15T00:00:00Z"),
"parameters" : [
{ "name" : "value_5", "value" : 10 },
{ "name" : "value_3", "value" : 20 },
{ "name" : "value_1", "value" : 10 },
{ "name" : "value_6", "value" : 25 }
]}
{result :[
{
"name" : 'value1',
"2018-04-02" : {
"date" : ISODate("2018-04-02T00:00:00Z"),
"value" : 50
}
"2018-04-15" : {
"date" : ISODate("2018-04-15T00:00:00Z"),
"value" : 10
}
},....
]}
这是棘手的,同时也是艰难的
所以我想创建一个对象进行迭代,创建一个表,其中的行是名称及其随时间变化的值。如果在该日期没有值,则应使用空值填充
可能是设计不好,在这种情况下,请帮助我项目的集合
谢谢
编辑
@dnickless生成的输出非常棒,但很难管理。。。
我试图重新调整聚合,但太复杂了
输出应如下所示:
{ "dates" : ["14-04-2018", "02-04-2018"],
"result" : [
{
"parameters" : [50, 10],
"name" : "value1"
},
{
"parameters" : [25, null],
"name" : "value2"
},
{
"parameters" : [20, 20],
"name" : "value3"
},
{
"parameters" : [15, null],
"name" : "value4"
}....
]}
有人能解决这个rubick多维数据集吗?虽然下面的内容可能是我写过的最可怕的聚合管道之一(而且几乎可以肯定可以由@veeram等更聪明的人进行优化),但从我所能告诉你的情况来看,它为你的示例完成了任务
db.collection.aggregate({
$group: { // this is to create an array "dates" that holds all date values
_id: "$null",
dates: { $push: "$date" },
docs: { $push: "$$ROOT" } // we remember all documents, so we can...
}
}, {
$unwind: "$docs" // basically restore the original documents again after the grouping just with the new "dates" array that holds all date values
}, {
$unwind: "$docs.parameters" // flatten the "parameters" array into individual documents
}, {
$group: { // now group all documents into buckets
_id: "$docs.parameters.name", // by the "name" field
"dates": { $first: "$dates" }, // retain the globally identical "dates" array with all dates in it
"docs": { $push: "$docs" } // remember all full documents per bucket
}
}, {
$project: {
"docs": {
$arrayToObject: { // transform the key-value pairs created below into documents
$map: { // loop through all dates
input: "$dates",
as: "this", // let the "$$this" variable point to the currently processed date
in: {
$let: { // this is to avoid duplicating the inner map stage which would otherwise be needed for the conditional handling below (see the "missing values" $cond bit)
vars: {
"arrayOrEmpty": { // create a variable "$$arrayOrEmpty" which will either hold a (single element) array or an empty array
$map: { // loop again
input: {
$filter: { // locate the element in the (single element) "docs" array
input: "$docs",
as: "that", // let the "$$that" variable point to the currently processed document
cond: { $eq: [ "$$that.date", "$$this" ] } // whose "date" field matches the date we're currently processing
}
},
as: "that",
in: {
"k": { // we create a key-value pair that will...
$dateToString : { // ...have a key like "2018-04-15" based on the date we're currently processing
format: "%Y-%m-%d",
date: "$$this"
}
},
"v": { // ...and a value that is a sub-document
"date": "$$this", // ...with the full "date" inside
"value": "$$that.parameters.value" // ...and also the "value" field
}
}
}
}
},
in: { // this is to create a null entry for missing values
$cond: [
{ $ne: [ { $size: "$$arrayOrEmpty" }, 0 ] }, // check if empty array returned by previous $map magic
{ $arrayElemAt: [ "$$arrayOrEmpty", 0 ] }, // if not then the first entry is what we want
{ // otherwise we create some dummy entry with a null value but the date fields set to what they should be set to...
"k": {
$dateToString : {
format: "%Y-%m-%d",
date: "$$this"
}
},
"v": {
"date": "$$this",
"value": null
}
}
]
}
}
}
}
}
}
}
}, {
$unwind: "$docs" // flatten the "docs" array
}, {
$addFields: {
"docs.name": "$_id", // move the "_id" field into into the "docs" sub-document
}
}, {
$sort: {
"docs.name": 1 // make sure the result is sorted by "name" (may or may not be needed)
}
}, {
$group: {
"_id": null,
"result": { $push: "$docs" } // this is just to create a "result" array as shown in your desired output
}
}, {
$project: {
"_id": 0 // get rid of "_id" field
}
})
像往常一样,使用这些管道,您可以从最后一个管道开始移除各个阶段,以了解到底发生了什么…这是一条管道
阶段1-7:获取所有唯一的名称并对其进行排序
阶段8:对于每个文档,填写缺少的值
第11阶段:按名称分组文档
第12阶段:调整结构,使之与预期结果相匹配
const pipeline = [
{
$project: {
date: 1,
parameters_: '$parameters',
parameters: 1
}
},
{
$unwind: '$parameters'
},
{
$group: {
_id: null,
names: {
$addToSet: '$parameters.name'
},
parameterUndDate: {
$addToSet: {
parameters: '$$ROOT.parameters_',
date: '$date'
}
}
}
},
{
$unwind: '$names'
},
{
$sort: {
names: 1
}
},
{
$group: {
_id: null,
names: {
$push: '$names'
},
parameters_: {
$first: '$$ROOT.parameterUndDate'
}
}
},
{
$unwind: '$parameters_'
},
{
$project: {
date: '$parameters_.date',
regularizedParameters: {
$map: {
input: '$names',
as: 'needle',
in: {
$ifNull: [{
$arrayElemAt: [{
$filter: {
input: '$parameters_.parameters',
as: 'haystack',
cond: {
$eq: ['$$haystack.name', '$$needle']
}
}
},
0
]
}, {
name: '$$needle',
value: null
}]
}
}
}
}
}
{
$unwind: '$regularizedParameters'
},
{
$sort: {
date: 1
}
},
{
$group: {
_id: '$regularizedParameters.name',
parameters: {
$push: '$regularizedParameters.value'
},
dates: {
$push: '$date'
}
}
},
{
$group: {
_id: null,
results: {
$push: {
parameters: '$parameters',
name: '$_id'
}
},
dates: {
$first: '$dates'
}
}
},
{
$project: {
_id: 0
}
}
];
db.collection.aggregate(pipeline);
再次感谢@dnickless,你是蒙哥神,但我发现我的浇注设计很难管理。你能提取一个稍微不同的文档吗?在数组中分隔日期和推送值?对不起,我的请求被卡住了。。{“日期”:[ISODate(“2018-04-02T00:00:00Z”)、ISODate(“2018-04-15T00:00:00Z”)、“结果”:[{“参数”:[50,10]、“名称”:“value1”}、{“参数”:[25,null]、“名称”:“value2”}、.]}